I want to know which solution is better for a Jersey Rest Web service. In some cases JAXB is not able to handle some types. Is it better to use XStream?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
I want to know which solution is better for a Jersey Rest Web service.
JAXB (JSR-222) is the default binding layer for JAX-RS. This means that if you have the following method, JAXB will automatically be used to convert the return type (Customer) to XML (and JSON when using Jersey).
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("{id}")
public Customer read(#PathParam("id") long id) {
return entityManager.find(Customer.class, id);
}
If you need more control over your JAXBContext you can use a JAX-RS mechanism called ContextResolver:
http://blog.bdoughan.com/2011/04/moxys-xml-metadata-in-jax-rs-service.html
In some cases JAXB is not able to handle some types
JAXB is able to handle all types, either by default or through the use of an XmlAdapter. Below are some examples where an XmlAdapter is used with the Joda-Time types and some immutable domain objects:
http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html
http://blog.bdoughan.com/2010/12/jaxb-and-immutable-objects.html
Is it better to use XStream?
Below is a link to a blog entry I wrote where I mapped the same object model to the same XML document using both JAXB and XStream you may be interested in:
http://blog.bdoughan.com/2010/10/how-does-jaxb-compare-to-xstream.html
JAXB implementations such as MOXy also contain many extensions you will find useful such as XPath based mapping (#XmlPath) and an external mapping document:
http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html
For an example of using MOXy as the JAXB provider in Jersey see:
http://blog.bdoughan.com/2010/08/creating-restful-web-service-part-35.html
Depends on your use case - if you think JAXB will be significant limitation, you can use XStream. Btw Jersey recently added support for MOXy, which could help you overcome some corner cases in JAXB Reference impl in JDK.
Pro JAXB
out of the box functionality with Jersey
ability to specify own JAXBContext
stable; lots of tests / support from Jersey/JAXB team
Con JAXB
it doesn't work as expected for some corner cases (java/xml binding has limitations due to different nature of these languages)
Pro XStream:
you probably have some experience with that
Con XStream:
you'll need implement support for it (MessageBodyReaders/Writers) in Jersey
Related
I wanted to know why do we need to specify the Annotation #XmlAccessorType when working with JAXB .
When i googled for this i found out this description from a website stating this
#XmlAccessorType sets default field and property serializability. By default, JAXB serializes public fields and properties. By setting #XmlAccessorType, the bean can choose to only allow annotated fields to be serialized.
Here the author mentions that with this annotation it gives control on serialization .
My question is , so #XmlAccessorType has nothing to do with the JAXB Binding and Unbinding from XML to java and java to XML , and it is all about Serialization only .
JAXB's #XmlAccessorType annotation is only used by JAXB (JSR-222) implementations for determining how to marshal a file to/from XML:
Normally the main decision to be made is between FIELD & PROPERTY/PUBLIC. FIELD is particularly useful when you have logic in your get/set methods that you do not want triggered during marshalling/unmarshalling. To see one way this choice affects the mapping metadata see:
http://blog.bdoughan.com/2012/02/jaxbs-xmltype-and-proporder.html
NONE is a useful choice when you have many unmapped properties and you want to tell your JAXB implementation to only map the fields/properties you have annotated. This can be alot easier than adding a lot of #XmlTransient annotations into your model.
Fore More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
I use JAXB marshaller to store some java objects as XML files. Some of these objects reference each other, so I unsurprisingly obtain this error:
[com.sun.istack.internal.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML
The solution which consists in removing the cycles and use only tree structure is not feasible - I need both navigability directions.
To solve this issue, I would rather use xlink to reference the xml objects instead of copying them in cascade. Is this solution pertinent? Is it possible to do that with JAXB marshaller? How?
You can implement an XLink approach in JAXB using an XmlAdapter. Below are links to various similar answers.
Serialize a JAXB object via its ID?
Using JAXB to cross reference XmlIDs from two XML files
Can JAXB marshal by containment at first then marshal by #XmlIDREF for subsequent references?
I lead the EclipseLink JAXB (MOXy) implementation, and we have the #XmlInverseReference extension for mapping bidirectional relationship that you may be interested in:
http://blog.bdoughan.com/2010/07/jpa-entities-to-xml-bidirectional.html
Dude, you can note in one of the entity the annotation #XmlTransient, so when unmarch, it will not complain about the cycle problem.
But with thius workaround after unmarch the xml you will have to populate the atribute with the #XmlTransient.
I was reading some paper and find this. You can set #XmlTransient and use the callback method to do something after the unmarch. So you can set the parent to you child.
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.pessoa = (Pessoa) parent; }
I'm trying to enable JAXB annotation support within my RESTEasy based web application and this article was suggested to me (http://wiki.fasterxml.com/JacksonJAXBAnnotations). I'm able to get the jackson-xc.jar but I don't see how to register the annotation introspector. Currently, RESTEasy automatically serializes my JSON responses, where would the below fit? Currently, RESTeasy serializes the JSON object automatically.
Include jackson-xc jar, which contains org.codehaus.jackson.xc.JaxbAnnotationIntrospector
Register this annotation introspector
ObjectMapper mapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
// make deserializer use JAXB annotations (only)
mapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
// make serializer use JAXB annotations (only)
mapper.getSerializationConfig().setAnnotationIntrospector(introspector);
What you need to figure out is how to make RESTeasy use ObjectMapper you have configured. JAX-RS offers generic way to do this via providers, but there may be simpler way(s) to do this with RESTeasy.
Some JAX-RS implementations also register JAXB annotation introspector by default.
Last thing: are you sure you need to use JAXB annotations? While Jackson can use them, preferable method is to either just use basic naming convention for discovery and jackson's own annotations in case where overrides are needed. Problem with JAXB is that it is xml-specific so there is little bit of impedance when used with JSON.
Thanks for the reply, I'll take a look at your suggestions...
The reason why we want to stick with the jaxb annotations is that the #XmlRootElement(name="userResponse") annotation allows an extra wrapping element that we want in our JSON responses. See example below:
We want to have {"response":{"userResponse":[{"user":{"businessRegion":"US","firstName":"joe","language":"en","lastName":"smith"}}}]} instead of what Jackson currently outputs, {"response":[{"user":{"businessRegion":"US","firstName":"joe","language":"en","lastName":"smith"}}]}. Is there anyway to mimic the #XmlRootElement in Jackson without adding an additional wrapper class?
User class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="userResponse")
public class UserResponse extends AbstractResponse{
private Users user;
I have generated classes using wsimport/wsconsume for my webservice. I am using JAXB marshaller and unmarshaller support. Can any one tell me how these marshaller/unmarshaller uses gnereated classes? say it is geneated - requestFile,Response File,service,ServiceSoap,ObjectFactory, Package-info. Here Service is name of my webservice.
Any help is greatly appreciated.
JAXB uses the annotations on the generated classes to reflectively marshal/unmarshal XML documents. It tries to use sensible defaults if the annotations are missing.
package-info.java is a weird Java5 thing, which allows you to declare package-level annotations. JAXB uses this is do things like declare package-wide type converters, or XML namespaces.
ObjectFactory is a generate class that provides factory methods for the various JAXB types. You usually don't need to use that yourself.
The generated service classes are used by the JAX-WS runtime to assemble the JAXB-bound model objects into actual SOAP requests and responses.
Using JAXB I can create an XSD using code like:
JAXBContext ctx = JAXBContext.newInstance(classes);
ctx.generateSchema(new MySchemaOutputResolver());
That makes a goods XSD describing the structure of all the JAXB objects in the list of classes I pass in, however, I can't figure out how to add other types of XSD restrictions like minOccurs, maxOccurs, pattern, etc.
Is it possible to add annotations which indicate that additional information so that the XSD will include it?
You can use the #XmlElement(required = true) annotation to make an item required. Similar annotations exist for repetition, etc.
See here for annotation classes, the Javadoc has details.