REST and CQRS (again without the arguments please) .....

254 views
Skip to first unread message

Polemann

unread,
Feb 13, 2011, 1:44:43 PM2/13/11
to DDD/CQRS
Firstly, apologies for any REST people out there who find my example
confusing I'm trying to understand.

I'm interesting in using rest principles and links combined with a
CQRS system but I'm not sure how commands etc fit in. Using an example
of an CQRS Shopping Cart system which has commands like
(AddItemToShoppingCart,ReplaceItemInCart,
RemoveItemFromCart ,CheckoutShoppingCart) how would you approach the
design of URL paths etc. The confusing bits are as follows:

1.CQRS splits the commands and queries but rest PUTs etc always result
in a value being returned. Does this mean we can't really combine the
concepts. I don't think rest support eventual consistency concepts.
2.If we allow Commands to be HTTP puts then that seems to violate the
rest concepts of posting back an entire representation


3. Whats interesting to me is the links. I would love to allow a
client to be able to ask for the cart and get the current possible
links for the current user.

GET http://www.acart.com/customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/

Returns:

<cart>
<created>2011-Jan-10 00:00:00 UTC</created>
<customer>blah b</customer>
<total>123.00 USD</total>
<products>
<id=1 qty=2 total='13.00 USD'>
<id=2 qty=1 total='110.00 USD'>
</products>

<links>
<dap:link rel="http://www.acart.com/AddItemToShoppingCart"
mediaType='application/vnd/acart+xml' uri="http://www.acart.com/
customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/
AddItemToShoppingCart/>
<dap:link rel="http://www.acart.com/ReplaceItemInShoppingCart"
mediaType='application/vnd/acart+xml' uri="http://www.acart.com/
customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/ReplaceItemInCart/>
</links>
</cart>










Polemann

unread,
Feb 13, 2011, 2:20:34 PM2/13/11
to DDD/CQRS

Rickard Öberg

unread,
Feb 14, 2011, 12:05:19 AM2/14/11
to ddd...@googlegroups.com
On 2011-02-14 02.44, Polemann wrote:
> I'm interesting in using rest principles and links combined with a
> CQRS system but I'm not sure how commands etc fit in. Using an example
> of an CQRS Shopping Cart system which has commands like
> (AddItemToShoppingCart,ReplaceItemInCart,
> RemoveItemFromCart ,CheckoutShoppingCart) how would you approach the
> design of URL paths etc. The confusing bits are as follows:
>
> 1.CQRS splits the commands and queries but rest PUTs etc always result
> in a value being returned. Does this mean we can't really combine the
> concepts. I don't think rest support eventual consistency concepts.

REST does not say that a "PUT" always result in a value being returned,
since REST doesn't talk about "PUT" at all (it's an implementation
detail when using HTTP). I use PUT/POST/DELETE all the time for
commands, and they either return nothing apart from a success code, or
the list of events that were caused by the command (I do synchronous
processing).

> 2.If we allow Commands to be HTTP puts then that seems to violate the
> rest concepts of posting back an entire representation

Where did you get this constraint from? I've never heard about that before.

> 3. Whats interesting to me is the links. I would love to allow a
> client to be able to ask for the cart and get the current possible
> links for the current user.
>
> GET http://www.acart.com/customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/

<snip>

That is how I do it, and it works great for me. Note that the
/ReplaceItemInCart should support at least GET and POST though (GET to
retrieve the form for it, and POST to send it).

/Rickard

alexis

unread,
Feb 14, 2011, 5:06:11 AM2/14/11
to DDD/CQRS
On 14 fév, 06:05, Rickard Öberg <rickardob...@gmail.com> wrote:
> On 2011-02-14 02.44, Polemann wrote:

> REST does not say that a "PUT" always result in a value being returned,
> since REST doesn't talk about "PUT" at all (it's an implementation
> detail when using HTTP). I use PUT/POST/DELETE all the time for
> commands, and they either return nothing apart from a success code, or
> the list of events that were caused by the command (I do synchronous
> processing).

Yes, but it should not be the same success code (204 instead of 200 if
you don't want to return anything).

[...]

alexis

unread,
Feb 14, 2011, 5:42:41 AM2/14/11
to DDD/CQRS
On 13 fév, 19:44, Polemann <sco...@reynoldsphotography.com> wrote:
> Firstly, apologies for any REST people out there who find my example
> confusing I'm trying to understand.
>
> I'm interesting in using rest principles and links combined with a
> CQRS system but I'm not sure how commands etc fit in. Using an example
> of an CQRS Shopping Cart system which has commands like
> (AddItemToShoppingCart,ReplaceItemInCart,
> RemoveItemFromCart ,CheckoutShoppingCart) how would you approach the
> design of URL paths etc. The confusing bits are as follows:
>
> 1.CQRS splits the commands and queries but rest PUTs etc always result
> in a value being returned. Does this mean we can't really combine the
> concepts. I don't think rest support eventual consistency concepts.
> 2.If we allow Commands to be HTTP puts then that seems to violate the
> rest concepts of posting back an entire representation
>
> 3. Whats interesting to me is the links. I would love to allow a
> client to be able to ask for the cart and get the current possible
> links for the current user.
>
> GEThttp://www.acart.com/customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/
>
> Returns:
>
> <cart>
> <created>2011-Jan-10 00:00:00 UTC</created>
> <customer>blah b</customer>
> <total>123.00 USD</total>
> <products>
>    <id=1 qty=2 total='13.00 USD'>
>    <id=2 qty=1 total='110.00 USD'>
> </products>
>
> <links>
>     <dap:link rel="http://www.acart.com/AddItemToShoppingCart"
> mediaType='application/vnd/acart+xml' uri="http://www.acart.com/
> customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/
> AddItemToShoppingCart/>
>    <dap:link rel="http://www.acart.com/ReplaceItemInShoppingCart"
> mediaType='application/vnd/acart+xml' uri="http://www.acart.com/
> customer/4d36e97b-e325-11ce-bfc1-08002be10318/cart/ReplaceItemInCart/>
> </links>
> </cart>

It depend on what problem you are trying to solve by making the update
of the cart asynchronous. Because if you look at amazon, the cart is
updated synchronously (the order is processed asynchronously, but it's
not the same thing).
So if there is no good reason to make updates of the cart
asynchronous, you should use PUT/POST/DELETE/... on your cart resource
and use the pending order pattern for example when you want to commit
it (http://bitworking.org/news/201/RESTify-DayTrader)
If there is a problem of scalability (but updating a cart is not as
resource intensive as processing an order and there is no concurrency
problems with it because only one customer owns it), maybe you should
create and update the cart client side (and use the pending order
pattern when you want to commit), with Web SQL Db, Web Indexed Db,
LocalStorage, FlashStorage, Cookies, ... there are a lot of techniques
to persist the cart client-side (but maybe the customer will "loose"
his cart when it will connect with a different browser)

I think the biggest mismatch between REST and CQRS is the design of
uris, using differents uris for add/replace methods instead of using
methods on a ressource, you will have problems if you want to use
cache (PUT/POST/DELETE on a resource clean the cache for example).

Greg Young

unread,
Feb 14, 2011, 8:50:49 AM2/14/11
to ddd...@googlegroups.com
Your day traders would also have you commit hari kari if you brought
in the kinds of latencies that tend to exist with rest based systems
(high latency/high through put). Not that its a bad set of
non-functional requirements but certainly not acceptable for traders
:) Consider the example he has with retries. If placing an order times
out then retry ... how long is the time out? Would you really want to
retry like that when $ is in question? Most of the time with a real
stock market you are talking < 100ms latency across a WAN... my guess
is he can't even open a TCP socket in that time.

--
Les erreurs de grammaire et de syntaxe ont été incluses pour m'assurer
de votre attention

Jimmy Bogard

unread,
Feb 14, 2011, 8:52:45 AM2/14/11
to ddd...@googlegroups.com
So why not just use XML-RPC?  It's still using the building blocks of the web (HTTP etc).  I suppose you don't get any geek points for if the API isn't REST, but does it really matter for your system?

It's an approach we took in several of our external integration points.  We never talked about REST, just about our HTTP API.  As for design, we went something along the lines of /resource/command, so you'd see something like /cart/AddItem or /cart/ReplaceItem etc.

Thanks,

Jimmy

alexis

unread,
Feb 14, 2011, 10:21:31 AM2/14/11
to DDD/CQRS
On 14 fév, 14:50, Greg Young <gregoryyou...@gmail.com> wrote:
> Your day traders would also have you commit hari kari if you brought
> in the kinds of latencies that tend to exist with rest based systems
> (high latency/high through put). Not that its a bad set of
> non-functional requirements but certainly not acceptable for traders
> :) Consider the example he has with retries. If placing an order times
> out then retry ... how long is the time out? Would you really want to
> retry like that when $ is in question?
> Most of the time with a real
> stock market you are talking < 100ms latency across a WAN... my guess
> is he can't even open a TCP socket in that time.

I'm not sure to understand your reply. If for a POST on "pending
order", the server write to its MOM and reply with a 202 Accepted,
could this solve the problem ?

Greg Young

unread,
Feb 14, 2011, 10:26:48 AM2/14/11
to ddd...@googlegroups.com
You need to know completion status in ms. Also trading systems just
don't work as shown in that example. Basically they built a toy app to
solve a set of non-functional requirements that will never exist (both
in the original and the port). EG for viewing orders/quotes/etc data
is pushed not pulled.

Chris Nicola

unread,
Feb 15, 2011, 1:39:52 PM2/15/11
to ddd...@googlegroups.com
Jimmy, I do think it is a bit of a derailment to start talking about XML-RPC when he is asking about implementing REST.  In the end XML-RPC and REST are different for numerous reasons and I think it best to avoid a discussion like "why not do something different"  or at least start an XML-RPC vs REST discussion somewhere else, though I realize you are just asking him to think about his needs.  Arguably discussions about how to implement REST probably belong in a REST discussion group too, but I digress...


First, I would probably suggest that the decision to apply REST principles in your API design are largely an orthogonal issue to your choice to use CQRS within the API.  You can choose to expose your commands and even your events via REST if you want or need to but you certainly don't have to.  Where REST and CQRS have synergies is that REST is quite typically about exposing the client's use cases via HTTP and Hypermedia endpoints, while CQRS is about creating a task-driven UI, which essentially means exposing your use cases via your Commands and service bus.  So there is definitely a lot of synergy there, but your context will dictate how you use it.

As an example, if you were using REST to do a PUTs for your Commands, then your first responsibility is to make sure the PUT call is safe and idempotent.

Again with REST you have numerous options for what to do when the command is handled, as Rickard said, these are implementation details, not rules.  You could:

1. Return ACCEPTED and a representation of a Resource (remember REST is about resources) which represents the state of the Command result:

ACCEPTED
{
  commandId: 24
  status: "Processing"
}

This would be useful for longer running commands where consistency may take some time

2. Return OK or even CREATED (depending on the context) and simply return a representation of the the result that is important to the client, this is an option if you choose to process the command in synchronously or nearly synchronously (very high consistency) way or if you know what the result will be ahead of time.  In this case it is important to know the command executed successfully (that the event happened) but not necessarily that the events were handled and denormalized.

 e.g., I have an event that creates a new aggregate root, I may return CREATED and a de-normalized representation of that Aggregate Root as my Resource.

Finally, my disclaimer: I don't claim to be a REST or CQRS expert at this point in time.  These represent some of the things I've found while working with both and some of the options I have considered as I develop the API.  I'm sure my thoughts and ideas will change as I continue to learn.

Reply all
Reply to author
Forward
0 new messages