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:
@Annotation1 or @Annotation2package1, package2 or package3SuperClass.classAll 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.
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.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With