Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google App Engine and Java org.reflection library - Error during the scan procedure

I'm trying to setup a ConfigurationBuilder for the library Reflections, which use the following configuration:

I'm using the library through a Maven dependency

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>

with the last available version, 0.9.10

Here is the 3 constraints which I need to apply to the scanner:

  • annotated with @Annotation1 or @Annotation2
  • declared in the package package1, package2 or package3
  • an extension of the class SuperClass.class

All the code is executed in a ServletContextListener (triggered and the start of the instance, of dev-server if localhost)

This is the code I managed to create

ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();

// Package filter
FilterBuilder scannerFilter = new FilterBuilder();
scannerFilter.includePackage("com.mypackage1");
scannerFilter.includePackage("com.mypackage2");
scannerFilter.includePackage("com.mypackage3");
configurationBuilder.filterInputsBy(scannerFilter);

// Select the proper location to scan
configurationBuilder.setUrls(Arrays.asList(ClasspathHelper.forClass(SuperClass.class)));

Reflections reflections = new Reflections(configurationBuilder);

// Get all the classes with annotation @Annotation1 or @Annotation2
Set<Class<?>> annotation1Classes = reflections.getTypesAnnotatedWith(Annotation1.class);
Set<Class<?>> annotation2Classes = reflections.getTypesAnnotatedWith(Annotation2.class);

but it does not works. This line

Reflections reflections = new Reflections(configurationBuilder);

triggers the following error:

ago 26, 2015 1:22:22 PM com.google.appengine.tools.development.agent.impl.Transformer transform
GRAVE: Unable to instrument javassist.bytecode.annotation.ShortMemberValue. Security restrictions may not be entirely emulated.
java.lang.RuntimeException
    at com.google.appengine.repackaged.org.objectweb.asm.MethodVisitor.visitParameter(MethodVisitor.java:114)
    at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.readMethod(ClassReader.java:959)
    at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.accept(ClassReader.java:693)
    at com.google.appengine.repackaged.org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
    at com.google.appengine.tools.development.agent.impl.Transformer.rewrite(Transformer.java:146)
    at com.google.appengine.tools.development.agent.impl.Transformer.transform(Transformer.java:113)
    at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
    at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:199)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at javassist.bytecode.AnnotationsAttribute.getAnnotations(AnnotationsAttribute.java:227)
    at org.reflections.adapters.JavassistAdapter.getAnnotationNames(JavassistAdapter.java:156)
    at org.reflections.adapters.JavassistAdapter.getClassAnnotationNames(JavassistAdapter.java:50)
    at org.reflections.adapters.JavassistAdapter.getClassAnnotationNames(JavassistAdapter.java:24)
    at org.reflections.scanners.TypeAnnotationsScanner.scan(TypeAnnotationsScanner.java:12)
    at org.reflections.scanners.AbstractScanner.scan(AbstractScanner.java:35)
    at org.reflections.Reflections.scan(Reflections.java:250)
    at org.reflections.Reflections.scan(Reflections.java:204)
    at org.reflections.Reflections.<init>(Reflections.java:129)
    at it.noovle.ape.core.persistence.objectify.ObjectifyManager.getClassesToRegister(ObjectifyManager.java:107)
    at it.noovle.ape.core.listener.ObjectifyServantLoader.contextInitialized(ObjectifyServantLoader.java:51)
    at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
    at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
    at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
    at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
    at org.mortbay.jetty.Server.doStart(Server.java:224)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:266)
    at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:288)
    at com.google.appengine.tools.development.AutomaticInstanceHolder.startUp(AutomaticInstanceHolder.java:26)
    at com.google.appengine.tools.development.AbstractModule.startup(AbstractModule.java:87)
    at com.google.appengine.tools.development.Modules.startup(Modules.java:105)
    at com.google.appengine.tools.development.DevAppServerImpl.doStart(DevAppServerImpl.java:258)
    at com.google.appengine.tools.development.DevAppServerImpl.access$000(DevAppServerImpl.java:47)
    at com.google.appengine.tools.development.DevAppServerImpl$1.run(DevAppServerImpl.java:213)
    at com.google.appengine.tools.development.DevAppServerImpl$1.run(DevAppServerImpl.java:211)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:211)
    at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:270)
    at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
    at com.google.appengine.tools.development.DevAppServerMain.run(DevAppServerMain.java:218)
    at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:209)

I should mention that I'm working on a Google App Engine project

I also tried starting from the sample provided in the home page

//scan urls that contain 'my.package', include inputs starting with 'my.package', use the default scanners
Reflections reflections = new Reflections("my.package");

//or using ConfigurationBuilder
new Reflections(new ConfigurationBuilder()
     .setUrls(ClasspathHelper.forPackage("my.project.prefix"))
     .setScanners(new SubTypesScanner(), 
                  new TypeAnnotationsScanner().filterResultsBy(optionalFilter), ...),
     .filterInputsBy(new FilterBuilder().includePackage("my.project.prefix"))
     ...);

but I'm unable to create a working code.


EDIT

Starting from the provided sample in the website (and through the use of JavaDoc) I managed to create another code

Reflections reflections = new Reflections(new ConfigurationBuilder()
        .setUrls(
                // Select the proper location to scan
                ClasspathHelper.forClass(SuperClass.class)
        )
        .setScanners(
                // Scan only the subtype of SuperClass
                new SubTypesScanner().filterResultsBy(
                        new FilterBuilder()
                            .include(SuperClass.class.getName())
                ),
                // Scan only the types which have the required annotations
                new TypeAnnotationsScanner().filterResultsBy(
                        new FilterBuilder()
                            .include(Annotation1.class.getName())
                            .include(Annotation2.class.getName())
                )
        )
        .filterInputsBy(
                // Include only 3 package in the analysis
                new FilterBuilder()
                    .includePackage("com.my.package1")
                    .includePackage("com.my.package2")
                    .includePackage("com.my.package3")
        )
);

Set<Class<?>> annotation1Classes  = reflections.getTypesAnnotatedWith(Annotation1.class);
Set<Class<?>> annotation2Classes  = reflections.getTypesAnnotatedWith(Annotation2.class);

This code works, as long as I use a main method to test the code (which I did to quickly test various lines of code instead of run every time the App Engine dev-server).

But the same code, executed by the App Engine dev-server triggers the exception error that I already posted above.

Then... the problem seems to be related to the App Engine server and not strictly to the Reflection code.


EDIT2

It is true that during the scan (with the App Engine environment) there is the exception throwned (many times I need to add, so many that the Eclipse console log cannot contains all the lines and it remove the oldest ones).

But those exception are not really thrown (a catch clause will be pointless) and at the end the scanner provides the correct classes.

At this point those exception seems to be only severe logs thrown by the Reflections constructor but they don't stop the execution of the server.

It remains only to understand why those exception are thrown, maybe it is related to the App Engine environment which block some inside feature of Java.


EDIT3

I tried to deploy the application to see what kind of behaviour there is on the production enviroment. Unlike the development environment (which logs a lot of severe exceptions) online there isn't any error logged but the scan result is 0 classes.

like image 274
Deviling Master Avatar asked Mar 02 '26 23:03

Deviling Master


1 Answers

After opening an issue to the project site, the issue has been solved with the help of Google Support, which has replied:

The java runtime team was able to track the issue down to a weirdly formatted class file in javassist (javassist/bytecode/ClassFile.class) where the major version indicates Java SE 6.0 but the code seems to have been compiled with Java 8 using Java 8 features.

As such, forcing javassist to a non-broken version should work, for example something like this:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
    <exclusions>
        <exclusion>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.18.2-GA</version>
</dependency>
like image 107
Deviling Master Avatar answered Mar 05 '26 13:03

Deviling Master