Description
Jackson version: 2.8.1
Hi,
I use jackson as a MessageBodyWriter and MessageBodyReader in jesery framwork. I am doing a
restful application. But I meet a terrible issue when i get InvalidFormatiotException and convert it
to a response, Infinite recursion (StackOverflowError)
error reporting!
org.glassfish.jersey.server.internal.process.MappableException: com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]->com.fasterxml.jackson.databind.ObjectMapper["factory"]->com.fasterxml.jackson.databind.MappingJsonFactory["codec"]
have ignored very long repeat information.
I have a POJO:
public class Post extends Domain {
@PrimaryKey
private Integer post_id;
private Integer category_id;
private Integer user_id;
private String post_title;
private String post_content;
private Boolean post_published;
private Boolean post_enabled;
private String post_created_at;
private String post_updated_at;
public Post() {
this.post_id = null;
this.category_id = null;
this.user_id = null;
this.post_title = null;
this.post_content = null;
this.post_published = null;
this.post_enabled = null;
this.post_created_at = null;
this.post_updated_at = null;
}
@JsonCreator
public Post(@JsonProperty("post_id") Integer postId,
@JsonProperty("category_id") Integer categoryId,
@JsonProperty("user_id") Integer userId,
@JsonProperty("post_title") String postTitle,
@JsonProperty("post_content") String postContent,
@JsonProperty("post_published") Boolean postPublished,
@JsonProperty("post_enabled") Boolean postEnabled,
@JsonProperty("post_created_at") String postCreatedAt,
@JsonProperty("post_updated_at") String postUpdatedAt) {
this.post_id = postId;
this.category_id = categoryId;
this.user_id = userId;
this.post_title = postTitle;
this.post_content = postContent;
this.post_published = postPublished;
this.post_enabled = postEnabled;
this.post_created_at = postCreatedAt;
this.post_updated_at = postUpdatedAt;
}
// omit setter and getter
}
In normal situation, i transfer a normal json like {"post_id": 1, "post_title": "test"'}
(I want to update a post), it works fine. But when i transfer a type mismatch json like
{"post_id": "test", "post_title": "test"'}
, the terrible situation appeared.
I have a exception mapper to mapper a exception to a response, so in this case, when the type
is mismatch, jackson will occur a InvalidFormatException:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.lang.Integer from String "test": not a valid Integer value
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@77d4bc0b; line: 2, column: 13] (through reference chain: myblog.domain.Post["post_id"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:74)
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1374)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:925)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseInteger(StdDeserializer.java:454)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer.deserialize(NumberDeserializers.java:308)
at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer.deserialize(NumberDeserializers.java:286)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:490)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1579)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:961)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:808)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:256)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:74)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.provide(EntityParamValueFactoryProvider.java:96)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.provide(ParamValueFactoryWithSource.java:71)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:94)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:127)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384)
at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
And then i use a InternalServerException to pack this exception, and then set response entity by
using this new exception:
@Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {
public Response toResponse(Exception ex) {
if (App.isDebug()) {
ex.printStackTrace();
return Response.status(500)
.entity(ex)
.type(MediaType.APPLICATION_JSON)
.build();
} else {
return Response.status(500)
.entity(ex)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
}
Then, as you see, the infinite recursion appeared. Why i get this terrible error? If i dont pack the
InvalidFormatException and use another exception to wrap the response entity, every thins is ok!
Hopeful to get the reply, i debugged whole day, StackOverFlow is really a disaster.
Thanks