12 Replies Latest reply on Nov 7, 2007 4:39 PM by Scott Stark

    Instance annotations from Object Models

    Adrian Brock Master

      I've written two simple examples of how to load instance annotations from
      Object Models (xml).

      PREPOPULATE

      The first one works the same way as the MC and as I understand it the EJB3 container
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/scope/test/PopulateMetaDataRepositoryUnitTestCase.java
      It explicitly adds the annotations to the mutable metadata context of the component instance
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/scope/support/TestComponentMetaDataRepositoryPopulator.java

      METADATA LOADER

      The second takes a more lazy approach
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/scope/test/LoaderMetaDataRepositoryUnitTestCase.java
      instead of populating the context up front, it installs a MetaDataLoader
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/scope/support/TestComponentMetaDataRepositoryLoader.java
      that will retrieve the annotations from the Object Model on the fly
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/scope/support/TestComponentMetaDataLoader.java

      THE TESTS:

      The tests are fairly trivial, they both do the same thing.

      There is one test that uses an annotated class and another that uses an
      unannotated class but supplies the annotation via the instance metadata.

      An AOP proxy is created for each to show AOP can read both the class metadata
      and the instance metadata when applying pointcuts and at runtime.
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/deployers-impl/src/tests/org/jboss/test/deployers/scope/support/TestComponentCreator.java

      The tests then check that an aspect based on the annotation is being used
      with the aspect retrieving the annotation in question.

      METADATA POPULATION DEPLOYERS

      The two alternate deployers that populate the instance metadata
      both do two steps.

      1) They add an AnnotatedElementMetaDataLoader for the class of the deployment component, this is the class scope that is also added to the deployment unit's scopeKey
      so it appears in the full contextual metadata retrieved from DeploymentUnit.getMetaData()
      and passed to AOP.

      2) They maintain the instance metadata using one of the two mechanisms described
      above.

      FOR THE REAL THING

      On the MetaDataLoader approach, I've cheated in the test by making the object
      model just have a list of class annotations. In practice, it would need to be more complex
      in that it will have to navigate the object model in a less trivial way.

      It would also need to implement Method and Field annotation retrieval,
      an example of how to do this can be found in the "Class" MetaDataLoader:
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/container/src/main/org/jboss/metadata/plugins/loader/reflection/AnnotatedElementMetaDataLoader.java

      Obviously, the MetaDataLoader can do what it likes to create the annotations
      (even if the underlying model is not annotations).
      See the AnnotationCreator
      https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/container/src/main/org/jboss/annotation/factory/AnnotationCreator.java

      e.g.

      MyAnnotation annotation = (MyAnnotation) AnnotationCreator.createAnnotation("@com.acme.MyAnnocation(value=\"" + fromXML() + "\")", unit.getClassLoader());
      


      A BUG

      Finally, I found a bug in the AbstractDeploymentContext where the
      getMutableMetaData() wasn't finding the metadata correctly.
      The MemoryMetaDataLoader was wrapped in a MetaDataContext
      so it didn't recognise it. I've fixed this problem, but it will need
      an update of the snapshot if you want to use the prepopulate annotations
      approach.

        • 1. Re: Instance annotations from Object Models
          Bill Burke Master

          * I don't see how something like the EJB3 container could use any of this.

          * The AOP examples you give are all driven off of class level annotations. Where are the method/field driven ones?

          • 2. Re: Instance annotations from Object Models
            Adrian Brock Master

             

            "bill.burke@jboss.com" wrote:
            * I don't see how something like the EJB3 container could use any of this.


            The EJB3 container already does something similar. The purpose of the change
            is to use the MetaDataRepository rather than the old AOP way.
            They are functionally equivalent, but the MetaDataRepository has additional
            features like defining your loader over the xml or defining application level metadata.


            * The AOP examples you give are all driven off of class level annotations. Where are the method/field driven ones?


            That isn't the purpose of the example. If you want to see method/field stuff look at
            what the MC does or aop-mc-int tests of aop proxy (or just look at the AOP advisor).

            • 3. Re: Instance annotations from Object Models
              Adrian Brock Master

              Since Carlo and Bill said they thought this complicated
              (the test is complicated to get things working in a similar way to EJB3 :-)

              This post just explains that the only real change is to replace EJB3's use
              of AOP's AnnotationRepository
              http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/aop/trunk/aop/src/main/org/jboss/aop/annotation/AnnotationRepository.java?revision=63589&view=markup

              with the MetaDataRepository's MutableMetaDataLoader
              http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/microcontainer/trunk/container/src/main/org/jboss/metadata/spi/loader/MutableMetaDataLoader.java?revision=55064&view=markup
              which is made up of the following interfaces
              http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/microcontainer/trunk/container/src/main/org/jboss/metadata/spi/MutableMetaData.java?revision=60565&view=markup
              http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/microcontainer/trunk/container/src/main/org/jboss/metadata/spi/retrieval/MetaDataRetrieval.java?revision=65047&view=markup

              AOP Supports both. The big difference is that the MetaDataRepository uses many scopes.
              e.g. you can annotations at Class, Instance (XML), Application, Deployment, etc.
              and supports non-annotations.

              To explain the later, take the SecurityDomain in EJB2 as an example.

              There can be a Deployment level one at the top of jboss.xml, it could potentially
              be annotated on the class (it's not currently in EJB2)
              and finally it can appear at the EJB level (instance) in jboss.xml.

              With the MetaDataRepository scopes, it would be trivial to extend this to provide
              a Server level SecurityDomain. i.e. every EJB uses a default security domain
              unless it specifies otherwise.

              • 4. Re: Instance annotations from Object Models
                Scott Stark Master

                The way I see it, the Ejb3DescriptorHandler should not be using the AnnotationRepository, nor its MetaDataRepository replacement. Rather, the annotations should be another source of data for the org.jboss.metadata.* pojos.

                There are two ways this can be done. One would be to create another merged view similar to how the standard metadata is merged into the jboss metadata. Defining a merge(AnnotatedElement) api to map the annotations onto the jboss metadata view would be needed.

                The second would be to create a separate wrapped view similar to how the standardjboss.xml is handled. The wrapped view would be MetaDataRepository aware and look to it for the annotation based metdata. This is the approach I think is cleanest.

                • 5. Re: Instance annotations from Object Models
                  Adrian Brock Master

                   

                  "scott.stark@jboss.org" wrote:
                  The way I see it, the Ejb3DescriptorHandler should not be using the AnnotationRepository, nor its MetaDataRepository replacement. Rather, the annotations should be another source of data for the org.jboss.metadata.* pojos.

                  There are two ways this can be done. One would be to create another merged view similar to how the standard metadata is merged into the jboss metadata. Defining a merge(AnnotatedElement) api to map the annotations onto the jboss metadata view would be needed.

                  The second would be to create a separate wrapped view similar to how the standardjboss.xml is handled. The wrapped view would be MetaDataRepository aware and look to it for the annotation based metdata. This is the approach I think is cleanest.


                  That doesn't solve the problem.

                  The issue is making the xml look like annotations such that EJB3's AOP configuration
                  (which works off annotations to enable adivces) can see the configuraiton from the xml.

                  • 6. Re: Instance annotations from Object Models
                    Carlo de Wolf Master

                    Note that the example works on a MC bean instance. I don't have a MC bean instance, I got an (EJB) class.

                    • 7. Re: Instance annotations from Object Models
                      Adrian Brock Master

                       

                      "wolfc" wrote:
                      Note that the example works on a MC bean instance. I don't have a MC bean instance, I got an (EJB) class.


                      So what? A class is a class whether it's an MC bean, an EJB or a Servlet that is your component deployment.

                      • 8. Re: Instance annotations from Object Models
                        Scott Stark Master

                         

                        "adrian@jboss.org" wrote:

                        That doesn't solve the problem.

                        The issue is making the xml look like annotations such that EJB3's AOP configuration
                        (which works off annotations to enable adivces) can see the configuraiton from the xml.

                        I don't see this type of processing in the Ejb3DescriptorHandler, is it there or somewhere else? I'm looking at the standard javaee annotations which affect the org.jboss.metadata.


                        • 9. Re: Instance annotations from Object Models
                          Scott Stark Master

                           

                          "wolfc" wrote:
                          Note that the example works on a MC bean instance. I don't have a MC bean instance, I got an (EJB) class.

                          I'm working on a testcase in the metadata project that illustrates what I'm talking about in terms of a wrapped/proxied jboss view that builds metadata from annotations from the ejb, interceptor, servlet, etc. classes. I"ll post it later today when I get it done.


                          • 10. Re: Instance annotations from Object Models
                            Scott Stark Master

                            See the org.jboss.test.metadata.annotation.repositoryMetaDataRepositoryUnitTestCase.testAnnotationMetaData test that shows what I'm talking about in terms of creating a JBossMetaData view that integrates the annotation based metadata.

                            An AnnotationMetaDataDeployer that runs during POST_CLASSLOADER would create such a view if the metadata is not complete, and annotations exist. It uses the org.jboss.metadata.annotation.* stuff Carlo started.

                            I'm still not clear on what is needed for the aop aspects configuration. This seems like a problem separate from the unified metadata view's requirement to incorporate deployment annotations.

                            • 11. Re: Instance annotations from Object Models
                              Adrian Brock Master

                               

                              "scott.stark@jboss.org" wrote:

                              I'm still not clear on what is needed for the aop aspects configuration.


                              The idea is to replace this code + related methods:
                               private void addEjbAnnotations(EJBContainer container,
                               JBossEnterpriseBeanMetaData enterpriseBean) throws Exception
                               {
                               if (enterpriseBean != null)
                               {
                               if (enterpriseBean instanceof JBossSessionBeanMetaData)
                               {
                               addHomeAnnotations(container, (JBossSessionBeanMetaData) enterpriseBean);
                              
                               addJndiAnnotations(container, (JBossSessionBeanMetaData) enterpriseBean);
                               }
                              
                               addInterceptorMethodAnnotations(container, enterpriseBean);
                              
                               handleResourceRefs(container, enterpriseBean.getResourceReferences());
                              
                               addMessageDestinationAnnotations(container, enterpriseBean.getMessageDestinationReferences());
                              
                               addSecurityIdentityAnnotation(container, enterpriseBean.getSecurityIdentity());
                              
                               addDependencies(container, enterpriseBean);
                              
                               addPoolAnnotations(container, enterpriseBean);
                              
                               addXmlAnnotations(container, enterpriseBean);
                              
                               if (enterpriseBean instanceof JBossSessionBeanMetaData)
                               {
                               addConcurrentAnnotations(container, (JBossSessionBeanMetaData)enterpriseBean);
                               addClusterAnnotations(container, (JBossSessionBeanMetaData)enterpriseBean);
                               addCacheAnnotations(container, (JBossSessionBeanMetaData)enterpriseBean);
                               }
                               }
                               }
                              


                              with something that loads into the INSTANCE mutable metadata.

                              My preference would be to make this a visitor pattern over the metadata itself,
                              e.g.
                              MutableMetaData mmd = deploymentUnit.getMutableMetaData();
                              MetaDataVisitor visitor = new MetaDataVisitor(mmd, ...);
                              visitor.visit(enterpriseBean);
                              


                              Which is much more extensible/maintainable and OO than the current EJB3 sutff.
                              Each part of the JavaEE/JBoss metadata can decide if/where it goes in the
                              annotation view.

                              • 12. Re: Instance annotations from Object Models
                                Scott Stark Master

                                 

                                "adrian@jboss.org" wrote:

                                ... with something that loads into the INSTANCE mutable metadata.

                                My preference would be to make this a visitor pattern over the metadata itself,
                                e.g.
                                MutableMetaData mmd = deploymentUnit.getMutableMetaData();
                                MetaDataVisitor visitor = new MetaDataVisitor(mmd, ...);
                                visitor.visit(enterpriseBean);
                                


                                Which is much more extensible/maintainable and OO than the current EJB3 sutff.
                                Each part of the JavaEE/JBoss metadata can decide if/where it goes in the
                                annotation view.


                                I see, which really just ends up replacing code like this:
                                 private void addClassAnnotation(EJBContainer container, Class<? extends Annotation> annotationClass, Annotation annotation)
                                 {
                                 log.debug("adding class annotation " + annotationClass.getName() + " to "
                                 + container + " " + annotation);
                                 container.getAnnotations()
                                 .addClassAnnotation(annotationClass, annotation);
                                 }
                                

                                where container.getAnnotations() is returning the AnnotationRepository.