3

I'm working on a JSR-303 validation framework for GWT. Some of you may have heard of it even though it is a small project. Here is gwt-validation.

In the old days (v1.0) it used a marker interface for each class and each class had metadata generated separately. This was bad because it was not part of the JSR-303 standard and we moved on to the next idea.

In version 2.0 it scans the classpath at runtime using Reflections. This is great. The downside is that it doesn't seem to be able to work inside of containerized environments or those with special restrictions.

This is probably my fault, look at the following code:

    //this little snippet goes through the classpath urls and ommits jars that are on the forbidden list.
    //this is intended to remove jars from the classpath that we know are not ones that will contain patterns
    Set<URL> classPathUrls = ClasspathHelper.forJavaClassPath();
    Set<URL> useableUrls = new HashSet<URL>();
    for(URL url : classPathUrls) {
        boolean use = true;
        for(String jar : this.doNotScanJarsInThisList) {
            if(url.toString().contains(jar)) {
                use = false;
                break;
            }
        }
        if(use) {
            useableUrls.add(url);
        }
        use = false;
    }       

    ConfigurationBuilder builder = new ConfigurationBuilder()
                                    .setUrls(useableUrls)
                                    .setScanners(   new TypeAnnotationsScanner(), 
                                                    new FieldAnnotationsScanner(), 
                                                    new MethodAnnotationsScanner(), 
                                                    new SubTypesScanner()
                                    )
                                    .useParallelExecutor()
                                    ;

    this.reflections = new Reflections(builder);

I'm using the filter to remove jars that I know can't have annotations in them that I'm interested in. As I mention this gives a huge speed boost (especially on large classpaths) but the ClasspathHelper.forJavaClassPath() that I'm basing this on probably isn't the best way to go in container environments. (e.g. Tomcat, JBoss)

Is there a better way or at least a way that will work with a container environment and still let my users filter out classes they don't want?

I've looked, some, into how the Hibernate Validation project (the reference implementation for JSR-303) and they appear to at least be using (at least in part) the Annotations Processing in Java 6. This can't be all of the story because that didn't show up until JDK6 and Hibernate Validator is JDK5 compatible. (See: hibernate documentation)

So, as always, there's more to the story.

I've read these threads, for reference:

  • About Scannotation which has been pretty much replaced by Reflections.
  • This one but it uses File and I'm not sure what the implications are of that in things like GAE (Google App Engine) or Tomcat.
  • Another that goes over a lot of the things I've talked about already.

These threads have only helped so much.

I've also read about the annotation processing framework and I must be missing something. It appears to do what I want but then again it appears to only work at compile time which I know isn't what is done by Hibernate Validator. (Can anyone explain how it does scanning? It works on GAE which means it can't use any of the IO packages.)

Further, would this code work better than what I have above?

Set<URL> classPathUrls = ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader());

Could that correctly get the classloader inside of a Tomcat or JBoss container? It seems scan a smaller set of classes and still finish okay.

So, in any case, can anyone help me get pointed in the right direction? Or am I just stuck with what I've got?

Community
  • 1
  • 1
Chris Ruffalo
  • 1,903
  • 12
  • 17

1 Answers1

0

You could take a look at Spring's annotation support. Spring can scan annotations in files (using asm IIRC), and works in and out of a container.

It may not be easy because it goes through Spring's Resource abstraction, but it should be doable to reuse (or extract) the relevant code.

Olivier Croisier
  • 6,139
  • 25
  • 34