Skip to content

Serialize InvalidFormatException cause infinite recursion #1413

Closed
@inxi-pc

Description

@inxi-pc

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions