Reputation: 4534
I'm using Jersey 1.17 on the server side to process REST requests and JAXB 2 to unmarshall the XML request content.
Context
This is the Jersey method I use. The MyDTO class uses the @XmlRootElement annotation (otherwise, I'd need to define the parameter with the JAXBElement type).
@Path("/myService")
@POST
@Consumes(MediaType.APPLICATION_XML)
public void myService(MyDTO dto) throws Exception
{
// Shouldn't get this far if the XML content in the request was invalid
System.out.println(dto);
}
Requirement
By default, the Sun/Oracle JAXB implementation doesn't throw exceptions when the XML content has errors. For example providing a string value, say ABC, for an Integer attribute simply leaves the value as null instead of throwing an exception.
In JAXB 2 a ValidationEvenHandler can be defined. Using the following handler handler, makes the XML unmarshalling throw an exception the way I need it to.
public class UnmarshallerValidationEventHandler implements ValidationEventHandler {
@Override
public boolean handleEvent(ValidationEvent event) {
// This indicates JAXB that it should continue processing only if the
// severity level is less than error. NOTE: validation event constants
// go in ascending order in level of severity(i.e., 0 WARNING, 1: ERROR, 2 :FATAL_ERROR)
return event.getSeverity() < ValidationEvent.ERROR;
}
}
Question
How can I get Jersey to use a particular JAXBContext instance in order to use an unmarshaller with my custom validation event handler?
Alternatively, given that my application only uses JAXB in Jersey methods, defining a particular JAXBContext globally for the the JVM instance would be a good option. How could that be done?
Upvotes: 4
Views: 1705
Reputation: 10379
Jersey Users Guide covers this in Using custom JAXBContext chapter. Basically you need to provide ContextResolver<T> like:
@Provider
public class PlanetJAXBContextProvider implements ContextResolver<JAXBContext> {
private JAXBContext context = null;
public JAXBContext getContext(Class<?> type) {
if(type != Planet.class)
return null; // we don't support nothing else than Planet
if(context == null) {
try {
context = JAXBContext.newInstance(Planet.class);
} catch (JAXBException e) {
// log warning/error; null will be returned which indicates that this
// provider won't/can't be used.
}
}
return context;
}
}
You can see a sample use in storage-service sample project (see JAXBContextResolver).
Note: Instead of ContextResolver<JAXBContext>
you can also provide ContextResolver<Marshaller>
or/and ContextResolver<Unmarshaller>
.
Upvotes: 3