I\'m hoping to have a flexible way of marshalling objects. A verbose version for single objects and a less-verbose version for multiple object versions.
For example, co
Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB 2 (JSR-222) expert group.
Your question is tagged EclipseLink
, if you are using EclipseLink JAXB (MOXy) you can take advantage of the external binding document to apply a second mapping to the Department
class.
ContextResolver
In a JAX-RS environment you can leverage MOXy's external binding document through a ContextResolver
:
import java.io.*;
import java.util.*;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
@Provider
@Produces({"application/xml", "application/json"})
public class DepartmentContextResolver implements ContextResolver {
private JAXBContext jc;
public DepartmentContextResolver() {
try {
Map props = new HashMap(1);
props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "example/bindings.xml");
jc = JAXBContext.newInstance(new Class[] {Department.class} , props);
} catch(JAXBException e) {
throw new RuntimeException(e);
}
}
public JAXBContext getContext(Class> clazz) {
if(Department.class == clazz) {
return jc;
}
return null;
}
}
For More Information
External Binding Document
By default MOXy's external binding document is used to augment the annotated model, but if you set the xml-mapping-metadata-complete
flag it will completely override the annotations allowing you to apply a completely different mapping:
...
For More Information
UPDATE
This update is to address a number of questions you asked in one of your comments:
1 . Should/can each ContentResolver have its own binding file?
Yes each ContextResolver
should have its own binding file. The main reason for introducing a new ContextResolver
is to represent a secondary mapping.
2 . Can I have more than one for each ContentResolver (this would give me a number of renderings of the same class, creating a 'view' of sorts), perhaps specifying its location in the constructor?
For a single ContextResolver
you can express the metadata across multiple binding files, but they will be combined into a single set of mappings. This means that a single ContentResolver
cannot have multiple views of a single class. A separate ContextResolver
is used to represent a secondary mapping.
3 . Where should the binding files reside?
I recommend loading the metadata file from the class path.
4 . I can see how the ContentResolver could be easily specified in a Resource's GET method, but how would this be done if the object is embedded in another (JPA) object? In the embedded object's getter/setter?
Your JAX-RS implementation should pick up your ContextResolver
because it is annotated with @Provider
. The ContextResolver
used for a class will depend on how you implement the getContext
method:
public JAXBContext getContext(Class> clazz) {
if(Customer.class == clazz) {
return jc;
}
return null;
}