Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to model parent-child entities via REST and JAX-RS

Tags:

rest

jax-rs

I am working on a REST based API, and having some trouble figuring out what the canonical way is to represent parent / child relationships. (I am writing beans in CXF and using JAX-RS and JAXB. I started from the basic example provided by CXF)

My problem is let's say you have a Foo and a Bar. There is a 1-N relationship with Foo and Bar, that is 1 Foo has many Bars. My question is, what's the canonical way to find out what Bars a Foo has? And what's the canonical way to access Bar resources owned by the Foo?

I have figured out that for example I might list Foos at:

GET http://xxx/fooservice/foos

And operate on a single foo at:

PUT/UPDATE/DELETE http://xxx/fooservice/foo/{fooid}

But how do I list Bars that Foo 121 has? And how do I access them? I've noticed that it seems the default JAXB marshaller doesn't output Collections just attributes for a bean, so if a Foo is:

Foo
  - String id
  - String name
  - Collection bars

JAXB outputs something like:

<foo><id>123>/id><name>foo name</name></foo> <-- note the absence of the bars attribute

Which is problematic, as there is no way for the client to reasonably be expected to know that Foo has Bars, unless it "just knows" (which seems bad to me). So while I can imagine to get a list of bars using:

GET http://xxx/fooservice/foo/121/bars

How does a client know that Foo has Bars if the output of the entity doesn't say anything about it? Now presuming the client does get the list, then it seems entity operations would be something like:

GET/DELETE/UPDATE http://xxx/fooservice/foo/121/bar/435

which would access Bar 435 owned by Foo 121.

like image 570
Taylor Gautier Avatar asked Dec 29 '22 10:12

Taylor Gautier


1 Answers

What you want to do is certainly possible. One way of designing the resources is:

/foo
          # A list of all the Foo resource names (not representations).

/foo/{fooid}
          # A detailed representation of a particular Foo, including 
          # a list of all that Foo's Bar resource names (not representations).

/foo/{fooid}/bar/{barid}
          # A detailed representation of a particular Bar.

You may have a situation where the Bars have no real existence outside of a particular Foo (as in a purchase order's master and the detail rows it contains). If this is the case, and each Foo hasn't got all that much Bar data to go with it, you could return the full Bar details right in the Foo representation:

/foo
          # A list of all the Foo resource names (not representations).

/foo/{fooid}
          # A detailed representation of a particular Foo, including 
          #   full details on each of its Bars.

You generally want coarser granularity with REST resources. Note that if you choose this, then to modify a Foo's Bars, you'd GET the Foo, modify the Bars in the Foo representation, and then PUT the Foo.

Not sure what's happening with your serialized XML representations, you should create a second question with the relevant code.

like image 92
Jim Ferrans Avatar answered Dec 31 '22 23:12

Jim Ferrans