JAXB REST PUT'ting referenced association - java

Consider the following entity classes:
Manufacturer: represents a car manufacturer (Ford, Volvo, ...) and has a name.
Model: represents a model (Fiesta, S80), has a name, and is manufactured by a single manufacturer.
The manufacturer field in the model is annotated as follows:
#ManyToOne
#XmlIDREF
private Manufacturer manufacturer;
I then have two REST resources defined for getting and putting both manufacturers and types. The problem is with putting types:
#PUT
#Consumes("application/xml")
public void putModel(JAXBElement<Model> model) {
modelFacade.create(model.getValue());
}
and the XML I try to put:
<model>
<name>Fiesta</name>
<manufacturer>1</manufacturer>
</model>
The manufacturer element points to 1, a valid instance of Manufacturer, however, when the Model is persisted, the MANUFACTURER_ID is null. How can I get JAXB to read the manufacturer's ID from the XML as well?
Thanks!

Consider adding a hyperlink to the manufacturer instead of an ID (to make it more RESTful). See this e-mail from the users#jersey mailing list which has an example of that.

The following answer I gave to a similar question may help. It makes use of an XmlAdapter to convert the referenced object to/from an ID:
Serialize a JAXB object via its ID?
To leverage this in a JAX-RS environment to create a RESTful service you will need to leverage a MessageBodyReader in order to set an instance of EntityManager on the XmlAdapter passed to the Unmarshaller.

Related

Firestore - set a POJO field to the ID of the collection of a query

I know this is a very specific ask but I've got a situation where it would be very nice to have my custom class deserialized and have the collections parent ID set to a specific field. I know with the #DocumentId annotation we can do this for the documents own ID, is there some SDK method to extend this for my use case?
public class MyCustomClass {
#DocumentId public documentID;
...
#<insert magic here> public documentsCollectionsParentID
So for example, something like /users/<uid>/docs/<docid>, I already have the functionality for documentID to be set automatically to docID, but I'd like documentsCollectionsParentID set to uid. Is this in any way possible at the moment?
My current alternative is to deserialize, and the the object afterword:
MyCustomClass thing = (MyCustomClass)doc.toObject(MyCustomClass.class);
thing.setDocumentsCollectionsParentID(doc.getReference().getParent().getParent().getId())
Unfortunately, there is no method in Firebase that does that automatically. This is Java limitation and you are doing it correctly by deserializing the object.

Domain class vs. Dto class vs. naming for Swagger

I have a case where my hibernate Customer object needs to be a little bit different then the one exposed in my rest api, so I am using the dto pattern.
So, the rest api uses the CustomerDto object and the internal object is just Customer correct? Kind of OCD, but I'd rather have Swagger show it as "Customer" vs. "CustomerDto", no?
Is there a way to change the class name that Swagger shows, akin to #JsonProperty?
You can use the #ApiModel Swagger annotation for that. Just annotate your DTO class with:
#ApiModel(value = "Customer")

Restrict JSON attributes for #RequestBody

This may be a simple task, but I couldn't find a way to do it. Basically, I need to disallow some parameters at the time of using #RequestBody annotation in my controller.
Here is my model:
#Data
public class MyModel {
private int id;
private String name;
}
What I want to do is at the time of response, I want both of the properties to be serialized to JSON, but at the time of create or update, I prefer not to receive id as part of #RequestBody deserialization.
Right now, if I pass id in the JSON body, Spring initializes a MyModel object with its id set to the passed value.
Reason? The ID cannot be generated until the model is created, so the app shouldn't allow the ID to be set. On update, the ID needs to be passed in the URL itself e.g. (PUT /mymodels/43). This helps following the REST principles appropriately.
So, is there any way to achieve this functionality?
Update 1:
Right now, I am stuck with using a request wrapper. I created a new class MyModelRequestWrapper with only name as its property, and have used it with the #RequestBody annotation.
How you do this depends on what version of Jackson you are using. It's basically possible by a combination of the annotations #JsonIgnore and #JsonProperty on relevant fields/getters/setters.
Have a look at the answers here: Only using #JsonIgnore during serialization, but not deserialization

What data type should be used to reference serialized objects by ID?

I have a bunch of classes that will be instantiated and passed between my JS front-end and Spring MVC.
I'm using Simple to serialize my object as XML for persistent storage and Jackson to pass it to my UI as JSON. Consequently I need to have an ID attribute that is used to reference an object, and this needs to be consistent in both the JSON, POJO and XML.
This means I need an ID attribute in my Java class. What type should I declare it as? I've seen int being used in the Simple library tutorial and I've also seen UUID being used here.
The Simple library creates id and ref attributes (or any other that you provide) to maintain references:
<parent name="john" id="1">
<children>
<child id="2" name="tom">
<parent ref="1"/>
</child>
</children>
</parent>
The accompanying Java to read it back in:
Strategy strategy = new CycleStrategy("id", "ref");
Serializer serializer = new Persister(strategy);
File source = new File("example.xml");
Parent parent = serializer.read(Parent.class, source);
The id isn't in the original Java object however, so it won't be passed with the JSON to the UI. Should I define a private UUID uid; and pass that, while also letting Simple generate the auxiliary id and ref attributes it uses, or is there a way to use a single Java attribue to do both?
EDIT: Hibernate has an #Id annotation, but I can't find something similar for Simple. Will this do?
#Attribute
private int id;
The problem is that I'll need to instantiate and pass it as JSON, but it needs to be unique as well (meaning it'd be easier to use UID). Also, will Simple use this id for its ref?
EDIT 2:
Using id as an attribute and then using the CycleStrategy causes it to use the value you define from the class and not the internal ones it uses in the XML which the ref point to... I'm using two attributes for now - a uuid I generate together with the id Simple uses internally.

RESTful 1-N optional relationships

I trying to learn how to write RESTful apps in Java using Jersey and
Hibernate, and I'm struggling to understand how to handle parent/child type
relationships when POSTing data to a Resource. I'm using JSON to exchange
data, but I don't think that's particularly relevant to my problem.
The example I'm working with models the relationship between employees and
teams. An employee may, or may not, be a member of one team:
GET /team/ - returns a list of teams
POST /team/ - creates a new team
GET /team/1 - returns a list of employees in the team with the ID 1
GET /employee/ - returns a list of employees
POST /employee/ - creates a new employee
GET /employee/1 - returns details about the employee with the ID 1
Behind this I have some Hibernate annotated POJOs: one for team, and one
for employee, with a 1-N relationship between the two (remember that an
Employee may not be a member of a team!). The same POJOs are also annotated
as #XmlRootElements so that JAXB will allow me to pass them to/from the
client as JSON.
The properties for the two entities look like this:
Team
Long id;
String name;
String desc;
List<Employee> employees;
Employee
Long id;
Team team;
String name;
String phone;
String email;
All good so far. But I'm struggling to understand how to make an employee
a member of a team at creation-time by just passing in a Team ID, rather
than passing in a nested team object in my JSON object.
For example, I'd like to be able to call POST /employee/ with a JSON that
looks like this:
{
"team_id":"1",
"name":"Fred Bloggs",
"phone":"1234567890",
"email":"test#example.com"
}
But, instead, I have to pass in something like this:
{
"team":{
"id":"1",
}
"name":"Fred Bloggs",
"phone":"1234567890",
"email":"test#example.com"
}
So, my question is, how do others handle creating relationships in JSON/REST without passing around whole object graphs?
Sorry this is such a sketchy question, but as I say, I'm just starting
out, and terminology is a problem for me at this stage!
If your framework forces your representation to include strange constructs like { "id":"1" } then I'd say it's time to switch framework!
More importantly, instead of worrying about adding a sub-JSONObject to your code, I would worry that the term "1" is indeed not really a hyperlink. Read up on the hypermedia constraint, or HATEOAS if you want.
What you want to pass in your POST is this:
{
"team_href" : "/teams/1",
"name":"can'tbebothered"
}
so when the server sees this, it links the newly created employee with team #1 merely because it recognises the (relative) URI.
I would use a dedicated link type, I modelled it in xml-link tag, but it would map to following json:
{
...
links:
[
{
"href" : "/teams/1",
"rel" : "team"
},
{
"href" : "/teams/2",
"rel" : "team"
}
]
}
I prefer above link style because it is more generic (you define the relationship through the rel attribute). To me the link concept is so important in HTTP REST that I dedicate an own type for it.
Beware in some cases for performance reasons (avoiding network calls to traverse linked resource) you need to inline such relationships. For that you could offer a switch to return a inlined representation /employee/123?inline=true. But only offer such gimmicks, if really necessary. I once had to do it, but implementation wasn't trivial (though my format was XML, which is more constrained by schema definitions).
REST offers the possibility to use URLs as references, too, which I find really cool. So it would look like this:
{
"team":"http://myapp.com/team/1",
"name":"Fred Bloggs",
"phone":"1234567890",
"email":"test#example.com"
}
You can avoid passing nested objects, too by just supplying a
{
"team":"1",
"name":"Fred Bloggs",
"phone":"1234567890",
"email":"test#example.com"
}
In that case your converter must be smart enough to figure that if the value of the team key is a string (or integer, whatever works) and not another JSON object it should be interpreted as an id.
There are multiple ways to approach a solution for this problem. Its a class hyperlinking problem in the domain of RESTful Web Services. Since this has to do with Jersey the first thing I would recommend is to avoid JAXB all together since JAXB (in context of XML or JSON) ain't HATEOAS.
After dwindling a lot with Jersey and HATEOAS I have come to the opinion that the best representations for a RESTful WS is Atom Syndication Format coupled with JSON. For your example of Team and Employee I would take the following approach.
GET /team/ - returns a paginated Atom Syndication Feed list of teams
POST /team/ - creates a new team receiving a JSON representation
GET /team/1 - returns a paginated Atom Syndication Feed list of employees in the
team with the ID 1 with an Link to team's JSON representation too.
GET /employee/ - returns a paginated Atom Syndication Feed list of employees
POST /employee/ - creates a new employee using JSON
GET /employee/1 - returns details about the employee with the ID 1 in JSON
Till here I haven't change much just specifying some representation details. The interesting part is adding/removing an employee from a team. For this I would add resources with pattern
#Path("/team/{id}/employees)
class TeamEmployees {
#Path("/{posId}")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Employee get(#PathParam("posId") int positonId) {}
#Path("/{posId}")
#DELETE
public Employee remove(#PathParam("posId") int positonId) {}
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
//empUri sample is /employee/{id} server knows how to parse it
public Employee add(#FormParam("employeeUri") String empUri) {}
}
Now what is position id, one approach - it is a unique number across all teams, i.e. primary key in a table which will have position_id, team_id, emp_id as tuple. Ensuring that
there will never be 2 position_id same for 2 teams. This way the whole scenario could be turned to be HATEOAS.
In addition to be able to export URIs in JSON representation to a DTO, the approach that I take is, I have DTO representing the data model for its persistent storage and I have a representation model representing hyperlinked (de)serializable version of DTO where I store string value as hyperlink. I look at representation model as API and DTO as the SPI to the RESTful WS Data Model.

Categories