Reputation: 1758
I am using Jersey to create a restful web-service marshals XML.
How would I set the xsi:schemaLocation?
This answer show how to set the Marshaller.JAXB_SCHEMA_LOCATION directly on the Marshaller.
The trouble I am having is that Jersey is marshaling the Java objects into XML. How do I tell Jersey what the schema location is?
Upvotes: 2
Views: 2724
Reputation: 149037
You could create a MessageBodyWriter
for this use case. Through the ContextResolver
mechanism you can get the JAXBContext
associated with your domain model. Then you can get a Marshaller
from the JAXBContext
and set the JAXB_SCHEMA_LOCATION
on it and do the marshal.
package org.example;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
@Provider
@Produces(MediaType.APPLICATION_XML)
public class FormattingWriter implements MessageBodyWriter<Object>{
@Context
protected Providers providers;
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public void writeTo(Object object, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
try {
ContextResolver<JAXBContext> resolver
= providers.getContextResolver(JAXBContext.class, mediaType);
JAXBContext jaxbContext;
if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
jaxbContext = JAXBContext.newInstance(type);
}
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "foo bar");
m.marshal(object, entityStream);
} catch(JAXBException jaxbException) {
throw new WebApplicationException(jaxbException);
}
}
public long getSize(Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
}
UPDATE
One other question. What is the connection between the my rest resource and the provider?
You still implement your resource the same way. The MessageBodyWriter
mechanism is just a way to override how the writing to XML will be done. The @Provider
annotation is a signal to the JAX-RS application to have this class automatically registered.
My resource class would return a
Foo
object. I take it I should be implementing aMessageBodyWriter<Foo>
?
You could implement it as MessageBodyWriter<Foo>
if you only want it applied to the Foo
class. If you want it to apply to more than just Foo
you can implement to the isWriteable
method to return true for the appropriate classes.
Upvotes: 3