Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full support for Jackson 2.7 [SPR-13483] #18062

Closed
spring-projects-issues opened this issue Sep 22, 2015 · 10 comments
Closed

Full support for Jackson 2.7 [SPR-13483] #18062

spring-projects-issues opened this issue Sep 22, 2015 · 10 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Sep 22, 2015

Juergen Hoeller opened SPR-13483 and commented

Work on Jackson 2.7 started in August 2015 and completed in early January 2016. We need to revise our type variable exposure (#18301) for proper Jackson 2.7 support in Spring Framework 4.3 and should also evaluate other changes that are worth adapting to.


Issue Links:

Referenced from: commits a730e55

1 votes, 7 watchers

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 25, 2016

Sébastien Deleuze commented

Fixed by this commit, see #18301 comments for more details.

Jackson 2.7 and our support for it contains significant changes related to type resolution, so the more testing and feedbacks we get before GA, the best it is (for example in Spring Data cc Oliver Drotbohm).

@spring-projects-issues
Copy link
Collaborator Author

Osvaldo Pinali Doederlein commented

Since you asked for more feedback :) I just tried Spring 4.2.3 + Jackson 2.7.1 (which was just released promising some relief for this, see FasterXML/jackson-databind#1079). It still didn't work for me, but now with more interesting test failures like:

Caused by: java.lang.ClassCastException: com.google.openbidder.ui.resource.support.ExternalResource cannot be cast to com.google.openbidder.ui.resource.model.UserResource
at com.google.openbidder.ui.resource.impl.UserResourceServiceImpl.update(UserResourceServiceImpl.java:1)
at com.google.openbidder.ui.resource.support.AbstractResourceService.update(AbstractResourceService.java:99)
at com.google.openbidder.ui.controller.support.ResourceController.updateFromJson(ResourceController.java:124)
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:606)
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)
... 66 more

The exception is raised in my app code, but investigating this, it turns out the problem is related to resolution of methods with generics. The update() method at the top of stack has a parameter typed as UserResource, which is overriding a superclass's method definition where this parameter is a <C extends ExternalResource>, so the typecast is performed by a javac-generated stub (thus line "1" in the stack). Now the question becomes, why does the argument have the incorrect type. I have traced this to InvocableHandlerMethod.getMethodArgumentValues(); it's trying to work with a bean where I have this:

@RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public T createFromJson(@PathVariable("parentResourceName") String parentResourceName,
@RequestBody @Validated(Create.class) T newResource) {...}

Generics once again -- the above is in a base class, the actual bean is a derived UserController class that makes T->UserResource. The InvocableHandlerMethod looks wrong, it has:
bean = com.google.openbidder.ui.controller.UserController@67f06e49
bridgedMethod = (updateFromJson() Method that's a child of the parent class ResourceController)

The derived class UserController does NOT override this method, it doesn't even have any stub either. The only way to detect that this parameter must be an UserResource is by inspecting the bean class with getGenericSuperclass(), so you know that it binds its parameter #0 to UserResource, which with some effort can be correlated to the method definition in the superclass.

But the good news is that the fix you have for 4.3.0 makes even this scenario works; the tests passes again with the current 4.3.0 snapshot (doesn't pass with the 4.2.5 snapshot).

@spring-projects-issues
Copy link
Collaborator Author

Sébastien Deleuze commented

Thanks for your feedback, and glad it works with 4.3.x.

Indeed unlike Jackson 2.7.0, Jackson 2.7.1 avoid to break totally your app with Spring 4.2.x but given the changes they did, it is expected that generic resolution still does not work anymore. That's in line with the fact that Spring 4.2.x does not support Jackson 2.7.x (and won't from my POV since my fix would be a risk for regressions).

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Agreed from my side: Proper Jackson 2.7 support will have to remain a Spring 4.3 topic, going through the RC phase there, with Spring 4.2.x just fully supporting Jackson up until 2.6.x.

Spring Framework 4.3 RC1 is less than two months away anyway...

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Suhas V. Wadadekar commented

After upgrading to Jackson 2.7.5 and Spring 4.3.0.RELEASE, I get the following error when using Jackson to transform response body to JSON

14:26:04,247 ERROR [org.springframework.web.servlet.handler.SimpleMappingExceptionResolver] (default task-11) Controller Exception: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.ObjectWriter.forType(Lcom/fasterxml/jackson/databind/JavaType;)Lcom/fasterxml/jackson/databind/ObjectWriter;
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:978) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:248) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:77) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:167) [undertow-servlet-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:761) [undertow-core-1.1.8.Final.jar:1.1.8.Final]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_71]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_71]
	at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_71]
Caused by: java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.ObjectWriter.forType(Lcom/fasterxml/jackson/databind/JavaType;)Lcom/fasterxml/jackson/databind/ObjectWriter;
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:264) [spring-web-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100) [spring-web-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:225) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:173) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) [spring-web-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:130) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) [spring-webmvc-4.3.0.RELEASE.jar:4.3.0.RELEASE]
	... 32 more

It doesn't help if I rollback Jackson to 2.6.7. However, if I downgrade Spring to 4.2.6, then the problem goes away (both with Jackson 2.6.7 and 2.7.5) (I understand, that while official support for Jackson 2.7+ was only added in Spring 4.3, using Spring 4.2.6 with Jackson 2.7.5 may not be the best idea, even if it seems to work fine for me, as there could be bugs lurking somewhere).

Anyways, it seems like Spring 4.3 has some issues with Jackson overall.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

That ObjectWriter.forType method is available on Jackson 2.5 and higher, and we're using it as of Spring 4.3 since its predecessor - ObjectWriter.withType - is deprecated in the meantime.

So it actually looks like there's some old pre-2.5 Jackson jar lurking on your classpath, maybe brought in transitively through some other Maven dependency of yours... Could you please double-check that Jackson 2.6 or 2.7 is exclusively present?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

BTW, as of Spring 4.3, we also support Jackson 2.8 (currently in RC2) already. This is what we run against in our own test suite at the moment.

@spring-projects-issues
Copy link
Collaborator Author

Suhas V. Wadadekar commented

Thanks for your comment.
I checked again. I have exclusively 2.6 or 2.7 jars, cannot see any duplicates.

Now, I am using Wildfly 8.2.1 and has jackson modules installed with version 2.4.1. I am not using those, but I will see if that might an issue.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

It looks like that WildFly-included version of Jackson gets picked at runtime then. In other words, it might not matter which version you package into your war file since the WildFly-included version always gets picked up first... With Spring 4.2.x, you wouldn't have noticed, but as of Spring 4.3, we require Jackson 2.6+...

@spring-projects-issues
Copy link
Collaborator Author

Suhas V. Wadadekar commented

Yep, that was it.
Could that be added as a note to the wiki for Wildfly, that 'an upgrade to Wildfly modules might be required to meet the minimum dependencies'?

Thanks again for the pointers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants