Hi

Thanks for the analysis, comments in the end of the message,
On 30/04/13 08:45, [email protected] wrote:
hey guys,
I recently wanted to upgrade to fasterxml jackson 2.2.0 (was on 2.1.4)
and noticed the changes they have made to their Provider breaks
how current ProviderFactory in cxf jax-rs looks up a message writer/reader.

Here are the details and I would like to hear what you guys think
on how to procede with this.
I'm using cxf 2.7.4

first up let's look at Providerfactory and specifically


private static Type[] getGenericInterfaces(Class<?>  cls) {
         if (Object.class == cls) {
             return new Type[]{};
         }
         Type genericSuperCls = cls.getGenericSuperclass();
         if (genericSuperCls instanceof ParameterizedType) {
             return new Type[]{genericSuperCls};
         }
         Type[] types = cls.getGenericInterfaces();
         if (types.length>  0) {
             return types;
         }
         return getGenericInterfaces(cls.getSuperclass());
     }

which is called from handleMapper(...);

on fasterxml jackson 2.1.4 it works fine because here is how the class is 
declared in there
com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider:

@Provider
@Consumes(MediaType.WILDCARD) // NOTE: required to support "non-standard" JSON 
variants
@Produces(MediaType.WILDCARD)
public class JacksonJsonProvider
     implements
         MessageBodyReader<Object>,
         MessageBodyWriter<Object>,
         Versioned
{

this leads to grabbing the generic interfaces and since Object is handled it 
can handle
writing your models fine.


now in 2.2.0 it's been modified to be like this
@Provider
@Consumes(MediaType.WILDCARD) // NOTE: required to support "non-standard" JSON 
variants
@Produces(MediaType.WILDCARD)
public class JacksonJsonProvider
     extends ProviderBase<JacksonJsonProvider,
         ObjectMapper,
         JsonEndpointConfig, JsonMapperConfigurator>
{

it's been refactored to extend ProviderBase which is delcared as so:
public abstract class ProviderBase<
     THIS extends ProviderBase<THIS, MAPPER, EP_CONFIG, MAPPER_CONFIG>,
     MAPPER extends ObjectMapper,
     EP_CONFIG extends EndpointConfigBase<EP_CONFIG>,
     MAPPER_CONFIG extends MapperConfiguratorBase<MAPPER_CONFIG,MAPPER>

     implements
         MessageBodyReader<Object>,
         MessageBodyWriter<Object>,
         Versioned
{


now what happens when getGenericInterfaces(...) is called now we hit this:

Type genericSuperCls = cls.getGenericSuperclass();
         if (genericSuperCls instanceof ParameterizedType) {
             return new Type[]{genericSuperCls};
         }

and in handleMapper we end up grabbing the parameterized types
which in this case are<JacksonJsonProvider, ObjectMapper, JsonEndpointConfig, 
JsonMapperConfigurator>
and end up having no match for a body writer/reader.

Shouldn't getGenericInterfaces been fixed so as to also return the actual 
interfaces of the class/superclass
in this case
   implements
         MessageBodyReader<Object>,
         MessageBodyWriter<Object>,
         Versioned

It seems to me that only looking at ParameterizedType and returning early
leaves out the actual interfaces that a Provider normally implements.

For now we are back on 2.1.4 of fasterxml jackson and cxf 2.7.4 but
eventually we would like to move 2.2.+
We can probably introduce a contextual property for the factory to even avoid checking all those type variables, to be able to work-around the cases like this one, with the complex class hierarchies, and also save the time (example, if a user knows a Jackson provider is registered then just let it be selected).

Thee other simple workaround is to register a custom JSONProvider which simply wraps Jackson 2.2.0.

The actual fix will also need to be done but I probably won't have time to do it for 2.7.5 (due shortly), as this fix will be quite sensitive

Thanks, Sergey

thanks,
parwiz



--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Reply via email to