We are using CQRS and REST(/HATEOAS) in my project, with great success.
Here's what we do:
Each path ending with "/" represents a selection in the UI. It could be
"/organizationalunit/123/" for a particular item, or
"/organizationalunit/123/projects/" for some particular aspect on that
item. The client always start by doing a GET on that resource, and
receives back a JSON description for that resource which contains:
1) List of queries
2) List of (available) commands
3) List of (available) subresources
4) Index data
The list of commands is typically used to enable/disable
buttons/menuitems/popups. The client essentially know what it is allowed
to do. Whether a command is there or not could be because of application
state, but it could just as well be based on user roles. The client
doesn't have to care: if command "x" is in the resource description,
enable button "x", otherwise not.
The list of subresources is typically used to drive a tabbed pane. The
component will map the subresources to views, and instantiate them as
tabs. Same as above, some tabs may not always be available because of
roles, and so the client doesn't have to understand this: it just
creates tabs for the links it finds.
The index data itself is what will be used to display information about
the resource. We try to use generic DTO's such as Link and Links
(serialized to JSON) as much as possible, and have client components
that knows how to "render list of links", "select from a list of links",
and so on.
Commands are represented as "/organizationalunit/123/commandname". You
can do GET on it for a form that shows what parameters it needs, and
with default values filled in. You POST to it to send the command.
Conneg is supported, either with headers or .json/.html/.atom suffixes.
The URL's look kinda pretty :-)
Whenever we can we try to not let the client know about how to invoke a
particular command. Instead it will first do a GET on a query to get a
set of links, display those to a user, and when a link is selected the
client POSTS to it without "knowing" what the link looks like.
Example: for a project we want to be able to add users to it. Project
itself goes here:
/projects/123/
and member list:
/projects/123/members/
A GET on that will show the current list of members, and a link to a
query "possiblemembers". A GET on that returns a list of links, each
named with the usernames of users not yet in the project, and links
pointing to "addmember?entity=someusername". The list is shown to the
user, and when a link is selected the client POST's it, without having
to know about e.g. "addmember" being a command. This allows evolution of
the REST API without having to change the client, which is kinda neat.
We also use ETags and lastmodified timestamps for optimistic locking.
Works quite well.
This is the gist of it. One more important detail is that the REST API
should expose your *usecases* and not the domain model. We got this
wrong the first time (as do most projects/blogs/articles I've seen), and
it was really bad until we realized to structure our API according to
the usecases in the client, at which point everything became supersimple
and logical. I wrote about this here:
http://www.jroller.com/rickard/entry/rest_api_for_infrastructure_domain
Code for the above can be found here:
http://waybuild.gotdns.com/nexus/content/repositories/snapshots/se/streamsource/streamflow/
Take a look at the "streamflow-web" module, and start from RootResource
to see the REST API. Framework for server+client is in "streamflow-dci"
module.
/Rickard
a clueless question:
i thought CQRS allowed for some arbitrary delay between the write
side's changes getting out to the read side, and that mostly it was a
one-way pipe. (people have asked before about how to e.g. show the
newly added item in the shopping cart right away instead of possibly
having some unknown delay and a "your cart will be updated shortly"
message.) how does my (mis)understanding fit with REST? seems like
with REST the command's results need to be known and returned right
away, rather than going through the write->read->ui delayed path?
sincerely.
The result must be returned right away, but it may be an 202 ACCEPTED
instead on an 201 CREATED, for example.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
> sincerely.
Best regards,
Daniel Yokomizo
That's one way to do it.
> (people have asked before about how to e.g. show the
> newly added item in the shopping cart right away instead of possibly
> having some unknown delay and a "your cart will be updated shortly"
> message.) how does my (mis)understanding fit with REST? seems like
> with REST the command's results need to be known and returned right
> away, rather than going through the write->read->ui delayed path?
In our version the command is processed synchronously and the list of
events (or the error if it failed) is returned to the client, at which
point it can do a refresh of its view. We update our snapshot and graph
querying index synchronously with the request (which is what we need for
the main views), and RDBMS and search engine (Lucene) asynchronously.
There's a ton of options here, and only you can decide what's right in
your case. Just know about what the options and tradeoffs are.
/Rickard
It's difficult to comment more, since I've never yet tried your
approach, but it just seems so right on so many levels. I look forward
to trying it sometime, hopefully sooner than later.
Cheers,
=David
Rickard, you are my idol! (*-*)/
It's difficult to comment more, since I've never yet tried your approach, but it just seems so right on so many levels. I look forward to trying it sometime, hopefully sooner than later.
Cheers,
=David
On Oct 27, 2010, at 9:32 AM, Rickard Öberg wrote:
On 2010-10-27 05.37, Polemann wrote:
I've been reading a few posts on rest-discuss and I'm really confused.
I thought, and still think, that rest and CQRS is a great mix. When
you ask me for a resource I will provide you with the list of commands
that you can call on that resource and specify its URLs etc.
Does anyone have a good rest / cqrs sample they could point me too or
event just discuss how you used HATEOS to describe how you post
commands to resources.
We are using CQRS and REST(/HATEOAS) in my project, with great success. Here's what we do:
Each path ending with "/" represents a selection in the UI. It could be "/organizationalunit/123/" for a particular item, or "/organizationalunit/123/projects/" for some particular aspect on that item. The client always start by doing a GET on that resource, and receives back a JSON description for that resource which contains:
1) List of queries
2) List of (available) commands
3) List of (available) subresources
4) Index data
The list of commands is typically used to enable/disable buttons/menuitems/popups. The client essentially know what it is allowed to do. Whether a command is there or not could be because of application state, but it could just as well be based on user roles. The client doesn't have to care: if command "x" is in the resource description, enable button "x", otherwise not.
If you have a specific question, sure. Otherwise it's kind of hard to
know where to start. It's a huge topic.
/Rickard
Best regards,
Rinat Abdullin
Technology Leader at Lokad.com | Writer at Abdullin.com | Contacts
Something like that. Based on the policy of the object being accessed,
and the user accessing it, you present links based on that
(authorization). The links that is provided to the client gets enabled
in the client UI, and the rest are not shown or are greyed out.
For banks, there might be several types of users accessing a bank
account, and some may be allowed to see balance, some may be allowed to
make payments, and some may be allowed to make transfers. Different sets
of links are provided, and the client just reacts to it.
> Are you returning the structure of your commands in the payload as
> well or just via links. If I was to use an xml appraoch I woulc
> imagine that I woul just supply an XSD that had the command format in
> it for people to consume.
In my case the client gets the set of links. Either I have preprogrammed
the client to "know" what to supply when POSTing to it, or the client
first does a GET on it to get fields that needs to be filled in and then
fill in what it knows and POST it. Or a more dynamic client might
present the fields to the user dynamically to be filled in. Very similar
to how a browser would. In fact, your client will become more and more
like a browser as you continue down this path, as you get more
hypermedia-driven.
/Rickard