I chased it down to:
org.glassfish.jersey.message.internal.MessageBodyFactory
@SuppressWarnings("unchecked")
private <T> MessageBodyWriter<T> _getMessageBodyWriter(Class<T> c, Type t,
Annotation[] as,
MediaType mediaType,
List<MbwModel> models,
PropertiesDelegate propertiesDelegate) {
List<MbwModel> writers = mbwLookupCache.get(new ModelLookupKey(c, mediaType));
if (writers == null) {
writers = new ArrayList<MbwModel>();
for (MbwModel model : models) {
if (isCompatible(model, c, mediaType)) {
...
isCompatible is returning false for the org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider. This is what isCompatible looks like:
org.glassfish.jersey.message.internal.MessageBodyFactory
@SuppressWarnings("unchecked")
private <T> boolean isCompatible(WorkerModel<T> model, Class c, MediaType mediaType) {
if (model.providerClassParam.equals(Object.class) ||
// looks weird. Could/(should?) be separated to Writer/Reader check
model.providerClassParam.isAssignableFrom(c) ||
c.isAssignableFrom(model.providerClassParam)
) {
for (MediaType mt : model.types) {
if (mediaType == null) {
return true;
}
if (MediaTypes.typeEqual(mediaType, mt) ||
MediaTypes.typeEqual(MediaTypes.getTypeWildCart(mediaType), mt) ||
MediaTypes.typeEqual(MediaTypes.GENERAL_MEDIA_TYPE, mt)) {
return true;
}
}
}
return false;
}
Note that isCompatible is *not* asking the MessageBodyWriter if the media type isWritable(). I'm not really sure why it wouldn't do that. This deferrment to the media type is from 2.4 - 2.8. Presumably this is a bug that should be fixed? Jackson is ready and able to (de)serialize my custom media type, but Jersey isn't letting it.
What is the workaround for this? Do I need to write custom MessageBody(Reader/Writer) instances for all my media types? I thought I read somewhere that they could leverage the existing Jackson implementation somehow. Is there a good web resource which will walk me through doing this?
Thanks,
Eric
From: Eric Stein
Sent: Friday, June 27, 2014 3:24 PM
To: users_at_jersey.java.net
Subject: (De)Serializing Custom MIME types
I read in an old thread that support for custom MIME types should work out of the box:
Anything "+json" should work out of the box
- Martin Maula-3
http://jersey.576304.n2.nabble.com/Application-Specific-content-types-and-JAXB-annotations-td6380235.html
but that hasn't been my experience. I have a resource
@POST
@Consumes("application/vnd.locustec.eim.initial.query.v1+json")
@Produces("application/vnd.locustec.eim.secured.query.v1+json")
public Response createSecuredQuery(
@ApiParam(required = true) final InitialQueryBean initialQuery) {
I have a simple bean:
@XmlRootElement(name = "InitialQuery")
public final class InitialQueryBean {
@JsonProperty("initialQuery")
public String getInitialQuery() { ...
public void setInitialQuery(final String initialQuery) { ...
@JsonProperty("restrictQueryToSites")
public Set<String> getRestrictQueryToSites() {...
public void setRestrictQueryToSites(final Set<String> restrictQueryToSites) { ...
}
and a simple test case:
@Test
public void testCreateSecuredQuery() {
final Response response =
this.target("/secured-queries")
.request("application/vnd.locustec.eim.secured.query.v1+json")
.post(Entity.entity(this.initialQueryBean, "application/vnd.locustec.eim.initial.query.v1+json"));
but I'm seeing
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:
MessageBodyWriter not found for
media type=application/vnd.locustec.eim.initial.query.v1+json,
type=class com.locustec.eim.query.rest.InitialQueryBean,
genericType=class com.locustec.eim.query.rest.InitialQueryBean.
If I change everything to MediaType.APPLICATION_JSON, it my test runs just fine. So what am I doing wrong here? I'm running Jersey 2.4.