Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How best to implement link relations for HATEOAS in XML?

We have a Java server web application where the core of the system contains a very complex domain model that was designed according to the principles of domain driven design. For the most part, these domain objects have been affectly very little by the applications other concerns.

We are now looking to put a REST web services API in front of the system and I am struggling with how to best implement the HATEOAS links that come within our own new media type. For example, lets say we have domain class foo that has an id and name properties with JAX-B annotations:

@XmlType(name = "foo")
public class FooImpl implements Foo {

    private String name;
    private String id;

    ...snip....

@XmlID
@XmlAttribute
@Override
public String getId() {
    return id;
}

    @XmlElement
    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(final String name) {
        this.name = name;
    }
}

But the XML I want to return looks like this:

<foo id="123" href="http://myserver.com/foos/123">
   <name>myFoo</name>
   <links>
          <link rel="previous" href="http://myserver.com/foos/122" type="application/mything+xml" />
          <link rel="next" href="http://myserver.com/foos/124" type="application/mything+xml" />
          <link rel="edit" href="http://myserver.com/foos/123" type="application/mything+xml" />
          <link rel="revise" href="http://myserver.com/foos/123" method="put" type="application/mything+xml" />
          <link rel="cancel" href="http://myserver.com/foos/123?op="cancel"" method="post" type="application/mything+xml" />
   </links>
</foo>

What is the best way to do this such that I do not have pollute my domain design with these media type links, but can still use the power of JAX-B for XML marshalling? Here are some thoughts:

1) JAX-B Adapters - could I use these to modify the XML for the entities and insert the links..is it possible? is it reasonable? Any examples?

2) DTO Layer - Create a new REST service layer that converts my domain objects in DTOs. So far we been able to avoid the hassle of DTOs. While this would provide total flexibility in what we return to the client, I am also not looking to create domain agnostic clients here.

3) Link Headers - I really like this idea, but I don't think it would work (by itself) because sometimes our resources contain collections of sub-resources. In this case the subresources would still have to be marshalled into XML that contains links/hrefs, etc. So while link headers solves the problem to the top level type, it doesn't solve the entire problem. Feel free to say otherwise!

Is there another approach that will help me avoid DTOs and yet remain transparent to the domain model?

like image 541
HDave Avatar asked Nov 05 '22 07:11

HDave


1 Answers

The problem is that correctly generating the links requires knowing the context within which they are being generated, which in turn means that simple JAXB interceptors won't do the job: they simply won't know what URL to insert. What's more, generating the next and previous links will require knowing what those values are; it's probably not safe to say that they are consecutive, as that would imply a resource changing its URL when some other resource is deleted, which would be madness.

The safest, easiest method is going to be a wrapper class (with JAXB serialization annotations on it) which delegates to the DAO layer for the information it needs. While this can be a fair amount of code to write, it's at least easy to get such code right. Fancy automated decoration will be much harder.

like image 158
Donal Fellows Avatar answered Nov 09 '22 09:11

Donal Fellows