복붙노트

[SPRING] Spring 4.2.3 및 fasterxml Jackson 2.7.0은 호환되지 않습니다.

SPRING

Spring 4.2.3 및 fasterxml Jackson 2.7.0은 호환되지 않습니다.

fasterxml.jackson 2.6.3에서 2.7.0으로 마이그레이션 한 후 이것은 Spring의 AbstractJackson2HttpMessageConverter에서 사용 된 public JavaType constructType (Type type, Class contextType) 메소드가 제거 되었기 때문입니다. 이 문제를 해결하는 방법? 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. ==============================

    1.Jackson 2.7에 대한 지원은 Spring 4.3에 추가 될 예정이다. https://jira.spring.io/browse/SPR-13483을 참조하십시오.

    Jackson 2.7에 대한 지원은 Spring 4.3에 추가 될 예정이다. https://jira.spring.io/browse/SPR-13483을 참조하십시오.

    지금은 자신 만의 통합 클래스를 제공하지 않으면이를 사용할 수 없습니다.

  2. ==============================

    2.가장 적합한 호환 버전

    가장 적합한 호환 버전

    1) Spring 4.2.4는 fasterxml Jackson 2.7.2 또는 2.8.4와 호환됩니다.

    2) spring 4.3.5는 fasterxml Jackson 2.7.0에서 작동합니다.

  3. ==============================

    3.모든 것을 작동하게하려면 MappingJackson2HttpMessageConverter를 재정의해야했습니다 (주로 제네릭). 사실 Spring MVC 4.3 master에서 MappingJackson2HttpMessageConverter를 가져 왔습니다 :

    모든 것을 작동하게하려면 MappingJackson2HttpMessageConverter를 재정의해야했습니다 (주로 제네릭). 사실 Spring MVC 4.3 master에서 MappingJackson2HttpMessageConverter를 가져 왔습니다 :

    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;
        }
    
    }
    
  4. from https://stackoverflow.com/questions/34721851/spring-4-2-3-and-fasterxml-jackson-2-7-0-are-incompatible by cc-by-sa and MIT license