Skip to content

Get NPE on deserializing values with recursive @JsonIgnoreProperties #1755

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

Open
Romain-P opened this issue Aug 28, 2017 · 29 comments
Open

Get NPE on deserializing values with recursive @JsonIgnoreProperties #1755

Romain-P opened this issue Aug 28, 2017 · 29 comments
Labels
has-failing-test Indicates that there exists a test case (under `failing/`) to reproduce the issue

Comments

@Romain-P
Copy link

Romain-P commented Aug 28, 2017

I'm using spring-mvc for a restful service. By adding the dependency, my rest controllers automatically generate json from my response entities.

Dependency

jackson = '2.9.0'
compile "com.fasterxml.jackson.core:jackson-databind:$jackson"

Objects

@Getter @Setter
public final class UserDTO {
    [...]

    private Set<ActivityDTO> activities = Sets.newHashSet();
}


@Getter @Setter
public final class ActivityDTO {
    [...]

    private Set<ActivityDTO> subActivities;
}

Problem

Problems come in special cases. For example, I want to add an activity to an user. The following user-json works good, Jackson converts it without error.

{
"id": 1,
  "activities": [
    {
      "id": 1,
      "subActivities": null,
    }
  ]
}

But if I add an activity with sub activities, it crashes!

{
  "id": 6,
  "activities": [
    {
      "id": 19,
      "subActivities": [
        {
          "id": 20,
          "subActivities": [
            {
              "id": 24,
              "subActivities": null
            },
            {
              "id": 21,
              "subActivities": [
                {
                  "id": 23,
                  "subActivities": null
                },
                {
                  "id": 22,
                  "subActivities": null
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Indeed, jackson can't deserialize this json and I don't understand why. I get the following error.. Any idea?

13:45:56.890 [http-nio-8080-exec-1] DEBUG org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod - Failed to resolve argument 0 of type 'com.ortec.gta.database.model.dto.UserDTO'
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.ortec.gta.database.model.dto.UserDTO["activities"]->java.util.HashSet[2]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"]->java.util.HashSet[0]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"])
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:238)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:201)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:128)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:664)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.ortec.gta.configuration.ServletInitializer$CorsFilter.doFilter(ServletInitializer.java:78)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.ortec.gta.database.model.dto.UserDTO["activities"]->java.util.HashSet[2]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"]->java.util.HashSet[0]->com.ortec.gta.database.model.dto.ActivityDTO["subActivities"])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391)
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1689)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:370)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:368)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:285)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:368)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
	... 77 common frames omitted
Caused by: java.lang.NullPointerException: null
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:271)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:368)
	... 93 common frames omitted
@Romain-P Romain-P changed the title Jackson: get a null reference on deserializing Get a null reference on deserializing Aug 28, 2017
@Romain-P
Copy link
Author

I had to rollback to 2.7.9. It seems this bug appeared since 2.8.0,
More details: https://stackoverflow.com/questions/45918309/jackson-get-a-null-reference-on-deserializing

@cowtowncoder
Copy link
Member

cowtowncoder commented Sep 7, 2017

I would need a full reproduction here: member in question is the value deserializer, which should not be null. But perhaps there is a custom deserializer that does not properly resolve value deserializer.
Regarding this, it would be helpful to indicate which Jackson modules are used (if any).
For example something like jackson-datatype-hibernate or jackson-datatype-guava would register additional deserializers for specific types of Collections.

Alternative some features like Object Id handling (@JsonIdentityInfo) could also invoke alternate handling and could be relevant. Or, unwrapping (@JsonUnwrapped) with recursion can actually cause problems similar to this.

Other than this I do not know of any existing problems that would manifest this way.

@cowtowncoder
Copy link
Member

Can not reproduce. May be reopened with a reproduction.

@cen1
Copy link

cen1 commented Jun 5, 2018

@cowtowncoder I can also confirm this bug, exact same scenario as SO thread linked above. Specifically, @JsonIgnoreProperties with a combination of nested attributes (self-nesting of the same class) causes the NullPointer error mentioned above. Tested on jackson 2.9.5

This should be reopened.

Minimal test case:

public class JackBase {

    private String id;
}
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.math.BigDecimal;
import java.util.List;

public class JackExt extends JackBase {

    private BigDecimal quantity;

    private String ignoreMe;

    @JsonIgnoreProperties({"ignoreMe"})
    private List<JackExt> linked;

    private List<KeyValue> metadata;

    public BigDecimal getQuantity() {
        return quantity;
    }

    public void setQuantity(BigDecimal quantity) {
        this.quantity = quantity;
    }

    public String getIgnoreMe() {
        return ignoreMe;
    }

    public void setIgnoreMe(String ignoreMe) {
        this.ignoreMe = ignoreMe;
    }

    public List<JackExt> getLinked() {
        return linked;
    }

    public void setLinked(List<JackExt> linked) {
        this.linked = linked;
    }

    public List<KeyValue> getMetadata() {
        return metadata;
    }

    public void setMetadata(List<KeyValue> metadata) {
        this.metadata = metadata;
    }
}
public class KeyValue {

    private String key;

    private String value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public KeyValue(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public KeyValue() {}
}

Input JSON:

{
	"id": "1",
	"quantity": 5,
	"ignoreMe": "yzx",
	"metadata": [
                {
                    "key": "position",
                    "value": "2"
                }
            ],
	"linked": [
		{
			"id": "1",
			"quantity": 5,
			"ignoreMe": "yzx",
			"metadata": [
                {
                    "key": "position",
                    "value": "2"
                }
            ]
		}
	]
}

Exception:

2018-06-05 19:07:48,911 ERROR  Rest Api error. com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: JackExt["linked"]->java.util.ArrayList[0]->JackExt["metadata"])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391)
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1704)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:290)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
	at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1574)
	at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:965)
	at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:815)
	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.servlet.WebComponent.serviceImpl(WebComponent.java:473)
	at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:860)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
	at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:209)
	at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:244)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1629)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:530)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:272)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
	... 78 more

I can also confirm 2.7.9 works so this is a regression.

@cowtowncoder cowtowncoder reopened this Jun 5, 2018
@cowtowncoder
Copy link
Member

@cen1 Thank you for including reproduction. But I think it is missing couple of types (CommonItem and KeyValue); and also ObjectMapper configuration as private fields are not included by default. Could you include those so that reproduction can be run as a test?

@cen1
Copy link

cen1 commented Jun 5, 2018

Updated previus post with full test case. Commenting out @JsonIgnoreProperties stops the exception. Hopefully it's a trivial fix.

@cowtowncoder
Copy link
Member

@cen1 Thanks! We'll see... it is problematic, being recursive self-reference, so may be simple, or might be next to impossible to tackle. Hope it's former :)

cowtowncoder added a commit that referenced this issue Jun 6, 2018
@cowtowncoder
Copy link
Member

I am able to reproduce this. NPE itself is due to recursive definition that somehow either prevents contextualization, or leaves non-contextual instance to be used (createContextual() is where value deserializer is fetched, if not constructed from annotations earlier).

@cowtowncoder
Copy link
Member

Oddly enough, commenting out metadata (or changing type, anything to avoid another List valued property) prevents problem.

@cen1
Copy link

cen1 commented Jun 6, 2018

Yes, this is how I actually encountered the problem, after adding another list in my project. This may or may not be connected to #1575 (which I also encountered in v2.8.10 but on a recursive non-list property).

@cowtowncoder
Copy link
Member

@cen1 Thank you for pointing out #1575, I had a feeling I had worked on similar issue somewhat recently.
Odd thing is that test for it had Collection too, so it's not a general problem with container types (which would be unfortunate). Now just need to try to figure out what is different in this case...

@oranheim
Copy link

oranheim commented Jan 30, 2019

Experiencing a similar error:

FILE: src/test/resources/raml/schemas/ProvisionAgreement.raml

java.lang.IllegalArgumentException: (was java.lang.NullPointerException) (through reference chain: java.util.concurrent.ConcurrentHashMap["description"])

	at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3512)
	at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3431)
	at no.ssb.raml.jsonhandler.JsonSchemaHandler.lambda$resolveJsonLinks$4(JsonSchemaHandler.java:253)
	at java.util.concurrent.ConcurrentHashMap.forEach(ConcurrentHashMap.java:1597)
	at no.ssb.raml.jsonhandler.JsonSchemaHandler.resolveJsonLinks(JsonSchemaHandler.java:252)
	at no.ssb.raml.jsonhandler.JsonSchemaHandler.parseProperties(JsonSchemaHandler.java:244)
	at no.ssb.raml.jsonhandler.JsonSchemaHandler.lambda$mergePropertiesInJsonSchemaDefinitions$0(JsonSchemaHandler.java:97)
	at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
	at no.ssb.raml.jsonhandler.JsonSchemaHandler.mergePropertiesInJsonSchemaDefinitions(JsonSchemaHandler.java:97)
	at no.ssb.raml.jsonhandler.JsonSchemaHandler.addMissingJsonPropertiesInSchema(JsonSchemaHandler.java:80)
	at no.ssb.raml.RamltoJsonSchemaConverter.convertRamlToJsonSchema(RamltoJsonSchemaConverter.java:149)
	at no.ssb.raml.RamltoJsonSchemaConverter.lambda$parseDirectoryFiles$0(RamltoJsonSchemaConverter.java:120)
	at java.lang.Iterable.forEach(Iterable.java:75)
	at no.ssb.raml.RamltoJsonSchemaConverter.parseDirectoryFiles(RamltoJsonSchemaConverter.java:116)
	at no.ssb.raml.RamltoJsonSchemaConverter.convertSchemas(RamltoJsonSchemaConverter.java:95)
	at no.ssb.raml.RamltoJsonSchemaConverterTest.thatMainConvertsSchemas(RamltoJsonSchemaConverterTest.java:40)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at org.testng.TestRunner.privateRun(TestRunner.java:648)
	at org.testng.TestRunner.run(TestRunner.java:505)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
	at org.testng.SuiteRunner.run(SuiteRunner.java:364)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
	at org.testng.TestNG.runSuites(TestNG.java:1049)
	at org.testng.TestNG.run(TestNG.java:1017)
	at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:73)
	at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.concurrent.ConcurrentHashMap["description"])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:339)
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:299)
	at com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase.wrapAndThrow(ContainerDeserializerBase.java:79)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:507)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:341)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
	at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3507)
	... 39 more
Caused by: java.lang.NullPointerException
	at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
	at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)
	at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:502)
	... 42 more

This error can be reproduced by checking out: https://github.com/statisticsnorway/raml-to-jsonschema.git and set jackson.version=2.9.7 and run test case RamltoJsonSchemaConverterTest. It works with Jackson <=2.6.7.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jan 31, 2019

@oranheim Could you please file a new issue as it's not necessarily same problem. I can have a look with reproduction, but things get confusing if it's actually caused by different underlying problem (which seems possible reading descriptions).

@oranheim
Copy link

@cowtowncoder It turned out to be a serialization issue on our side. So it was not a bug. Please disregard my error report :)

@Romain-P Romain-P closed this as completed Feb 8, 2019
@cen1
Copy link

cen1 commented Feb 8, 2019

Was the bug actually solved or is this wrongly closed again?

@Romain-P
Copy link
Author

Romain-P commented Feb 8, 2019

I though it was fixed, isn't it? Issue opened for like 2 years lmao???

@cowtowncoder
Copy link
Member

cowtowncoder commented Feb 9, 2019

I think confusion here is that OP's problem not resolved; but someone who thought they had same issue found out it isn't. So I think this should not yet be closed.

We do have failing test, RecursiveIgnoreProperties1755Test

@cowtowncoder cowtowncoder reopened this Feb 9, 2019
@cowtowncoder cowtowncoder added 2.10 and removed 2.9 labels Feb 9, 2019
@SephShom
Copy link

@cowtowncoder we appreciate all your work and we know that is not easy. But this particular feature is a real problem for me. Is there any notice about that?. "(self-nesting of the same class) " is used for a tree a organization design, by example, base of the rest of data, and version 2.7 denies us to work with all new features. Nothing more to aport, same problem deserializing self-nesting of the same class

@cowtowncoder
Copy link
Member

cowtowncoder commented Jul 12, 2019

I don't think there's any feature here, but a bug. If someone has time to figure it out, that'd be great, but at this point there are dozens of other problems to work on so I doubt I will have time to look into this at all on short or even medium term.

There is a failing unit test (RecursiveIgnoreProperties1755Test) that may help pinpoint the issue: somewhere, somehow, contextualization of CollectionDeserializer fails (or, contextualized instance is not properly referenced by BeanSerializer).

@alexis-puska
Copy link

Still present, i have the same problem, recursive object with @JsonIgnoreProperties and the problem appear.

Methode :
public Collection deserialize(JsonParser p, DeserializationContext ctxt,

line 272 : if (valueDes.getObjectIdReader() != null) {

@cowtowncoder cowtowncoder added 2.11 and removed 2.10 labels Nov 15, 2019
@cowtowncoder cowtowncoder added 2.12 and removed 2.11 labels Apr 2, 2020
@cowtowncoder cowtowncoder changed the title Get a null reference on deserializing Get NPE on deserializing values with recursive @JsonIgnoreProperties Apr 2, 2020
@mxmlnglt
Copy link

Hello,

I just had the same problem (NPE at that same line 272 in CollectionDeserializer) and - omitting the details - I have a custom deserializer implementing interface ContextualDeserializer. In the deserialize(..) method implementation, I found out that due to reusing code from another serializer which did this:

ctxt.findNonContextualValueDeserializer(type);

type is a type I constructed via the TypeFactory ; I have to do this instead (when possible i.e. when the custom deserializer has been constructed via calling its createContextual(..) implemented method :

ctxt.findContextualValueDeserializer(collectionType, property);

Otherwise there are bits missing in the serializers leading to the NPE while reading the JSON.

@Romain-P
Copy link
Author

Romain-P commented May 5, 2020

Hello,

I just had the same problem (NPE at that same line 272 in CollectionDeserializer) and - omitting the details - I have a custom deserializer implementing interface ContextualDeserializer. In the deserialize(..) method implementation, I found out that due to reusing code from another serializer which did this:

ctxt.findNonContextualValueDeserializer(type);

type is a type I constructed via the TypeFactory ; I have to do this instead (when possible i.e. when the custom deserializer has been constructed via calling its createContextual(..) implemented method :

ctxt.findContextualValueDeserializer(collectionType, property);

Otherwise there are bits missing in the serializers leading to the NPE while reading the JSON.

Ggs maybe open a MR?

@cowtowncoder
Copy link
Member

I think code referenced would be in custom deserializer, and not in jackson-databind. It is true that the correct way to initialize, orchestrate use of deserializers to delegate to can be... tricky.
Particularly as contextualization (allowing (de)serializers to modify their behavior based on where [on which property, with what annotations] they are used) itself can get complicated, especially for structured types.

@DejazmachMolla
Copy link

Any update on this?

@cowtowncoder
Copy link
Member

No updates; no time to actively work on this.

@JooHyukKim
Copy link
Member

JooHyukKim commented Mar 10, 2024

In case this might help anybody working on this, sharing this here.

I took a stab at this issue (sample in my personal PR) and here are some of my findings+guesses.

  • Without @JsonIgnoreProperties, we use same CollectionDeserializer even with recursive input.
  • With @JsonIgnoreProperties, two CollectionDeserializer instances, that each recursively invokes valueDes.getObjectIdReader (second one fails)
  • Could it problem with how BeanPropertyMap is handled? Where during contextualization, we mutate BeanPropertyMap in BeanDeserializer.withByNameInclusion(), but do not update the reference pointing to the original BeanPropertyMap to the new one?

@SephShom
Copy link

Old problem but it remains me this working code:

    @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "parent_id", insertable = true, updatable = false, referencedColumnName="c_organization_id", foreignKey = @ForeignKey(name = "fk_parent"))
@Fetch(FetchMode.JOIN)
@JsonIgnoreProperties(value = "parents", allowSetters = true)
private Organization parent;

@OneToMany(mappedBy = "parent", orphanRemoval = false, fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
@JsonIgnoreProperties(value = "parent", allowSetters = true)
private List<Organization> parents;
allowSetters = true was the key here

@cowtowncoder
Copy link
Member

For what it's worth, allowSetters likely triggers different code path; probably leading to basically ignoring "ignored properties" for deserialization.

@cowtowncoder
Copy link
Member

@JooHyukKim Some reference somewhere does not get updated that much seems certain. BeanPropertyMaps cannot be shared between deserializers, although I don't know how necessary/useful creation of defensive copies is (in case a new variant of CollectionDeserializer is constructed).

I also spent some time trying to figure this out in the past, without managing to get there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has-failing-test Indicates that there exists a test case (under `failing/`) to reproduce the issue
Projects
None yet
Development

No branches or pull requests

9 participants