1 2 Previous Next 21 Replies Latest reply on Oct 28, 2008 12:54 PM by adrian.brock Go to original post
      • 15. Re: ClassLoader injection Scope issue
        alesj

         

        "adrian@jboss.org" wrote:

        Those sound overly complicated.
        The simplest fix would be in the component visitor, something like:

         protected static void addBeanComponent(DeploymentUnit unit, BeanMetaData bean)
         {
         DeploymentUnit component = unit.addComponent(bean.getName());
         component.addAttachment(BeanMetaData.class.getName(), bean);
        + String className = bean.getBean();
        + if (className != null)
        + component.getScope().addScope(CommonLevels.CLASS, className);
         }
        

        This is the code
        +
        + unit.addAttachment(ScopeBuilder.class, BeanMetaDataScopeBuilder.INSTANCE);
        +
         KernelControllerContext context = new AbstractKernelControllerContext(null, deployment, null);
         ScopeInfo scopeInfo = context.getScopeInfo();
        - if (scopeInfo != null)
        - {
        - mergeScopes(scopeInfo.getScope(), unit.getScope());
        - mergeScopes(scopeInfo.getMutableScope(), unit.getMutableScope());
        - }
        + scopeInfo.setScope(unit.getScope());
        + scopeInfo.setMutableScope(unit.getMutableScope());
         try
         {
         controller.install(context);
        @@ -190,4 +194,18 @@
         return new AbstractValueMetaData(unit.getClassLoader());
         }
         }
        +
        + private static class BeanMetaDataScopeBuilder extends DefaultScopeBuilder
        + {
        + private static final ScopeBuilder INSTANCE = new BeanMetaDataScopeBuilder();
        +
        + public ScopeKey getComponentScope(DeploymentContext context)
        + {
        + BeanMetaData bmd = context.getDeploymentUnit().getAttachment(BeanMetaData.class);
        + ScopeKey scopeKey = super.getComponentScope(context);
        + if (bmd != null && bmd.getBean() != null)
        + scopeKey.addScope(CommonLevels.CLASS, bmd.getBean());
        + return scopeKey;
        + }
        + }
         }

        But you're right, yours looks easier. :-)

        • 16. Re: ClassLoader injection Scope issue

           

          "adrian@jboss.org" wrote:

          But there's probably a reason why I didn't do that in the first place
          (other than I just forgot to do it? - which might actually be the real reason. :-)


          I think the reason why I didn't do it, is because it doesn't really work.

          To get close, DeploymentContext.getScope() would need a similar HACK to what is in
          KernelScopeInfo. i.e. use the deployment's classloader to convert the class name
          to a class in the CLASS scope level.

          But your example shows that the component/deployment's classloader
          isn't necessarily the correct classloader to do that.
          In fact, the correct classloader doesn't even exist yet.

          You do know whether you can use the deployment classloader
          bean.getClassLoader() == null
          but that doesn't help when it is not null. ;-)

          • 17. Re: ClassLoader injection Scope issue
            alesj

             

            "alesj" wrote:
            "adrian@jboss.org" wrote:

            The simplest fix would be in the component visitor

            But you're right, yours looks easier. :-)

            But yours doesn't work, where mine does. :-)

            Testing on AnnotatedBeansUnitTestCase.
            Need to check why is that ... since both look legit.

            • 18. Re: ClassLoader injection Scope issue

               

              "alesj" wrote:
              "alesj" wrote:
              "adrian@jboss.org" wrote:

              The simplest fix would be in the component visitor

              But you're right, yours looks easier. :-)

              But yours doesn't work, where mine does. :-)

              Testing on AnnotatedBeansUnitTestCase.
              Need to check why is that ... since both look legit.


              Neither of them work. See my comment about needing the className -> class HACK
              If somebody in a deployer does:

              unit.getMetaData().getAnnotation(Blah.class);
              


              The AnnotatedElementMetaDataLoader/ClassMetaDataRetrievalFactory
              is going to be very confused when it gets a class name instead of a class. :-)

              
               public MetaDataRetrieval getMetaDataRetrieval(Scope scope)
               {
               if (scope == null)
               throw new IllegalArgumentException("Null scope");
               if (CommonLevels.CLASS.equals(scope.getScopeLevel()) == false)
               throw new IllegalArgumentException("Not a class scope: " + scope);
              
               // Not a class
               Object qualifier = scope.getQualifier();
               if (qualifier instanceof Class == false)
               return null; // OOPS!!!!!!!!!!
              
               Class<?> clazz = Class.class.cast(qualifier);
               return new AnnotatedElementMetaDataLoader(clazz);
               }
              


              • 19. Re: ClassLoader injection Scope issue
                alesj

                 

                "alesj" wrote:

                But yours doesn't work, where mine does. :-)

                My mistake. :-(
                Coding faster then thinking ... :-)

                • 20. Re: ClassLoader injection Scope issue
                  alesj

                   

                  "adrian@jboss.org" wrote:

                  Neither of them work. See my comment about needing the className -> class HACK

                  I see.
                  What to do then?
                  Adding another hack to existing hack? :-)


                  • 21. Re: ClassLoader injection Scope issue

                     

                    "alesj" wrote:
                    "adrian@jboss.org" wrote:

                    Neither of them work. See my comment about needing the className -> class HACK

                    I see.
                    What to do then?
                    Adding another hack to existing hack? :-)


                    I think the closet you can get is:

                    1) Add the CLASS scope as we described above, but...
                    2) If bean.getClassLoader() == null add the real class to the CLASS scope level
                    using the deployment classloader to load the class
                    3) otherwise just use the class name.

                    Basically this means that if the bean is not using the deployment classloader
                    then unit.getMetaData() can't see the class annotations
                    (ClassMetaDataRetrievalFactory will return null for that metadata loader).

                    That seems like a fair restriction for this edge case and doesn't require
                    the HACK in the deployer's handling of scopes.

                    One change though is that it will be trying to load the bean class when it creates
                    the components. So it will be reporting an error in that earlier. You need to make
                    sure this error is understandable.
                    If you don't like this change, then you would have to introduce the HACK
                    to make it lazily load the class and update the scope key when getMetaData() is
                    first used.


                    1 2 Previous Next