How to model child objects of parent type through REST and JAX-RS

I am working on a REST-based API and have some problems figuring out what the parent / child relationships will represent. (I write beans in CXF and use JAX-RS and JAXB. I started with the basic example provided by CXF)

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

I realized that, for example, I can list Foos at:

GET http: // xxx / fooservice / foos

And work with one foo at:

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

But how do I list the bars that Foo 121 has? And how do I access them? I noticed that apparently the JAXB marshaller by default does not only display the Collections attributes for the bean, so if Foo:

  Foo
   - String id
   - String name
   - Collection bars

JAXB outputs something like:

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

Which is problematic, as the client has no reasonable reason to believe that Foo has bars, unless it β€œjust doesn't know” (which seems bad to me). Therefore, although I can imagine, to get a list of bars using:

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

How does the client know that Foo has bars if the output of the object says nothing about it? Now, assuming that the client is actually getting the list, then it seems that operations with the entity will look something like this:

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

which will gain access to Bar 435 owned by Foo 121.

+4
source share
4 answers

What you want to do is of course possible. One way to develop resources:

/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 Bar resource names (not representations). /foo/{fooid}/bar/{barid} # A detailed representation of a particular Bar. 

You may have a situation where the bars do not have a real existence outside of a certain Foo (as is the case with the purchase order wizard and the detail lines contained in it). If so, and each Foo lacked so much data about the bars that you could return full information about the bars directly in the Foo view:

 /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 usually want coarser granularity with REST resources. Note that if you select this and then change the Foo Bars, you must GET Foo, change the Bars in the Foo view, and then PUT Foo.

Not sure what is happening with your serialized XML views, you should create a second question with the appropriate code.

+10
source

Thanks for the detailed post - what you are describing is basically what I do already, without a detailed presentation of the bars inside each Foo, as you suggest, so it seems that I had it mostly correctly.

I will find out why the Bars collection inside Foo does not get unmarshalled as XML in JAXB in a separate Q, as you suggest.

0
source

Taylor, the JAX-RS implementation in Jersey, certainly emits the properties of a list of objects that he converts to XML or JSON. Therefore, in the application that I just finished, the UserStore object has a user property that List:

 List<User> users = new ArrayList<User>(); 

When I use Jersey to emit a version of UserStore XML or JSON, I get an array of users for this property:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <users> <user> <firstName>John</firstName> <id>a29a377f-4329-4ec8-9459-b5b1c2efc38a</id> <lastName>Doe</lastName> </user> <user> <firstName>Jane</firstName> <id>bb4dad28-1263-440a-afc5-062a8566ef90</id> <lastName>Roe</lastName> </user> </users> 

and

 { "user": [{ "firstName": "John", "id": "a29a377f-4329-4ec8-9459-b5b1c2efc38a", "lastName": "Doe", }, { "firstName": "Jane", "id": "bb4dad28-1263-440a-afc5-062a8566ef90", "lastName": "Roe", }] } 

Perhaps the problem you're encountering is simply because your property is an assembly, not a list ...

0
source

for me this question the answer will depend on the data modeling, and for data modeling the question is "use a composite key for the child model or not" if it uses a composite key, so you need to put the parent identifier in the URI if not, but the child has your own id, which is not compound, so you can just use the URL with a child id.

so this is a data modeling issue !!!

0
source

All Articles