Rickard Oberg is popular among Java developers. He has given seminars at all main Java conferences world wide. He worked as an architect at JBoss and other popular OpenSource Java frameworks, and wrote a book on RMI. In recent years, he has become famous as an Aspect Oriented Programming (AOP) crusader. He has worked with bleeding edge AOP in a portal product that has become a great commercial success, and is currently working on Qi4j at Jayway. Rickard is a DZone MVB and is not an employee of DZone and has posted 16 posts at DZone. You can read more from them at their website. View Full User Profile

The Domain Model as REST Anti-pattern

12.08.2010
| 14554 views |
  • submit to reddit

Today JavaLobby published yet another domain-model-as-REST article, using Spring and Jersey. As already pointed out, this really is an anti-pattern, and is not RESTful, and cannot be so either.

The point that all of these types of articles miss is the HATEOAS part, the hyperlinking of resources. If you expose your domain model, basically saying "here's all I got, use as you see fit", there is no sensible way to create links between resources that expose the application state. There is no sensible way to tell the client "here's what you can do next", because the "REST" API allows anything at any time.

Here's an example, from my own app, which showed me the problem with this approach. I have users in my system. I need two ways to work with their passwords: the user must be allowed to change his own password, and the administrator shall be allowed to reset any users' password. In the beginning, when I was exposing my domain model, the URL's for this were as follows:

/user/<username>/changepassword
/user/<username>/resetpassword

I'm just doing what the article suggests, which is to expose my domain model, and all that I can do with it. What's the problem with this? The first and most obvious problem is that it's very hard to determine who is allowed to do what here. I need to have authorization checks on both "changepassword" and "resetpassword". The first needs to check if it is the same user that accesses it, and the second needs to check if the accessing user has the administrator role. Also, since the client MUST get to these resources by following links in hypermedia (that's a constraint, remember?), the most obvious thing to do is to list them when accessing /user/<username>/. But then my link lists need to do these authorization checks as well, because if the user is not an administrator, then the "resetpassword" link should not be there. I should not allow clients to see links they cannot reasonably follow! My UI will also be quite complicated, because in one screen I might do "resetpassword" and a number of other administrative tasks, each of which uses different parts of the domain model, and so its exposure to the API, and consequently, its brittleness if the API changes, is immense. It's just a very bad situation, and one which you'll get into by following the guidelines in all of these expose-your-domain-model articles.

So what to do instead? The trick is to expose usecases instead. It's that simple. Now, the main problem with doing this is that you have to actually know what your usecases are! And this is probably why all of these articles do the domain-model anti-pattern: because of their simplified nature they only thought to the point of "we gotta have users in our system" and not take the next step "what can we do with them?", because then you need to decide a whole lot more about what your system does. Since articles need to be reasonably focused on one thing, they just don't go there. But for You, if you do that, you end up with the mess outlined above.

What did we do in our REST API to fix the above? We simply looked at our usecases, and rearranged the REST API accordingly. For the above, they relate to two different usecases which are account handling and user administration. And so we changed the API to something like this:

/account/changepassword
/administration/users/<username>/resetpassword

If a client goes to /account/, which it can do by first going to "/" and finding that link, it will receive a list of links with what you can do on your own account, such as "changepassword". Do a GET on that link, and the client gets a form with two fields: the old password and the new password. The client might show this as three fields though, with a duplicate new password field to ensure that the user typed it correctly. The client can then POST to "changepassword" to make the actual change. I don't have to make any authorization checks, since the client is implicitly accessing its own account, so there's no way to screw it up, even deliberately. For the admin side, the client browses to /administration/users/ (and again, that link was retrieved from "/" if the user is an administrator), lists/searches the users, gets the link to a particular user, do a GET on "resetpassword" to get the form for it, and then fills it in and POST it to make the change. The REST API has at all times told the client what it is allowed to do, by using hypertext to drive the application state. This is what HATEOAS means in practice, and it is VERY helpful if you expose your usecases, and VERY annoying if you expose your domain model (simply because you can't). This approach also removes the issue outlined in the article with circular references, simply because in usecases, there are no circular references.

Another effect of this is that links in the REST API will almost always be relative, since all they do is guide the client further into a usecase, or sub-usecase. If you expose domain models you have to have absolute links, and they will be going here there and everywhere, exposing the internal associations between entities. It's stupid beyond belief, but this is what pretty much all of the current articles on "RESTful" frameworks tell you to do. And I say: DON'T! It'll only bring you misery.

From a security point of view the above is also easier to work with. Now all I have to do is add a check on "/administration/" for the administrator role, and after that the user can do anything below that point. No need to duplicate that check everywhere (and no need to use aspects to get around this annoyance)!

Now that you know what to do, the next question might be: how to do it? The problem here is that since all the current "REST" frameworks haven't thought HATEOAS through, they don't really allow you to make REST API's for your applications, and so, they will not be very easy to use. You have to work against them. This goes for Jersey and friends as well, as they don't allow this usecase approach to URL parsing. What we have done in my project, Streamflow, is to create our own wrapper on top of Restlet. Restlet provides an excellent base for REST applications, but is too low-level to have to deal with in the application code. By putting a thin wrapper on top of it, which understand the notion of usecases and links, we have been able to really reduce the amount of code needed to do all of this.

Here's sample code for "change password". The code uses a routing technique, so in order to get to /account/changepassword, the framework first takes "/" and finds a resource for that. This resource then knows how to get to "/account/", which in turn knows how to get to "changepassword". The code looks like this:

public class RootResource
      extends CommandQueryResource
{
   @SubResource
   public void account()
   {
      subResource( AccountResource.class );
   }
...
}

When the client hits "/" the framework will automatically look at this class, and present hypermedia (JSON or HTML at this point, but Atom Services is also an option) for it. The client clicks "/account/", which leads to this:

 

public class AccountResource
   extends CommandQueryResource
{
   public AccountResource( )
   {
      super( AccountContext.class );
   }

   @SubResource
   public void profile()
   {
      subResourceContexts( ProfileContext.class, ContactableContext.class );
   }
}

To find out what the client can do on this level you look in AccountContext. If you want to continue further down into the profile handling of an account (setting email, phone, etc.) the client would follow "/account/profile/" link that is presented. In our case, let's look at AccountContext:

 

public class AccountContext
{
   public void changepassword( ChangePasswordCommand newPassword )
         throws WrongPasswordException
   {
      UserAuthentication user = RoleMap.role( UserAuthentication.class );

      user.changePassword( newPassword.oldPassword().get(), newPassword
            .newPassword().get() );
   }
}

It exposes one interaction on this level of the usecase, which is /account/changepassword. The parameter tells the framwork what it requires as input, so if the client does GET it can look at the ChangePasswordCommand value object and present it as a form. If the client does a POST the framework parses the input into the value object and invokes the method, allowing it to "do it's thing". In this case it looks up the UserAuthentication role, which is a Qi4j mixin that our user entity implements. This entity was registered automatically by the authentication filter, so I don't have to look it up. For the administration usecase the code would get access to the "<username>" part of the URL so that it can locate the user from the repository.

And that's pretty much it. Not only is this easier to work with for clients (who simply follow links in hypermedia), but the code in both client and application is also absolutely trivial. I can also find out what my REST API looks like in total by starting with RootResource and explore the API by clicking on the classes it references. Since the API is so deterministic given these classes I can also generate documentation automatically that basically says, "given your user authorization level, here are all the resources you can access in the API". In particular, when your API becomes hypermedia driven like this, what you want to expose as documentation is the set of "rel" attributes that the client must know, in this case "account" and "changepassword". What the URL's look like is none of the clients business! It should just go to "/" and follow links based on the "rel" attribute of those links. Then you can say that your API is "RESTful". Until you do that, no, you may have a "web API" or a "HTTP API", but it aint REST.

There are more details in how this works, and how to turn links on/off depending on internal state, but the gist of how to think is as above.

From http://www.jroller.com/rickard/entry/the_domain_model_as_rest

Published at DZone with permission of Rickard Oberg, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

cowwoc replied on Thu, 2010/12/09 - 1:26pm

Rickard,

 

I'm sorry to say but your example is completely wrong. REST is all about exposing data, not commands. The very fact that you expose /account/changepassword shows how wrong this is.

 

Ironically, your example *is* a REST anti-pattern.

Stephane Vaucher replied on Thu, 2010/12/09 - 2:48pm in response to: cowwoc

I think you are mistaking a common misuse of the term REST with its accepted use. Please read what the inventor of REST thinks of exposing data.

Rickard Oberg replied on Sat, 2011/01/01 - 12:32am

@cowwoc, I use queries and commands as the way to build my REST API, but this is not something a client has to actively understand. All commands and queries follow the constraints of REST, to the letter. For example, multiple HTTP verbs can be used when accessing query and command resources (e.g. GET on command produces it's form, and HEAD on query produces the metainfo about that query). What truly separates this approach from the domain model version is that it becomes trivial to expose hypermedia links, as they are all relative and are used to inform the client how to drive the application, which is something a domain based API simply cannot do.

Thomas Kern replied on Thu, 2012/09/06 - 10:59am

Thanks for this insightful writeup.

There's one missing link in my understanding of the HATEOAS concept and your article. You mention "clicking" and exposing links to show clients possible actions. This is intuitive for HTML, but how does that look like in practice when returning JSON or another machine-readable format?

Also, how can a programmatic client decide which of several links to follow? Is the intention that a human first explores the available links, and then hardwires the navigation paths in the programmatic client?

http://www.java-tips.org 

Antanas Bastys replied on Tue, 2014/03/18 - 7:19pm in response to: Thomas Kern

Maybe this answer is a little bit late but you can see how Spring Tutorial describes HATEOS usage with JSON's here https://spring.io/guides/tutorials/rest/6/. Keep in mind that they fallow "resource" approach rather then "user story" approach described here.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.