Spring 4.2.3 and fasterxml Jackson 2.7.0 are incompatible

删除回忆录丶 提交于 2019-11-26 12:17:37

问题


After migration from fasterxml.jackson 2.6.3 to 2.7.0. This is because public JavaType constructType(Type type, Class<?> contextType) method used in Spring\'s AbstractJackson2HttpMessageConverter was removed. How to fix this? I am using 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)

回答1:


Support for Jackson 2.7 will be added in Spring 4.3. See https://jira.spring.io/browse/SPR-13483.

For now you aren't able to use it without providing your own integration classes.




回答2:


The best compatible versions

1)Spring 4.2.4 works with fasterxml Jackson 2.7.2 or 2.8.4

2)Spring 4.3.5 works with fasterxml Jackson 2.7.0




回答3:


I needed to override MappingJackson2HttpMessageConverter to make everything work (mainly generics). In fact it's just grabbed MappingJackson2HttpMessageConverter from Spring MVC 4.3 master:

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;
    }

}


来源:https://stackoverflow.com/questions/34721851/spring-4-2-3-and-fasterxml-jackson-2-7-0-are-incompatible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!