0

I'm trying to use FasterXML Jackson-Databind in order to load configuration from a JSON file.

My application uses AspectJ. Aspect J is loaded via the following command line switch: "-javaagent:target\aspectjweaver-1.6.12.jar".

When I try to load the configuration without starting AspectJ, everything works as usual.

When I try to load the configuration with AspectJ, I get the following error stack:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.lang.reflect.Proxy.newInstance(Proxy.java:717)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:708)
    at sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:239)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:229)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
    at java.lang.Class.initAnnotationsIfNecessary(Class.java:3079)
    at java.lang.Class.getAnnotation(Class.java:3038)
    at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:113)
    at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:66)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:202)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
    at java.lang.Class.initAnnotationsIfNecessary(Class.java:3079)
    at java.lang.Class.getAnnotation(Class.java:3038)
    at com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std.<clinit>(VisibilityChecker.java:170)
    at com.fasterxml.jackson.databind.ObjectMapper.<clinit>(ObjectMapper.java:261)
    at com.mytest.core.ConfigurationManager.loadConfiguration(ConfigurationManager.java:44)
    at com.mytest.core.ConfigurationManager.getOrLoadConfigurationData(ConfigurationManager.java:33)
    at com.mytest.core.ApplicationContext.getConfigruation(ApplicationContext.java:51)
    at com.mytest.core.services.FootprintsServiceClient.init(FootprintsServiceClient.java:43)
    at com.mytest.core.AppManager.init(AppManager.java:43)
    at com.mytest.core.AppManager.getInstance(AppManager.java:61)
    at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
    at io.demo.App.main(App.java:12)
Caused by: java.lang.NullPointerException
        at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:530)
        at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:448)
        at com.mytest.core.ConfigurationManager.loadConfiguration(ConfigurationManager.java:44)
        at com.mytest.core.ConfigurationManager.getOrLoadConfigurationData(ConfigurationManager.java:33)
        at com.mytest.core.ApplicationContext.getConfigruation(ApplicationContext.java:51)
        at com.mytest.core.services.FootprintsServiceClient.init(FootprintsServiceClient.java:43)
        at com.mytest.core.AppManager.init(AppManager.java:43)
        at com.mytest.core.AppManager.getInstance(AppManager.java:61)
        at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
        at com.sun.proxy.$Proxy3.<clinit>(Unknown Source)
        ... 29 more

I'll appreciate if you could point me to the root cause or to a recommended debugging technique.

Kind regards,

Nadav

EDIT Please note that I know what's null pointer is. My problem is that I'm getting NullPointerException from an instance of the ObjectMapper class, which is part of the Jackson framework.

nadavy
  • 1,755
  • 1
  • 18
  • 33

1 Answers1

1

Your annotation processor is re-entering itself. If you look through the stack trace from main upwards, you see:

at io.demo.App.main(App.java:12)
at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
at com.mytest.core.AppManager.getInstance(AppManager.java:61)

which starts to load Jackson

at com.fasterxml.jackson.databind.ObjectMapper.<clinit>(ObjectMapper.java:261)
at com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std.<clinit>(VisibilityChecker.java:170)
at java.lang.Class.getAnnotation(Class.java:3038)

VisibilityChecker line 170 has a static intialisation to load the annotations on the Std class, so this goes back into reflection and eventually:

at sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:239)

creates a proxy (implementation of an annotation?), which during class initialisation tries to go through an aspect again:

    at com.sun.proxy.$Proxy3.<clinit>(Unknown Source)
    at com.mytest.core.aspects.TestAspect.ajc$before$com_mytest_core_aspects_TestAspect$1$93e74aa7(TestAspect.aj:21)
    at com.mytest.core.AppManager.getInstance(AppManager.java:61)

and now we're back at AppManager.getInstance, line 61

    at com.mytest.core.ConfigurationManager.loadConfiguration(ConfigurationManager.java:44)
    at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:448)

and this is trying to construct an ObjectMapper before the ObjectMapper class initialisation has completed- which not surprisingly, causes an error.

I don't have a solution (as I'm not familiar enough with AspectJ), but that's the core of what's happening. Possibly something like setting a flag to indicate if the configuration is unloaded/loading/loaded, and avoiding trying to re-enter the configuration load while the configuration is actually loading.

araqnid
  • 127,052
  • 24
  • 157
  • 134