users@jersey.java.net

[Jersey] Re: (De)Serializing Custom MIME types

From: Adam Lindenthal <adam.lindenthal_at_oracle.com>
Date: Thu, 03 Jul 2014 14:47:31 +0200

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
> *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.
>