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

NullPointerException from ResolvedRecursiveType (regression due to fix for #2331) #2395

Closed
michael-simons opened this issue Jul 29, 2019 · 24 comments
Milestone

Comments

@michael-simons
Copy link

michael-simons commented Jul 29, 2019

Hello,

the backport for #2331 into 2.9.9, specific 2.9.9.2, which comes through 2.9.9.20190727, leads to a null pointer exception together with the JDK 8 module:

Given

package ac.simons;

import java.io.IOException;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;

public class JacksonTest {

	@Test
	void shouldWorkWithoutJdk8Module() throws IOException {
		ObjectMapper objectMapper = new ObjectMapper();

		final JsonNode responseNode = objectMapper.readTree("{}");
		Assertions.assertNotNull(responseNode);
	}

	@Test
	void shouldWorkWithJdk8Module() throws IOException {
		ObjectMapper objectMapper = new ObjectMapper()
			.registerModule(new Jdk8Module());

		final JsonNode responseNode = objectMapper.readTree("{}");
		Assertions.assertNotNull(responseNode);
	}
}

It doesn't matter whether the object to be parsed is empty as above or contains data as for example

final JsonNode responseNode = objectMapper.readTree("{\"something\":\"foobar\"}");

Works with com.fasterxml.jackson:jackson-bom:2.9.9 and breaks with com.fasterxml.jackson:jackson-bom:2.9.9.20190727:

java.lang.NullPointerException
	at com.fasterxml.jackson.databind.type.ResolvedRecursiveType.getBindings(ResolvedRecursiveType.java:42)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromAny(TypeFactory.java:1243)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(TypeFactory.java:1452)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromAny(TypeFactory.java:1221)
	at com.fasterxml.jackson.databind.type.TypeFactory._resolveSuperInterfaces(TypeFactory.java:1367)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromClass(TypeFactory.java:1314)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromAny(TypeFactory.java:1217)
	at com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeFactory.java:631)
	at com.fasterxml.jackson.databind.cfg.MapperConfig.constructType(MapperConfig.java:281)
	at com.fasterxml.jackson.databind.cfg.MapperConfig.introspectClassAnnotations(MapperConfig.java:311)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findTypeDeserializer(BasicDeserializerFactory.java:1571)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:483)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4191)
	at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4052)
	at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2552)
	at ac.simons.JacksonTest.shouldWorkWithJdk8Module(JacksonTest.java:27)
	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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Please find a sample project attached.

jacksonissue.zip

@VanCoding
Copy link

I can confirm this bug. I just wasted my morning trying to find out what's going on. Turned out to be the 2.9.9.2 release.

@chriskessel
Copy link

chriskessel commented Jul 29, 2019

Confirmed here too. Using JDK 11. In my case, when Dropwizard is trying to parse its yml config file:

java.lang.NullPointerException
	at com.fasterxml.jackson.databind.type.ResolvedRecursiveType.getBindings(ResolvedRecursiveType.java:42)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromAny(TypeFactory.java:1243)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(TypeFactory.java:1452)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromAny(TypeFactory.java:1221)
	at com.fasterxml.jackson.databind.type.TypeFactory._resolveSuperInterfaces(TypeFactory.java:1367)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromClass(TypeFactory.java:1314)
	at com.fasterxml.jackson.databind.type.TypeFactory._fromAny(TypeFactory.java:1217)
	at com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeFactory.java:631)
	at com.fasterxml.jackson.databind.cfg.MapperConfig.constructType(MapperConfig.java:281)
	at com.fasterxml.jackson.databind.cfg.MapperConfig.introspectClassAnnotations(MapperConfig.java:311)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findTypeDeserializer(BasicDeserializerFactory.java:1571)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:483)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4191)
	at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3980)
	at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2385)
	at io.dropwizard.configuration.BaseConfigurationFactory.build(BaseConfigurationFactory.java:81)```

@rkraneis
Copy link

We are also affected.

@chadlwilson
Copy link

chadlwilson commented Jul 29, 2019

In our case the issue is observed using spring-data-redis's Jackson2HashMapper; but looks like a similar problem; details here.

(Edit: just checked and we initialize our Jackson2HashMapper with the default ObjectMapper injected via Spring; which itself has the JDK8 module registered by default via the Jackson2ObjectMapperBuilder's "well-known modules" support; so it seems quite possible it's the same root cause.)

It would also be good if we could get the changelog fixed too; the change that broke this was incorrectly included in the changelog for 2.9.9.1 - not 2.9.9.2 when it was actually released.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jul 29, 2019

I'll update the changelog first. Reproduction with Java8 module is interesting since it is unclear why and how that should have any effect (obviously basic readTree() functionality is heavily tested in databind itself, but won't fail somehow).

I will start with the test case but will need to figure out how to reproduce without other modules as tests from jackson-databind can not rely on modules (which depend on databind).

@cowtowncoder
Copy link
Member

I can reproduce this: looks like NPE is indirectly triggered by call to JavaType.getBindings();, which is not needed if no TypeModifiers registered. Bit odd that existing test class TestTypeModifiers does NOT somehow hit that... which is too bad as that would have caught the problem.

@cowtowncoder
Copy link
Member

Ah. This is due to JsonNode having recursive self-reference via Iterable<JsonNode>.

cowtowncoder added a commit that referenced this issue Jul 30, 2019
@cowtowncoder cowtowncoder changed the title Databind 2.9.9.2 breaks Jdk8 module with NullPointerException. NullPointerException from ResolvedRecursiveType (regression due to fix for #2331) Jul 30, 2019
@cowtowncoder cowtowncoder added this to the 2.9.9.3 milestone Jul 30, 2019
@rkraneis
Copy link

Great response time! 🚀

@michael-simons
Copy link
Author

Indeed. Shit happens, and this is has been dealt with. Thank you, @cowtowncoder !

@mp911de
Copy link

mp911de commented Jul 30, 2019

Do you have an indication about availability in a release?

@cowtowncoder
Copy link
Member

I'll have to think about timing a bit. There haven't been too many fixes aside from this one critical one, so it'll probably be 2.9.9.3 with matching jackson-bom; this is relatively light-weight thing to do (an hour or so). But I'd like to see if there are any fixes that would be backported in 2.9 jackson-databind since there will be another release.

But I think I will release that micro-patch by end of this week (so within 6 days).

@mp911de
Copy link

mp911de commented Jul 30, 2019

Thanks a lot!

@iemejia
Copy link

iemejia commented Aug 4, 2019

Any plans to release 2.9.9.3 soon?

@ryanscott72
Copy link

^

@cowtowncoder
Copy link
Member

2.9.9.3 of jackson-databind out with matching jackson-bom, as per:

https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.9

@iemejia
Copy link

iemejia commented Aug 6, 2019

Thanks @cowtowncoder !

@snicoll
Copy link

snicoll commented Aug 6, 2019

Bummer @cowtowncoder, the new bom still refers to 2.9.9.2 as far as I can see, see FasterXML/jackson-bom#24

@cowtowncoder
Copy link
Member

cowtowncoder commented Aug 6, 2019

Oh... f. Ok. How did I manage to do that. Joys of manual releases. Will need to release another pom. Thank you for reporting this.

@cowtowncoder
Copy link
Member

2.9.9.20190807 on its way now.

@snicoll
Copy link

snicoll commented Aug 6, 2019

Thanks for the quick turnaround @cowtowncoder

ddossot added a commit to apple/servicetalk that referenced this issue Aug 6, 2019
__Motivation__

A regression has been introduced in 2.9.9.2 and fixed in 2.9.9.3

See: FasterXML/jackson-databind#2395
doncem added a commit to hmcts/send-letter-service that referenced this issue Aug 7, 2019
nitinprabhu added a commit to hmcts/send-letter-service that referenced this issue Aug 7, 2019
nitinprabhu added a commit to hmcts/bulk-scan-processor that referenced this issue Aug 7, 2019
nitinprabhu added a commit to hmcts/bulk-scan-processor that referenced this issue Aug 7, 2019
xvrl added a commit to xvrl/common that referenced this issue Aug 7, 2019
Some downstream components are hitting the following regression in 2.9.9.2
FasterXML/jackson-databind#2395
xvrl added a commit to confluentinc/common that referenced this issue Aug 7, 2019
Some downstream components are hitting the following regression in 2.9.9.2
FasterXML/jackson-databind#2395
mibo added a commit to mibo/spring-cloud-connectors that referenced this issue Aug 8, 2019
Updated `jackson-databind` version to `2.9.9.3` which contains fix for [this regression](FasterXML/jackson-databind#2395).
scottfrederick pushed a commit to spring-cloud/spring-cloud-connectors that referenced this issue Aug 19, 2019
Updated `jackson-databind` version to `2.9.9.3` which contains fix for [this regression](FasterXML/jackson-databind#2395).
Dufgui pushed a commit to Dufgui/quarkus that referenced this issue Aug 26, 2019
Update to the latest [micro-patch](https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.9#micro-patches) of jackson-databind 2.9.9.3
to fix a regression FasterXML/jackson-databind#2395

Signed-off-by: Jorge Solorzano <jorsol@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests