Spring 4.2.3 和 fastxml Jackson 2.7.0 不兼容

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34721851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:55:21  来源:igfitidea点击:

Spring 4.2.3 and fasterxml Hymanson 2.7.0 are incompatible

springHymansonfasterxml

提问by Marek R

After migration from fasterxml.Hymanson 2.6.3 to 2.7.0. This is because public JavaType constructType(Type type, Class<?> contextType)method used in Spring's AbstractHymanson2HttpMessageConverterwas removed. How to fix this? I am using Spring 4.2.3.

从 fastxml.Hymanson 2.6.3 迁移到 2.7.0 之后。这是因为删除public JavaType constructType(Type type, Class<?> contextType)了 Spring 中使用的方法AbstractHymanson2HttpMessageConverter。如何解决这个问题?我正在使用 Spring 4.2.3。

/signin/facebook
java.lang.NoSuchMethodError: com.fasterxml.Hymanson.databind.type.TypeFactory.constructType(Ljava/lang/reflect/Type;Ljava/lang/Class;)Lcom/fasterxml/Hymanson/databind/JavaType;
    at org.springframework.http.converter.json.AbstractHymanson2HttpMessageConverter.getJavaType(AbstractHymanson2HttpMessageConverter.java:314)
    at org.springframework.http.converter.json.AbstractHymanson2HttpMessageConverter.canRead(AbstractHymanson2HttpMessageConverter.java:146)
    at org.springframework.http.converter.json.AbstractHymanson2HttpMessageConverter.canRead(AbstractHymanson2HttpMessageConverter.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)

回答by M. Deinum

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

Spring 4.3 中将添加对 Hymanson 2.7 的支持。请参阅https://jira.spring.io/browse/SPR-13483

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

目前,如果不提供自己的集成类,您将无法使用它。

回答by Jagadish

The best compatible versions

最佳兼容版本

1)Spring 4.2.4 works with fasterxml Hymanson 2.7.2 or 2.8.4

1)Spring 4.2.4 适用于 fastxml Hymanson 2.7.2 或 2.8.4

2)Spring 4.3.5 works with fasterxml Hymanson 2.7.0

2)Spring 4.3.5 适用于 fastxml Hymanson 2.7.0

回答by Ondrej Bozek

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

我需要重写MappingHymanson2HttpMessageConverter以使一切正常(主要是泛型)。实际上它只是MappingHymanson2HttpMessageConverter从 Spring MVC 4.3 master 中抓取的:

public class MappingHymanson27HttpMessageConverter extends MappingHymanson2HttpMessageConverter {

    public MappingHymanson27HttpMessageConverter() {
    }

    public MappingHymanson27HttpMessageConverter(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 MappingHymansonValue) {
                MappingHymansonValue container = (MappingHymansonValue) 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 Hymanson {@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 Hymanson 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 Hymanson 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;
    }

}