4

Let's say I have a mobile app, android/iOS and a java Spring back end. Given the mobile connectivity, the number of network round trips must be limited, ideally, 1 or less per screen.

Now, let's say I want to add/rewrite some messaging capabilities when 2+ app users can send each other messages.

There are 2 tables / resources (simplified here). 'Conversation' and 'Message'. Each conversation contain multiple messages.

conversation 
-----------------
id 
type 
last_message_test
last_message_username
message_count
etc

message
------------
id
conversation_id 
user_id
user name 
text
timestamp 

The conversation records contain some information about the latest message that took place in it so that a screen listing just the header of many conversations can show its latest content without having to query the actual message table (also the message count).

ideally there would be calls like this:

POST /api/conversation                                 => create a new conversation 
POST /api/conversation/1234/message                    => post a new message in conversation 1234
GET  /api/conversation?searchparam1=1&searchparam2=2   => retrieve certain conversation without their full actual content
GET  /api/converstaion/1234/message                    => retrieve all the messages of a given conversation, 1234

Here are the problems though:

problem A) When positing a new message, this creates a new message resource but their is also the side effect of an (async / messaging) update on the corresponding 'conversation' record. So POSTing a new resource of typeA triggers a PATCHing of another resource of typeB. Is that OK?

problem B) When positing the first message, there isn't yet a conversation record. Both must be created, first the 'conversation' record, then the 'message' record that will contain the new conversation ID (ideally in a transaction). How to do that in a rest way without having to do 2 api calls?

Basically trying to find the right compromise between:

  • number of rest calls
  • duplicated db fields and queries
  • rest style of resource-oriented API

Maybe it's not really possible without adding some sort of artificial new resources or 'batch / bundle / aggregate' operations / end points? any recommendations appreciated, thanks!

  • That one field in the conversations table should be "last_record_text" (not "last_message_test") right? – Tim Grant Aug 2 '16 at 23:21
6

Problem A) Yes, that's fine. RESTful POSTs are permitted to generate side effects on other resources. I'd suggest breaking out messages from conversations in your URI hierarchy in this case, or allowing clients to POST a message resource to /conversations to create a new conversation. It could respond with a Conversation Message with a "self" URI pointing to the newly created conversation and message.

Problem B) When you POST a new message, if it doesn't contain a conversation ID, have your service layer start a transaction that creates a new conversation, then creates the message with the conversation id. Your response from that POST can contain the conversation id for future calls.

I think that part of your problem is conflating a database table with a resource. It's often the case that the database model and resource model should be different, and I think this is a good example.

If you want to be able to update the screen in one call, figure out what information needs to be in the response to that call. Make that your resource. Clients can POST to /messages and get a response back containing something that isn't a message.

What REST is trying to push you towards is a state machine, where the resources are states, the requests are the inputs that determine which transition you make, and the response contains the new state after you complete the transition.

Unrelated but maybe helpful - it is a (loose) standard to use plurals for collection resources, so I would expect to see /conversations and /messages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.