Jersey REST Client - handle Custom MediaType as MediaType.APPLICATION_JSON

I am writing a REST client using Jersey with JacksonFeature enabled for a web service that forces me to specify my content type under names, even if it's just plain JSON. In other words, when I do this:

Request request = buildMySampleRequestPojo(); Response response = requestBuilder.post( Entity.entity(request, MediaType.APPLICATION_JSON) ); 

The service complains that I am using an invalid content type. I can get around this by specifying my media type with the username instead of the MediaType.APPLICATION_JSON constant:

 Response response = requestBuilder.post( Entity.entity(request, "vnd.stupidNameThatReallyIsJustJSON+json") ); 

However, when I do this, I get:

 *SEVERE: MessageBodyWriter not found for media type=stupidNameThatReallyIsJustJSON* 

Is there a way to get Jersey to treat this customized media type as if it were regular JSON without writing a customized MessageBodyWriter?

+8
java json web-services jersey jersey-client
source share
1 answer

I think you could use this (JAX-RS entity providers) and this (use Jackson with Jersey) to achieve what you want. In short, register a MessageBodyWriter annotated with @Produces("application/vnd.stupidNameThatReallyIsJustJSON+json") , and in the implementation, simply delegate marshalling / unmarshalling to Jackson.

EDIT: try something in lines

 package my.pack.age; import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider; import com.sun.jersey.core.util.ReaderWriter; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Type; @Produces("application/vnd.stupidNameThatReallyIsJustJSON+json") public class MyJsonBodyWriter<T> extends AbstractMessageReaderWriterProvider<T> { // T should be your pojo in this case. If you can make your pojo compatible with org.codehaus.jettison.json.JSONObject, // then you can extend com.sun.jersey.json.impl.provider.entity.JSONObjectProvider and delegate all the methods of // MessageBodyWriter (and MessageBodyReader) to that. Otherwise just implement them. @Override public T readFrom(Class<T> type, Type genericType, Annotation annotations[], MediaType mediaType,MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { try { // deserialize entityStream according to the given media type and return a new instance of T. // // You can do it like this (just an example) : // JSONObject myObject = new JSONObject(); // try { // these names and values should come from the stream. // myObject.put("name", "Agamemnon"); // myObject.put("age", 32); // } catch (JSONException ex) { // LOGGER.log(Level.SEVERE, "Error ...", ex); // } return null; } catch (Exception e) { throw new WebApplicationException(new Exception("Error during deserialization", e),400); } } @Override public void writeTo(T t,Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException { try { OutputStreamWriter writer = new OutputStreamWriter(entityStream, ReaderWriter.getCharset(mediaType)); // write t on the writer writer.flush(); } catch (Exception e) { throw new WebApplicationException( new Exception("Error during serialization", e), 500); } } @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { // should return true if this class can serialize the given type to the given media type return true; } @Override public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { // should return true if this class can deserialize the given type to the given media type return true; } @Override public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { // calculate and return content-lenght, ie the lenght of the serialized representation of t return 0; } } 

Obviously, this is just a starting point, not a working example, but it should give you enough information to get you started. Also remember that you will need to register a class in Jersey for it to use.

+7
source share

All Articles