Adam,
Thanks very much for your answer. Sorry for the delayed response .. I got pulled onto something else and only now have time to look at this again.
Unfortunately, we're still on Java 6, so upgrading Jersey past jersey version 2.6 isn't an option. I guess I'll play around with Moxy and see if I can get that to work.
Thanks,
Eric
From: Adam Lindenthal [mailto:adam.lindenthal_at_oracle.com]
Sent: Thursday, July 03, 2014 8:48 AM
To: users_at_jersey.java.net
Subject: [Jersey] Re: (De)Serializing Custom MIME types
Hi Eric,
your case fails indeed with jersey 2.8 and lower with Jackson (with Moxy, your case works as expected even in 2.4-2.8)
Please try to use Jersey 2.9+ which uses newer Jackson 2.x, whereas 2.8 and lower used 1.9.x.
Hope that helps.
Regards,
Adam
On 1.7.2014 15:15, Eric Stein wrote:
Can somebody please confirm that Jersey is unable to handle custom MIME types or tell me what I'm doing wrong? This seems like a really big thing to be missed. Should I be raising a bug?
Eric
From: Eric Stein
Sent: Friday, June 27, 2014 4:51 PM
To: users_at_jersey.java.net<mailto:users_at_jersey.java.net>
Subject: RE: (De)Serializing Custom MIME types
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<mailto: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.