7 Replies Latest reply on Apr 23, 2008 10:21 AM by Adrian Brock

    Annotation scanning

    Ales Justin Master

      OK, this issue is quite a blocker for few other JIRAs, and probably a good API changing candidate, meaning it needs to be done before CR1. :-)
      Not to mention that it spans over many areas, from AOP, EJBs, Seam, ... and even our MC will benefit from it.
      So, resolving this would relieve the pita of many. ;-)

      The initial discussion about starting this solution in classloading:
      - http://www.jboss.com/index.html?module=bb&op=viewtopic&t=132400

      And the root JIRA issue:
      - http://jira.jboss.com/jira/browse/JBCL-9

      So, what would be a good entry point into this in our classloading?
      Part of ClassLoadingPolicy?

      And the user hooks?
      We discussed it could be similar to Java6 APR:
      e.g.
      -
      http://java.sun.com/javase/6/docs/api/javax/annotation/processing/RoundEnvironment.html
      But instead on compiling, we could do this on class loading.

      And we should also consider our instance annotations. Which can kick in as late as in real deployment stage.

      How does this relate with the work we've done in metadata project?

        • 1. Re: Annotation scanning
          Kabir Khan Master

          One point: For the purposes of AOP, the classes must NOT be loaded when scanning for annotations. If they are loaded, then we can not do loadtime weaving. The annotation scanning should use javassist instead to look for annotations.

          • 2. Re: Annotation scanning
            Adrian Brock Master

             

            "alesj" wrote:

            So, what would be a good entry point into this in our classloading?
            Part of ClassLoadingPolicy?


            The entry point should be the module, which probably mean it delegates
            to the ClassLoadingPolicy (when the module is implemented by ClassLoadingPolicy :-)

            But this is only for the Class visitor.

            The rest of the annotation processing should be in the deployers project.

            To address Kabir'rs issue I'd suggest something like:
            public interface ClassVisitor
            {
             void visit(URL classURL, String className, ClassLoader cl);
            }
            


            So you can do URL.openStream() and pass it to javassit.

            • 3. Re: Annotation scanning
              Adrian Brock Master

               

              "adrian@jboss.org" wrote:

              To address Kabir'rs issue I'd suggest something like:
              public interface ClassVisitor
              {
               void visit(URL classURL, String className, ClassLoader cl);
              }
              



              Actually I'd suggest
              public interface ClassVisitor
              {
               void visit(ClassContext cc);
              }
              


              Then we can add new parameters and ease of use methods to ClassContext
              as required. e.g.
              ClassContext.getBytes();
              which will do all the work to open the stream and read the bytes from it.


              • 4. Re: Annotation scanning
                Scott Stark Master

                 

                "kabir.khan@jboss.com" wrote:
                One point: For the purposes of AOP, the classes must NOT be loaded when scanning for annotations. If they are loaded, then we can not do loadtime weaving. The annotation scanning should use javassist instead to look for annotations.

                If that's the case then to be general the metadata project/AnnotationMetaDataDeployer need to make this change. Currently they do load classes in the context of the deployment class loader during the POST_CLASSLOADER phase. We may be providing pass through support for other layers annotations though (webservices, rest, jpa) that need a view of the annotation. Are we going to have to pass the javassist view for these?

                • 5. Re: Annotation scanning
                  Adrian Brock Master

                   

                  "scott.stark@jboss.org" wrote:
                  "kabir.khan@jboss.com" wrote:
                  One point: For the purposes of AOP, the classes must NOT be loaded when scanning for annotations. If they are loaded, then we can not do loadtime weaving. The annotation scanning should use javassist instead to look for annotations.

                  If that's the case then to be general the metadata project/AnnotationMetaDataDeployer need to make this change. Currently they do load classes in the context of the deployment class loader during the POST_CLASSLOADER phase. We may be providing pass through support for other layers annotations though (webservices, rest, jpa) that need a view of the annotation. Are we going to have to pass the javassist view for these?


                  There's no problem with passing the annotations as long as we don't load
                  the classes that have those annotations until AOP has had the chance to enhance them.

                  i.e.
                  * parse the class file using javassist
                  * read the annotation and create metadata
                  * aop enhances the classes
                  * services load the enhanced class from the classloader

                  • 6. Re: Annotation scanning
                    Ales Justin Master

                    No idea where to start. :-)

                    "adrian@jboss.org" wrote:

                    The entry point should be the module, which probably mean it delegates
                    to the ClassLoadingPolicy (when the module is implemented by ClassLoadingPolicy :-)

                    Where in Module?
                    How/what to delegate to ClassLoaderPolicy (OK, probably preparing all these abstract methods that eventually get implemented in ClassLoaderPolicyModule)?
                    Who then triggers this?

                    "adrian@jboss.org" wrote:

                    But this is only for the Class visitor.

                    What are we visiting?
                    Or where do we get class url?

                    What's the info we're gathering?
                    Or how to keep it? MDR as we do in MC?

                    "adrian@jboss.org" wrote:

                    The rest of the annotation processing should be in the deployers project.

                    What do you consider as rest?

                    I can start hacking something on my own, but it's probably 99,9% chance of getting it wrong, if not even more. :-)


                    • 7. Re: Annotation scanning
                      Adrian Brock Master

                      I just did a ** COMPLETELY UNTESTED** commit that shows the basic outline
                      of how I think it should work.

                      See: svn diff -c 72623

                      Once this works, i.e. it is tested, you can write a generic annotation deployer
                      that runs off the module.

                      Something like:

                      public GenericAnnotationDeployer extends AbstractRealDeployer<Module>
                      {
                       public GenericAnnotationDeployer()
                       {
                       super(Module.class);
                       setStage(DeploymentStages.POST_CLASSLOADER);
                       }
                      
                       public void deploy(DeploymentUnit unit, Module module)
                       {
                       module.visit(new MyVisitor());
                       }
                      
                       public class MyVisitor extends ClassVisitor
                       {
                       public void visit(ResourceContext context)
                       {
                       // Annotation processing here
                       }
                       }
                      }
                      


                      This approach has a number of advantages:

                      1) This is a generic classloader resource visitor that understands the
                      classloading rules. i.e. nested roots are not processed twice, the
                      include/exclude filters are applied, etc.

                      2) Although the example above visits classes it is generic enough to work
                      for resources (or anything else you want to filter).

                      3) The current visit is implemented for the VFSClassLoader. But it could
                      be done for any classloader plugged in as a Module.

                      4) The VFS api is not exposed through this api so there can be no complaints
                      from other projects about JBoss dependencies. The ResourceContext
                      exposes things like the URL, name, classLoader, InputStream, bytes
                      of the resource which can be easily used in other projects.

                      5) It doesn't require any classloading to do the visit. It only requires
                      the classloader to exist. But this could be relaxed since we only require that
                      to include it in the ResourceContext in case somebody wants to actually
                      do classloading.

                      6) The deployer can get on with doing what it does best. Processing annotations
                      rather than worrying about classloading rules or where classes are located, etc.