users@jersey.java.net

Re: [Jersey] JSONP

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 21 Jan 2010 14:43:39 +0000

On Jan 21, 2010, at 2:11 PM, Jakub Podlesak wrote:

> On Thu, Jan 21, 2010 at 10:22:00AM +0000, Paul Sandoz wrote:
>>
>> On Jan 21, 2010, at 9:08 AM, Jakub Podlesak wrote:
>>> Since the Jackson writer is enabled by the application via the META-
>>> INF/services,
>>
>> Ah, i got it now. Yes, in the sample (or registered via Application/
>> ResourceConfig) application registered providers will take
>> precedence.
>>
>>
>>> it is given higher priority then the JSONWithPaddingProvider, and
>>> the delegation
>>> never happens.
>>>
>>
>> Possible solutions and work around(s):
>>
>> 1) introduce a priority ordering. This would be easy to with
>> @Produces("application/json;qs=2, */*").
>> or state that certain providers cannot be overridden.
>
> That would be great, even if it still allows for more such providers
> with the same quality parameter value.
>
>>
>> 2) re-register the JSONWithPaddingProvider ahead of the Jackson
>> providers.
>
> If you mean declaring that together with the Jackson provider
> at the application META-INF/services, i have tested it and it did
> not work.
> I think there is not guaranteed the providers order from the file
> would be kept
> withing the runtime.
>

I think that may be because JacksonJsonProvider has produces declared:

     https://svn.codehaus.org/jackson/trunk/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java
   @Provider
   @Consumes({MediaType.APPLICATION_JSON, "text/json"})
   @Produces({MediaType.APPLICATION_JSON, "text/json"})
   public class JacksonJsonProvider
and thus it will take priority over any @Produces("*/*") which is the
default (if @Produces is absent).

You could try doing:

   @Produces({MediaType.APPLICATION_JSON, "text/json", "*/*"})
   public class JSONWithPaddingProvider { ... }

However, i was not proposing this as an ideal solution, just a work
around.


>>
>> 3) Jersey declares to Jackson an exclude list of classes or package.
>
> That would mean changes in Jackson.

Yes. Jackson does have a concept of an "exclude" list:

     public final static HashSet<ClassKey> _untouchables = new
HashSet<ClassKey>();
     static {
         // First, I/O things (direct matches)
         _untouchables.add(new ClassKey(java.io.InputStream.class));
         _untouchables.add(new ClassKey(java.io.Reader.class));
         _untouchables.add(new ClassKey(java.io.OutputStream.class));
         _untouchables.add(new ClassKey(java.io.Writer.class));

         // then some primitive types
         _untouchables.add(new ClassKey(byte[].class));
         _untouchables.add(new ClassKey(char[].class));
         // 24-Apr-2009, tatu: String is an edge case... let's leave
it out
         _untouchables.add(new ClassKey(String.class));

         // Then core JAX-RS things
         _untouchables.add(new ClassKey(StreamingOutput.class));
         _untouchables.add(new ClassKey(Response.class));
     }

Note the latter two. I think an extensible solution, where something
else can also add to the "untouchables" list, may be worth exploring
further as i think that would be the best solution to solve the problem.


> Maybe we can just introduce
> a proxy provider in a separate Jersey module to call the Jackson
> provider for everything
> except the JSONWithPadding. That would also remove the necessity of
> the special META-INF/services files to enable the Jackson JSON
> provider.
>

That could be one solution but would not work for those using Jackson
independently.

Paul.