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

Rest Endpoints produce HttpMessageNotWritableException sometimes after restarts [DATAREST-716] #1085

Closed
spring-projects-issues opened this issue Nov 27, 2015 · 7 comments
Assignees
Labels

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Nov 27, 2015

Tim Meißner opened DATAREST-716 and commented

In some cases after application start some rest repositories fail to handle the http request and throw a HttpMessageNotWritableException (see StackOverflow reference)

2015-11-27 09:56:19.015  WARN 1207 --- [nio-9000-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$ProjectionResourceContentSerializer cannot be cast to com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["permissions"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.ProjectionResource["content"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$ProjectionResourceContentSerializer cannot be cast to com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["permissions"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.ProjectionResource["content"])
2015-11-27 09:56:19.024  WARN 1207 --- [nio-9000-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$ProjectionResourceContentSerializer cannot be cast to com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["userroles"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.ProjectionResource["content"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$ProjectionResourceContentSerializer cannot be cast to com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["userroles"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.ProjectionResource["content"])

Affects: 2.4.1 (Gosling SR1), 2.5 M1 (Hopper)

Reference URL: http://stackoverflow.com/questions/32572525/spring-data-rest-2-4-intermittent-error-classcastexception

Issue Links:

  • DATAREST-697 ProjectionSerializer doesn't react to unwrapping mode correctly
    ("duplicates")
  • DATAREST-743 Rest Endpoints produce HttpMessageNotWritableException sometimes after restarts

Referenced from: commits a8f271a, 88c97a6

Backported to: 2.4.2 (Gosling SR2)

1 votes, 5 watchers

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 6, 2016

Andrew Walters commented

The root cause of this seems to lie in the jackson-databind library:

UnwrappingBeanPropertyWriter.java:214

if (serializer.isUnwrappingSerializer()) {
    t = NameTransformer.chainedTransformer(t, ((UnwrappingBeanSerializer) serializer)._nameTransformer);
}

In the case of the ProjectionResourceContentSerializer, the isUnwrappingSerialzer() method returns true under certain conditions (if unwrappingSerializer(NameTransformer unwrapper) is invoked on it). As ProjectionResourceContentSerializer doesn't extend UnwrappingBeanSerializer we end up with this blowing up.

Now, I'm not a fan of how that's been implemented - a boolean check guarding a class cast which can end up with a blow up like this isn't great - but I think there's an issue within PersistentEntityJackson2Module that might be causing this (unverified at this time). At 2 points, a call is made to unwrappingSerializer(null) which is probably intended to ensure Unwrapping is disabled, but for the implementation in PersistentEntityJackson2Module it has what I imagine is the unintended consequence of setting isUnwrappingSerializer to true:

		public JsonSerializer<ProjectionResourceContent> unwrappingSerializer(NameTransformer unwrapper) {

			this.unwrapping = true;
			return this;
		}

A null check here would ensure the property is never inadvertently set to true, but I don't think the implementation as it stands will ever do anything practical anyway - I presume to have any impact (and be compatible with the jackson-databind code) we'd need to return an instance of UnwrappingBeanSerializer here.

At least in the short term though a null guard should be put in place which should alleviate this issue (though as I've said this is unconfirmed - I've only had time to trace the code through from stack traces, not execution - as the actual cause but looks a bad smell at the very least).

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 6, 2016

Andrew Walters commented

Actually taking a bit more of a look, even a null check probably isn't sufficient - the unwrapping property should be always set to false until a proper UnwrappingBeanSerializer can be returned as other code within jackson-databind invokes the unwrappingSerializer as well which will have the consequence of potentially leading to this failure.

Interim solution - remove this.unwrapping = true; @PersistentEntityJackson2Module:566

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 6, 2016

Oliver Drotbohm commented

Sounds like a duplicate of DATREST-697, which was fixed for Gosling SR2 and is already available via Spring Boot 1.3.1. Would you mind giving that a try?

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 6, 2016

Andrew Walters commented

Looks good to me Oliver. Upgrading from Gosling-RELEASE to SR2 seems to resolve the issue as you've said

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 6, 2016

Oliver Drotbohm commented

Awesome, happy coding! :)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 7, 2016

Collin Brown commented

It looks like I am still seeing this occur in Spring Boot 1.3.1.

2016-01-06 19:27:54.639  INFO 1783 --- [ost-startStop-1] o.a.catalina.util.SessionIdGenerator     : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [9,898] milliseconds.
Jan 06, 2016 7:27:54 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Jan 06, 2016 7:27:54 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Jan 06, 2016 7:27:54 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 59514 ms
Jan 06, 2016 7:27:54 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'dispatcherServlet'
2016-01-06 19:27:54.817  INFO 1783 --- [bio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2016-01-06 19:27:54.854  INFO 1783 --- [bio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 28 ms
2016-01-06 19:27:58.029  WARN 1783 --- [io-8080-exec-11] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$ProjectionResourceContentSerializer cannot be cast to com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["activities"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.ProjectionResource["content"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$ProjectionResourceContentSerializer cannot be cast to com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.UnmodifiableMap["activities"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.ProjectionResource["content"])

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 7, 2016

Oliver Drotbohm commented

Please don't reopen tickets that have been marked as fixed on already released versions (Gosling SR2 in this case) as this will create inconsistencies regarding the changelogs. Feel free to create a new ticket, which we can link to this one then

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

No branches or pull requests

2 participants