FasterXML/jackson-modules-base

BlackBird proxy object error in Java 17

noobgramming opened this issue ยท 11 comments

The object it's trying to serialize is an interface return value in a Spring REST controller, and the instance is constructed by a @Query in a Spring Repository

returned object looks like this

public interface GetStatusAccepted {
  Integer getAccepted();
  // more integer returning methods...
}

This problem was not occuring on identical code before we added BlackBirdModule to our Jackson configuration.

relevant part of trace:
java.lang.IllegalAccessException: module jdk.proxy3 does not open jdk.proxy3 to unnamed module @479f2dc2 at java.base/java.lang.invoke.MethodHandles.privateLookupIn(MethodHandles.java:259) at com.fasterxml.jackson.module.blackbird.util.ReflectionHack$Java9Up.lambda$privateLookupIn$0(ReflectionHack.java:53) at com.fasterxml.jackson.module.blackbird.util.Unchecked.lambda$supplier$1(Unchecked.java:41) at com.fasterxml.jackson.module.blackbird.util.ReflectionHack$Java9Up.privateLookupIn(ReflectionHack.java:53) at com.fasterxml.jackson.module.blackbird.util.ReflectionHack.privateLookupIn(ReflectionHack.java:25) at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.lambda$findProperties$0(BBSerializerModifier.java:67) at com.fasterxml.jackson.module.blackbird.util.Unchecked.lambda$runnable$0(Unchecked.java:31) at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.findProperties(BBSerializerModifier.java:68) at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.changeProperties(BBSerializerModifier.java:52) at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanOrAddOnSerializer(BeanSerializerFactory.java:414) at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanOrAddOnSerializer(BeanSerializerFactory.java:294) at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:239) at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:173) at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1495) at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1443) at com.fasterxml.jackson.databind.SerializerProvider._findExplicitUntypedSerializer(SerializerProvider.java:1412) at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.hasSerializerFor(DefaultSerializerProvider.java:260) at com.fasterxml.jackson.databind.ObjectMapper.canSerialize(ObjectMapper.java:3431) at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.canWrite(AbstractJackson2HttpMessageConverter.java:274) at org.springframework.http.converter.AbstractGenericHttpMessageConverter.canWrite(AbstractGenericHttpMessageConverter.java:76) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.getProducibleMediaTypes(AbstractMessageConverterMethodProcessor.java:380) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:230) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:183) at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:124) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1064) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:645) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)

@noobgramming is this different from #170 ?

Got to the same issue. No problem with Afterburner. Spring boot 2.7.12, java version 17.0.3.1
No other jackson module including MrBeanModule used.

Code:
public interface CharacterizationTypeDTO {
Long getCharacterizationSkey();
String getCharacterizationDescription();
}
@repository
public interface CharacterizationTypeRepository extends JpaRepository<CharacterizationType, Long> {
List findAllProjectedBy(Sort sort);
}

Exception:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: module jdk.proxy2 does not open jdk.proxy2 to unnamed module @36d64342; nested exception is com.fasterxml.jackson.databind.JsonMappingException: module jdk.proxy2 does not open jdk.proxy2 to unnamed module @36d64342 (through reference chain: java.util.ArrayList[0])]

And Jackson version?

Note that to help we'd need a reproduction that does not rely on Spring -- I'll a label to denote that. Otherwise problems may be due to Spring integration; we do not troubleshoot those parts. If a test can be isolated, please include it here.
Otherwise it may make sense to start with Spring altho TBH it is likely there's an issue on Blackbird module.

@pjfanning We don't use MrBeanModule so I don't think it's related to #170

@cowtowncoder version 2.13.5, Understand. Will try to setup example without spring at some point. What was leading me, that issue is in jackson and not in the spring itself, everything works when i'm using legacy afterburner module or different serializers like gson or even class based spring projections work. Only interface based projections and related proxy objects causing troubles only in combination with blackbird module.

@Jancula right, I suspect issue is indeed with Blackbird.

As to 2.13.5: while not super old, any fixes would go to 2.15 or later (with exception of some of safest fixes, or in some rare cases, security fixes) so it'd be nice to rule out possibility that things work on later versions.
That is, would be good to verify things fail with 2.15.2 too. Spring frameworks are pretty good with compatibility handling and often newer Jackson versions work fine even if Spring version specifies older dependency.

@cowtowncoder I confirm, after updating to 2.15.2 it is still failing.

Thank you for confirming @Jancula.

The next step would, I think, be stand-alone reproduction (unit) test.

I was able to create a test case that fails:

public class JacksonMB181Test {
    @Test
    public void wholeEnchilada() throws Exception {
        final var om = new ObjectMapper();
        om.registerModule(new BlackbirdModule());
        final var val = om.writeValueAsString(Proxy.newProxyInstance(JacksonBBTest.class.getClassLoader(), new Class<?>[] { Beany.class }, (p, m, a) -> {
            if (m.getName().equals("a")) {
                return 42;
            }
            return null;
        }));
        assertThat(val).isEqualTo("{\"a\":42}");
    }

    public interface Beany {
        int getA();
    }
}
java.lang.RuntimeException: java.lang.IllegalAccessException: module jdk.proxy2 does not open jdk.proxy2 to unnamed module @2d4e282b
	at com.fasterxml.jackson.databind.util.ClassUtil.closeOnFailAndThrowAsIOE(ClassUtil.java:502)
	at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4626)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3869)
	at com.paywholesail.service.api.JacksonBBTest.wholeEnchilada(JacksonBBTest.java:16)
Caused by: java.lang.IllegalAccessException: module jdk.proxy2 does not open jdk.proxy2 to unnamed module @2d4e282b
	at java.base/java.lang.invoke.MethodHandles.privateLookupIn(MethodHandles.java:279)
	at com.fasterxml.jackson.module.blackbird.util.ReflectionHack$Java9Up.lambda$privateLookupIn$0(ReflectionHack.java:55)
	at com.fasterxml.jackson.module.blackbird.util.Unchecked.lambda$supplier$1(Unchecked.java:41)
	at com.fasterxml.jackson.module.blackbird.util.ReflectionHack$Java9Up.privateLookupIn(ReflectionHack.java:55)
	at com.fasterxml.jackson.module.blackbird.util.ReflectionHack.privateLookupIn(ReflectionHack.java:25)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.lambda$findProperties$0(BBSerializerModifier.java:67)
	at com.fasterxml.jackson.module.blackbird.util.Unchecked.lambda$runnable$0(Unchecked.java:31)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.findProperties(BBSerializerModifier.java:68)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.changeProperties(BBSerializerModifier.java:52)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanOrAddOnSerializer(BeanSerializerFactory.java:415)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanOrAddOnSerializer(BeanSerializerFactory.java:295)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:240)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:174)
	at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1501)
	at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1449)
	at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:550)
	at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:828)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:308)
	at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4624)
	... 26 more

I opened #210 with a potential fix.