1 2 Previous Next 29 Replies Latest reply on Jan 11, 2005 6:11 PM by Adrian Brock

    Resolving MetaData/Annotations

    Bill Burke Master

      I'd like to discuss the interfaces for how metadata and/or annotations are resolved.

      IMO, there are two types of metadata.

      Static metadata
      Dynamic metadata

      Dynamic metadata is defined on the context of the invocation, on a per invocation basis. Static metadata is defined at compile (annotations) or deployment time. Aspects need to be able to resolve both dynamic and static metadata.

      Aspects need to distinguish between static and dynamic data because they may want to be assured that the metadata they are obtaining is coming only from static configuration and not overriden dynamically at runtime by the calling client.

      Conversely, Aspects may want Dynamic metadata that overrides existing static metadata to give flexibility to the calling client.

      That's why I think there needs to be two separate apis. One to get/set metadata dynamically on the current joinpoint, and one to get at statically defined metadata.

      Basically, I think Joinpoint should be a static construct(it is immutable metadata defined at deployment time) that models closely after the java.lang.reflect package. THis will allow us to have one interface that can represent metadata for JMX, java.lang.reflect, and Javassist or any other model that requires joinpoint-like metadata.

      Another thing about metadata is the need to support JDK annotations. It is conceivable that we will want to override annotations at both the bean and class level. JBoss AOP can already support overriding at the class level.

      Also, regarding annotations, some of the aspects that I have written have the need to get metadata from the "invocationContext", statically from the joinpoint, and to also get metadata from the joinpoint's declaring class. That's why I think the Joinpoint class hierarchy needs to support some method like getDeclaringType that can return annotations of the joinpoint's declaring class.

      So, here's what this post boils down to. We need:

      * dynamic definable metadata per joinpoint(this can be typed or untyped) that can be defined by the calling client to override statically defined metadata.
      * statically definable metadata per joinpoint that can be resolved separately from the dynamic interface. Static data can be overriden by the container. (annotation overrides) but should be a deployment time thing.
      * We need the notion of getDeclaredType so that the aspect can obtain Class level annotation data.

      Bill

        • 1. Re: Resolving MetaData/Annotations
          Scott Stark Master

          Ok, so this is like the third thread discussing the same concept. I just see dynamic metadata as yet another scope, invocation. There is no reason why metadata defined at deployment time could not be updated dynamically via some admin operation. Repeating myself again, its not the dynamic nature of the metadata that defines whether or not is should be updatable. Its attribute of the metadata itself.

          As such, I don't see the benefit of two seperate apis. There needs to be a metadata framework that allows the various scoped to be merged and that conrols what scopes may be overriden.

          • 2. Re: Resolving MetaData/Annotations
            Adrian Brock Master

            I'm still don't see the need for two apis? I think we have a congnitive dissonance?

            Let's take the authorization interceptor as an example. There
            are a number of possible implementations (pseudo code):

            // Per join point

            public class AuthenticationInterceptor extends AbstractInterceptor
             implements JoinPointAware
            {
             private SecurityDomain domain;
             private String[] roles;
             private JoinPoint joinPoint;
             public void setJoinPoint(JoinPoint joinPoint)
             {
             this.joinPoint = joinPoint;
             domain = (SecurityDomain) joinPoint.getMetaData("Security", "Domain");
             roles = (String[]) joinPoint.getMetaData("Security", "Roles");
             }
            
             public Object invocation(Invocation invocation) throws Throwable
             {
             Principal principal = invocation.getMetaData("Security", "Principal");
             if (domain.authorize(principal, roles) == false)
             throw new SecurityException(principal + " not authorized for " + joinPoint.toHumanReadableString());
             return invocation.invokeNext();
             }
            }
            


            // Shared
            public class AuthenticationInterceptor extends AbstractInterceptor
            {
             public Object invocation(Invocation invocation) throws Throwable
             {
             Principal principal = invocation.getMetaData("Security", "Principal");
             domain = (SecurityDomain) invocation.getMetaData("Security", "Domain");
             roles = (String[]) invocation.getMetaData("Security", "Roles");
             if (domain.authorize(principal, roles) == false)
             throw new SecurityException(principal + " not authorized for " + invocation.toHumanReadableString());
             return invocation.invokeNext();
             }
            }
            


            Note: obviously joinPoint.getMetaData() will cascade through instance, class, vm
            and invocation through invocation, transaction, joinPoint, class, vm
            or whatever levels of metadata are defined.

            The problem with the latter implementations is that we know an invocation should not
            override the domain.
            So why not have an extra parameter where we can limit the contexts, e.g.
             domain = (SecurityDomain) invocation.getMetaData("Security", "Domain", Scope.JOIN_POINT);
            
             with:
            
             public Object getMetaData(String context, String id, Scope startScope);
            


            • 3. Re: Resolving MetaData/Annotations
              Adrian Brock Master

              It also unclear how the current AOP annotations/xml will feed into the configuration
              in particular with relation to dependencies.

              e.g. Take an EJB2 bean getting deployed into the microcontainer.
              The domain is defined not through annotations but from a mapping of jboss.xml
              metadata into some bean config inside the new kernel.

              jboss.xml

              <jboss>
               <security-domain>MyRealm</security-domain>
              ...
              </jboss>
              


              This needs to be transformed into a microcontainer configuration that
              waits for MyRealm to appear in JNDI before completing the EJB container
              construction.
              The registry style dependency is a feature all implemented in the current
              microcontainer code.

              What is clear to me is that this type of thing (whether it xml or annotations)
              needs to be transformed into some form of dependency injection
              on a metadata object otherwise the microcontainer isn't go to know the correct
              startup order:
              <bean ...>
               <attribute name="Context">Security</attribute>
               <attribute name="Id">Id</attribute>
               <attribute name="Object"><depends name="MyRealm" type="JNDI"/></attribute>
              


              • 4. Re: Resolving MetaData/Annotations
                Scott Stark Master

                 


                So why not have an extra parameter where we can limit the contexts, e.g.

                One disconnect here is why do we even know the scope should be limited? The only reason that the roles allowed for an invocation should not be overriable at the invocation level is that there is a clear conflict of aspects when a declarative security interceptor is involved. This same scenario can apply to any combination of attributes and interceptors that jboss has no knowledge of, so I view this a more a problem of expressing to the metadata framework what the constraints on a given piece of metadata are. The metadata chain is not just a heirarchical hash map.


                • 5. Re: Resolving MetaData/Annotations
                  Scott Stark Master

                   


                  What is clear to me is that this type of thing (whether it xml or annotations) needs to be transformed into some form of dependency injection on a metadata object otherwise the microcontainer isn't go to know the correct startup order:

                  | <bean ...>
                  | <attribute name="Context">Security</attribute>
                  | <attribute name="Id">Id</attribute>
                  | <attribute name="Object"><depends name="MyRealm" type="JNDI"/></attribute>
                  |


                  The internalized behavior that the ejb container performs with respect to the security domain needs to be externalized as a depenendency on the service supporting the interface(s) that the ejb container looks up from jndi. Its not that there is really a dependency on the binding existing in JNDI, there is a need for the authentication and authorization interfaces to be injected, and the implementing service is what there needs to be a dependency on.

                  The unusual detail of this particular case is that the service is the JaasSecurityManagerService, but it does not actually create a binding at the location referenced by the java:/jaas/MyRealm value. It just creates an ObjectFactory at java:/jaas such that the lookup of java:/jaas/MyRealm returns the security service implementation associated with the MyRealm configuration. So depenendcy is not on the existence of the JNDI binding, its on the state of the JaasSecurityManagerService that manages the supports the JNDI binding.


                  • 6. Re: Resolving MetaData/Annotations
                    Adrian Brock Master

                    Ok, but it still a registry dependency.

                    It could also be implemented as a plain dependency, bypassing the need for
                    a registry altogether.

                    Whichever way it is done, you still need the

                    <depends>

                    to tell the microcontainer about the startup ordering.

                    • 8. Re: Resolving MetaData/Annotations
                      Scott Stark Master

                       


                      So why not have an extra parameter where we can limit the contexts, e.g.


                      Actually, thinking about this some more, it does make some sense in the context of the security interceptor trying to enforce declarative security based on the deployment roles. The security interceptor does know as part of its behavior that it only cares about the roles from the deployment scope.

                      There still is the question of whether there should be controll over what scopes should allow for the introduction of a given piece of metadata. This is actually an intersection of security with metadata, so perhaps it could be punted to a security aspect on the metadata service.


                      • 9. Re: Resolving MetaData/Annotations
                        Bill Burke Master

                         

                        "adrian@jboss.org" wrote:
                        I'm still don't see the need for two apis? I think we have a congnitive dissonance?


                        Sure it fits with those two example, but consider the cases when you may not have an Invocation, but may only have a Joinpoint...

                        * The first is, I need a common Joinpoint model that spans both Javassist and java.lang.reflect so that the pointcut matching and aspect binding can be done with other model. Besides greatly simplifying the AOP code, it allows pointcut matching and advice binding to happen without have to load a class which will be incredibly useful for the IDE integration and precompiler. Currently all advice/interceptor binding happens at class load time.

                        Come to think of it, resolving metadata from a Joinpoint becomes even more important for the microcontainer as you may want to know all dependencies introduced by aspects before class load time.

                        * Second, the aspect may be getting knowledge of its dependency based on an annotation attached to the class it is aspectizing. Which leads me to your second question


                        It also unclear how the current AOP annotations/xml will feed into the configuration
                        in particular with relation to dependencies.


                        The security aspect is a perfect example here. The way I have it implemented now in my aspect code is that the security aspect is allocated via a JBoss AOP aspect factory. When the factory goes to create the aspect (on a per class or per EJB container basis) it queries the container for the @SecurityDomain annotation and based on that annotation, looks up the domain in JNDI.

                        So how will this work with XML? The way I'm going to implement is that the EJB 3 deployer creates the container and then parses the XML. It will see the
                        <security-domain>
                        element and allocate an instance of the @SecurityDomain annotation and add it as an override to the class. That way there is a consistent Object model for configuration (the annotation class). This also allows you to totally mix and match XML and annotations together.

                        Am I making sense now?



                        • 10. Re: Resolving MetaData/Annotations
                          Adrian Brock Master

                          I think the misunderstanding comes from the two different use cases.

                          In the pure AOP case you don't have all the dependencies and you are doing lazy
                          xml parsing.
                          i.e. this is the case where you are running inside somebody else's container
                          and expect all the dependencies to be satisfied.
                          This is a pure IOC play.

                          In the microcontainer (MC) we are going further. We don't make any assumption
                          about dependencies. We let the user specify everything upfront and then
                          through it at MC to sort out the correct order (including creating classloaders
                          binding/lookup to jndi, etc.)

                          • 11. Re: Resolving MetaData/Annotations
                            Adrian Brock Master

                             


                            * The first is, I need a common Joinpoint model that spans both Javassist and java.lang.reflect so that the pointcut matching and aspect binding can be done with other model. Besides greatly simplifying the AOP code, it allows pointcut matching and advice binding to happen without have to load a class which will be incredibly useful for the IDE integration and precompiler. Currently all advice/interceptor binding happens at class load time.


                            The join point model I wrote does not require classloading. In fact, I deliberatly
                            removed all notion of class/method/etc from the abstraction at the top level
                            so you can create any sort of join point.
                            Even for those class/method/field join points I keep to a String representation
                            of the join point since the classes may not actually be loaded at DESCRIBE
                            (define the deployment) time.


                            • 12. Re: Resolving MetaData/Annotations
                              Adrian Brock Master

                               



                              It also unclear how the current AOP annotations/xml will feed into the configuration
                              in particular with relation to dependencies.


                              The security aspect is a perfect example here. The way I have it implemented now in my aspect code is that the security aspect is allocated via a JBoss AOP aspect factory. When the factory goes to create the aspect (on a per class or per EJB container basis) it queries the container for the @SecurityDomain annotation and based on that annotation, looks up the domain in JNDI.


                              But you don't know at the aop level that the SecurityDomain has been deployed yet.


                              So how will this work with XML? The way I'm going to implement is that the EJB 3 deployer creates the container and then parses the XML. It will see the
                              <security-domain>
                              element and allocate an instance of the @SecurityDomain annotation and add it as an override to the class. That way there is a consistent Object model for configuration (the annotation class). This also allows you to totally mix and match XML and annotations together.


                              Incorrect. There should be no dependency on XML. All configuration should be
                              turned into generic MetaData java Object graph.
                              1) We don't want to depend on XML for configuration, e.g. could be programatic
                              and we don't want to use XML internally
                              2) The config might not be XML (e.g. IDE, annotations, etc)
                              or could be a different XML format e.g. different deployers can put the config in different places in different xml documents.
                              3) We need to parse the XML/annotations early to generate the deployment
                              order/dependencies before we try to deploy anything.

                              • 13. Re: Resolving MetaData/Annotations
                                Adrian Brock Master

                                 


                                Am I making sense now?


                                No, this doesn't explain the need for two different apis.

                                Let me clarify
                                MetaData getMetaData()
                                

                                is an abstraction and does not have to resolve to a chain of HashMaps.

                                At the container level all we are interested in asking the context for the relevent
                                metadata. Whether this originally came from xml, annotations, programmatic definition,
                                delegation to some central config repository is unimportant to us when writing an
                                interceptor/aspect.

                                It is important to us when we are deploying this metadata.

                                Let me also clarify, that most of this metadata should be done through IOC where
                                there is no requirement to "dynamically" change it based on context or we don't
                                want to share aspect instances across contexts.

                                public class AuthorizationInterceptor
                                {
                                 @Inject
                                 public void setSecurityDomain(SecurityDomain domain) {};
                                }
                                


                                • 14. Re: Resolving MetaData/Annotations
                                  Bill Burke Master

                                   

                                  "adrian@jboss.org" wrote:


                                  It also unclear how the current AOP annotations/xml will feed into the configuration
                                  in particular with relation to dependencies.


                                  The security aspect is a perfect example here. The way I have it implemented now in my aspect code is that the security aspect is allocated via a JBoss AOP aspect factory. When the factory goes to create the aspect (on a per class or per EJB container basis) it queries the container for the @SecurityDomain annotation and based on that annotation, looks up the domain in JNDI.


                                  But you don't know at the aop level that the SecurityDomain has been deployed yet.



                                  No you don't, but you need to query some service for the dependency. Here's why:

                                  AOP works with classes instances that may not be registered as beans in the kernel. Consider this:

                                  <bind expr="* @SecurityDomain->@Unchecked(..)">
                                   <interceptor-ref name="AuthenticationInterceptor"/>
                                  </bind>
                                  


                                  This states that any @Unchecked method of any class annotated with @SecurityDomain should have an authentication interceptor attached to it. The Authentication interceptor cannot be created without knowing the securit domain. So, the interceptor factory needs to ask the class for its @SecurityDomain annotation so that it can lookup the security domain.

                                  Another thing I'm not sure you understand yet is that aspect definitions are declared before the beans, classes, or object instances they aspectize are even known. The advice bindings themselves(as in the above example) can be declared before beans and classes are loaded as well. Without this ability there's no way to have an aspect library that are based on annotations. The advice/interceptor bind process does not happen until a class is loaded.

                                  The main problem here being is that sometimes the aspect cannot specify or know its dependencies until it is bound into the thing it is aspectizing.



                                  So how will this work with XML? The way I'm going to implement is that the EJB 3 deployer creates the container and then parses the XML. It will see the
                                  <security-domain>
                                  element and allocate an instance of the @SecurityDomain annotation and add it as an override to the class. That way there is a consistent Object model for configuration (the annotation class). This also allows you to totally mix and match XML and annotations together.


                                  Incorrect. There should be no dependency on XML. All configuration should be
                                  turned into generic MetaData java Object graph.



                                  That not what I'm saying at all. I'm saying config COULD come from XML and that the common meta objects are instances of annotations rather than YET ANOTHER metamodel. Annotations in and of themsleves are meta objects.


                                  The join point model I wrote does not require classloading. In fact, I deliberatly
                                  removed all notion of class/method/etc from the abstraction at the top level
                                  so you can create any sort of join point.
                                  Even for those class/method/field join points I keep to a String representation
                                  of the join point since the classes may not actually be loaded at DESCRIBE
                                  (define the deployment) time.


                                  1 2 Previous Next