web-dev-qa-db-fra.com

Spring 4.2.3 et plus rapidexml Jackson 2.7.0 sont incompatibles

Après la migration de rapidxmlml.jackson 2.6.3 vers 2.7.0. Cela est dû au fait que la méthode public JavaType constructType(Type type, Class<?> contextType) utilisée dans le AbstractJackson2HttpMessageConverter de Spring a été supprimée. Comment régler ceci? J'utilise Spring 4.2.3.

/signin/facebook
Java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.type.TypeFactory.constructType(Ljava/lang/reflect/Type;Ljava/lang/Class;)Lcom/fasterxml/jackson/databind/JavaType;
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.getJavaType(AbstractJackson2HttpMessageConverter.Java:314)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.canRead(AbstractJackson2HttpMessageConverter.Java:146)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.canRead(AbstractJackson2HttpMessageConverter.Java:141)
    at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.Java:706)
    at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.Java:770)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.Java:594)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.Java:557)
    at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.Java:357)
    at org.springframework.social.oauth2.OAuth2Template.postForAccessGrant(OAuth2Template.Java:242)
    at org.springframework.social.oauth2.OAuth2Template.exchangeForAccess(OAuth2Template.Java:144)
    at org.springframework.social.connect.web.ConnectSupport.completeConnection(ConnectSupport.Java:160)
    at org.springframework.social.connect.web.ProviderSignInController.oauth2Callback(ProviderSignInController.Java:228)
    at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:44)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.Java:222)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.Java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.Java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.Java:814)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.Java:737)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.Java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:617)
31
Marek Raszewski

La prise en charge de Jackson 2.7 sera ajoutée au printemps 4.3. Voir https://jira.spring.io/browse/SPR-13483

Pour l'instant, vous ne pouvez pas l'utiliser sans fournir vos propres classes d'intégration.

36
M. Deinum

Les meilleures versions compatibles

1) Spring 4.2.4 fonctionne avec plus vitexml Jackson 2.7.2 ou 2.8.4

2) Spring 4.3.5 fonctionne avec Fastxml Jackson 2.7.0

3
Jagadish

Je devais surcharger MappingJackson2HttpMessageConverter pour que tout fonctionne (principalement des génériques). En fait, il vient de récupérer le MappingJackson2HttpMessageConverter du maître Spring MVC 4.3:

public class MappingJackson27HttpMessageConverter extends MappingJackson2HttpMessageConverter {

    public MappingJackson27HttpMessageConverter() {
    }

    public MappingJackson27HttpMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper);
    }

    @Override
    public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
        JavaType javaType = getJavaType(type, contextClass);
        if (!logger.isWarnEnabled()) {
            return (this.objectMapper.canDeserialize(javaType) && canRead(mediaType));
        }
        AtomicReference<Throwable> causeRef = new AtomicReference<Throwable>();
        if (this.objectMapper.canDeserialize(javaType, causeRef) && canRead(mediaType)) {
            return true;
        }
        Throwable cause = causeRef.get();
        if (cause != null) {
            String msg = "Failed to evaluate deserialization for type " + javaType;
            if (logger.isDebugEnabled()) {
                logger.warn(msg, cause);
            } else {
                logger.warn(msg + ": " + cause);
            }
        }
        return false;
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        if (!logger.isWarnEnabled()) {
            return (this.objectMapper.canSerialize(clazz) && canWrite(mediaType));
        }
        AtomicReference<Throwable> causeRef = new AtomicReference<Throwable>();
        if (this.objectMapper.canSerialize(clazz, causeRef) && canWrite(mediaType)) {
            return true;
        }
        Throwable cause = causeRef.get();
        if (cause != null) {
            String msg = "Failed to evaluate serialization for type [" + clazz + "]";
            if (logger.isDebugEnabled()) {
                logger.warn(msg, cause);
            } else {
                logger.warn(msg + ": " + cause);
            }
        }
        return false;
    }

    @Override
    protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage)
        throws IOException, HttpMessageNotWritableException {

        JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
        JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
        try {
            writePrefix(generator, object);

            Class<?> serializationView = null;
            FilterProvider filters = null;
            Object value = object;
            JavaType javaType = null;
            if (object instanceof MappingJacksonValue) {
                MappingJacksonValue container = (MappingJacksonValue) object;
                value = container.getValue();
                serializationView = container.getSerializationView();
                filters = container.getFilters();
            }
            if (type != null && value != null && TypeUtils.isAssignable(type, value.getClass())) {
                javaType = getJavaType(type, null);
            }
            ObjectWriter objectWriter;
            if (serializationView != null) {
                objectWriter = this.objectMapper.writerWithView(serializationView);
            } else if (filters != null) {
                objectWriter = this.objectMapper.writer(filters);
            } else {
                objectWriter = this.objectMapper.writer();
            }
            if (javaType != null && javaType.isContainerType()) {
                objectWriter = objectWriter.forType(javaType);
            }
            objectWriter.writeValue(generator, value);

            writeSuffix(generator, object);
            generator.flush();

        } catch (JsonProcessingException ex) {
            throw new HttpMessageNotWritableException("Could not write content: " + ex.getMessage(), ex);
        }
    }

    /**
     * Return the Jackson {@link JavaType} for the specified type and context
     * class.
     * <p>
     * The default implementation returns
     * {@code typeFactory.constructType(type, contextClass)}, but this can be
     * overridden in subclasses, to allow for custom generic collection
     * handling. For instance:
     * <pre class="code">
     * protected JavaType getJavaType(Type type) { if (type instanceof Class &&
     * List.class.isAssignableFrom((Class)type)) { return
     * TypeFactory.collectionType(ArrayList.class, MyBean.class); } else {
     * return super.getJavaType(type); } }
     * </pre>
     *
     * @param type the generic type to return the Jackson JavaType for
     * @param contextClass a context class for the target type, for example a
     * class in which the target type appears in a method signature (can be
     * {@code null})
     * @return the Jackson JavaType
     */
    @Override
    protected JavaType getJavaType(Type type, Class<?> contextClass) {
        TypeFactory typeFactory = this.objectMapper.getTypeFactory();
        if (type instanceof TypeVariable && contextClass != null) {
            ResolvableType resolvedType = resolveVariable(
                (TypeVariable<?>) type, ResolvableType.forClass(contextClass));
            if (resolvedType != ResolvableType.NONE) {
                return typeFactory.constructType(resolvedType.resolve());
            }
        }
        return typeFactory.constructType(type);
    }

    private ResolvableType resolveVariable(TypeVariable<?> typeVariable, ResolvableType contextType) {
        ResolvableType resolvedType;
        if (contextType.hasGenerics()) {
            resolvedType = ResolvableType.forType(typeVariable, contextType);
            if (resolvedType.resolve() != null) {
                return resolvedType;
            }
        }
        resolvedType = resolveVariable(typeVariable, contextType.getSuperType());
        if (resolvedType.resolve() != null) {
            return resolvedType;
        }
        for (ResolvableType ifc : contextType.getInterfaces()) {
            resolvedType = resolveVariable(typeVariable, ifc);
            if (resolvedType.resolve() != null) {
                return resolvedType;
            }
        }
        return ResolvableType.NONE;
    }

}
0
Ondrej Bozek