2016-01-11 93 views
28

從fasterxml.jackson 2.6.3遷移到2.7.0之後。這是因爲刪除了AbstractJackson2HttpMessageConverter中使用的public JavaType constructType(Type type, Class<?> contextType)方法。如何解決這個問題?我使用的是Spring 4.2.3。Spring 4.2.3和fasterxml Jackson 2.7.0不兼容

/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) 
+8

使用舊版本,對於Spring 4.3已經添加了對2.7的支持,請參閱https://jira.spring.io/browse/SPR-13483 –

+0

@ M.Deinum你應該發佈這個作爲答案 – yglodt

+2

看起來像春天4 .2.4和傑克遜2.6.5兼容。 –

回答

33

支持Jackson 2.7將在Spring 4.3中添加。見https://jira.spring.io/browse/SPR-13483

現在,如果不提供自己的集成類,就無法使用它。

+3

這個問題似乎在Jackson 2.7.1-1中得到修復,它現在可以在Spring 4.2.4中使用。 – turtlesallthewaydown

+0

我需要插入自定義的MappingJackson2HttpMessageConverter仍然存在泛型類型映射和推斷的問題。 –

+1

傑克遜2.7.3值得一提的是,修正了關於類型分辨率變化(由於在2.6和2.7之間重寫了類型處理引起的)最後已知/報告的問題。 – StaxMan

0

我需要覆蓋MappingJackson2HttpMessageConverter使一切正常(主要是泛型)。事實上,它只是抓住MappingJackson2HttpMessageConverter從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; 
    } 

} 
3

最好的兼容版本

1)春4.2.4工程與fasterxml傑克遜2.7.2或2.8.4

2) Spring 4.3.5使用fasterxml Jackson 2.7.0

+0

它適用於我,我有與Spring 4.3.5和fasterxml相同的問題,然後我使用傑克遜2.7.0,它適用於我。 – Yacino

相關問題