1 2 3 4 5 6 Previous Next 77 Replies Latest reply on Oct 21, 2010 6:45 AM by alesj Go to original post
      • 30. Re: Implementing a non-flat deployment for Weld Integration
        flavia.rainone

        Making myself clearer.

         

        Flavia Rainone wrote:

         

        public BeanDeploymentArchive loadBeanDeploymentArchive(Class<?> beanClass)
           {
              // collection to mark the archives we have already searched
              Collection<Archive> searchedArchives = new HashSet<Archive>();
              // collection to mark the classpaths we have already searched
              Collection<Classpath> searchedClasspaths = new HashSet<Classpath>();
              // TODO -- why the search? beanClass' ClassLoader should be mapped to Archive?
              // need to throw an IllegalArgumentException if the Archive is not reachable from
              // the archives contained in the archives of this deployment
              Archive archive = findArchive(beanClass, archives, searchedArchives, searchedClasspaths);
              if (archive == null)
        

         

         

         

        Currently, findArchive method, invoked by loadBeanDeploymentArchive as shown above, walks through the Archive graph in order to find an Archive associated with the requested beanClass (i.e., an Archive that is associated with the same ClassLoader that loaded beanClass).

         

        If the Archive is not reachable in the graph, it means that we need to throw IllegalArgumentException.

         

        Ales suggested to replace the findArchive call by a lookup in a ClassLoader -> Archive map. That way, all I would need to do is looking up for the archive that corresponds to the beanClass CL. This is faster than walking through the Archive graph, but I wouldn't be able to know whether the Archive is reachable from the current Deployment or not, so I wouldn't be able to throw the IllegalArgumentException to point that beanClass is not visible to the current Deployment.

         

        Which way should I go? Should I forego the "is beanClass visible to this Deployment" check and follow Ales's suggestion, or should I keep things the way they are?

        • 31. Re: Implementing a non-flat deployment for Weld Integration
          pmuir

          How much of an efficiency saving is using the map over walking the graph?

          • 32. Re: Implementing a non-flat deployment for Weld Integration
            alesj

            How often is this - loadBeanDeploymentArchive - method used?

             

            Or, shouldn't the (potential) operation [Archive|Deployment]::isReachable(Archive other) be O(1),

            a simple hash lookup of pre-build reachable archives / deployments?

            • 33. Re: Implementing a non-flat deployment for Weld Integration
              pmuir

              Ales Justin wrote:

               

              How often is this - loadBeanDeploymentArchive - method used?

              Depends how many extensions are present, and how many beans/classes they add. It's used once per extension and once per bean or class it adds. So potentially, a lot...

               

              Or, shouldn't the (potential) operation [Archive|Deployment]::isReachable(Archive other) be O(1),

              a simple hash lookup of pre-build reachable archives / deployments?

              That seems sensible to me.

              • 34. Re: Implementing a non-flat deployment for Weld Integration
                alesj
                How often is this - loadBeanDeploymentArchive - method used?

                Depends how many extensions are present, and how many beans/classes they add. It's used once per extension and once per bean or class it adds. So potentially, a lot...

                OK, thought so as well. Just wanted to make sure. :-)

                Or, shouldn't the (potential) operation [Archive|Deployment]::isReachable(Archive other) be O(1),

                a simple hash lookup of pre-build reachable archives / deployments?

                That seems sensible to me.

                At least that's how I would impl things --> building proper indexes when things get deployed.

                So any potential lookup would be super simple aka fast.

                • 35. Re: Implementing a non-flat deployment for Weld Integration
                  flavia.rainone

                  Ales Justin wrote:

                   

                  How often is this - loadBeanDeploymentArchive - method used?

                   

                  Or, shouldn't the (potential) operation [Archive|Deployment]::isReachable(Archive other) be O(1),

                  a simple hash lookup of pre-build reachable archives / deployments?

                  I was mentioning keeping only a single map of CL->Archives and bypassing the is reachable check. My argument on this is that is it really possible that Weld will request for a non reachable beanClass? If the beanClass is not reachable from the current deployment CL, the code won't run, because the CL can't load beanClass. Thus, IMHO, I don't think that it is possible that Weld will ever request for a beanClass associated with an Archive that is not visible to the current Deployment. But, as I don't know nothing about Weld implementation, I'm hoping that Pete or Ales will answer this question

                   

                  Having a pre-built map of reachable archives is totally a different story, i.e., more complex to implement and will incur at an extra cost to maintain (I have again to walk through the graph to be able to define which archives are visible, this time it won't be done at every loadBeanDeploymentArchive request; but it will be done for every pre-existing deployment at every new deployment, and the cost will increase according to the number of Archives we have in Default Domain).

                  • 36. Re: Implementing a non-flat deployment for Weld Integration
                    pmuir

                    If a class can't be loaded by the classloader then I can't see how Weld would end up with the Class object to pass to loadBeanDeploymentArchive...

                    • 37. Re: Implementing a non-flat deployment for Weld Integration
                      flavia.rainone

                      Pete Muir wrote:

                       

                      If a class can't be loaded by the classloader then I can't see how Weld would end up with the Class object to pass to loadBeanDeploymentArchive...

                      In that case, the "is reachable check" is pointless and I'm replacing the current implementation of loadBDA by one that uses a singleton map of CL->Archives.

                      • 38. Re: Implementing a non-flat deployment for Weld Integration
                        alesj

                        If a class can't be loaded by the classloader then I can't see how Weld would end up with the Class object to pass to loadBeanDeploymentArchive...

                        In that case, the "is reachable check" is pointless and I'm replacing the current implementation of loadBDA by one that uses a singleton map of CL->Archives.

                        How did we then decide to handle library archives?

                        Or, actually, how did you implement it?

                         

                        Or what happens if you push in a java.* Class instance into this loadBDA method?

                        • 39. Re: Implementing a non-flat deployment for Weld Integration
                          flavia.rainone

                          Ales Justin wrote:

                           

                          How did we then decide to handle library archives?

                          Or, actually, how did you implement it?

                           

                          As I told you last Friday, on our MC team call, this is something that I'll do later this week, as I think that the majority of the work is in integrating the current deployers to AS trunk and have this tested.

                           

                          We decided to add some stuff to bootstrap that would scan the lib dirs searching for jars that contain the META-INF/beans.xml file. On the first BDA request, we would then create the BDA(s) for those jars.

                           

                          Ales Justin wrote:

                           

                          Or what happens if you push in a java.* Class instance into this loadBDA method?

                           

                          It will create a BDA for the bootstrap ClassLoader and add the requested class to the BDA before returning it. This is not affected by the search algorithm (i.e., it doesn't matter whether we use the graph to search for the Archive, or whether we use a map), as the search will return a null Archive and loadBDA will then create an Archive for the requested Class:

                           

                           

                                Archive archive = findArchive(beanClass, archives, searchedArchives, searchedClasspaths);
                                if (archive == null)
                                {
                                   boolean reachable = false;
                                   for (Archive searchedArchive: searchedArchives)
                                   {
                                      if (searchedArchive.isClassVisible(beanClass))
                                      {
                                         reachable = true;
                                         break;
                                      }
                                   }
                                   if (!reachable)
                                      throw new IllegalArgumentException("Bean class " + beanClass + " is not reachable from deployment " + this);
                                   ArchiveInfo archiveInfo = new ArchiveInfo(SecurityActions.getClassLoader(beanClass));
                                   archive = ArchiveFactory.createArchive(archiveInfo, new ArrayList<EjbDescriptor<?>>());
                                   if (loadedArchives == null)
                                   {
                                      loadedArchives = new ArrayList<Archive>();
                                   }
                                   loadedArchives.add(archive);
                                }
                                archive.addClass(beanClass);
                                return archive.createBeanDeploymentArchive();
                          

                           

                          The only part that will change is that we won't do the isClassVisible check.  The requested class will be assumed to be visible to the current deployment, and we will stick only with the last lines, that crate the ArchiveInfo, the Archive, and the BDA.

                          • 40. Re: Implementing a non-flat deployment for Weld Integration
                            flavia.rainone

                            I'm having problems with this piece of code, located in org.jboss.weld.resources.ManagerObjectFactory:

                             

                             

                            public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception
                               {
                                  for (Entry<BeanDeploymentArchive, BeanManagerImpl> entry : Container.instance().beanDeploymentArchives().entrySet())
                                  {
                                     if (entry.getKey().getId().equals("flat"))
                                     {
                                        return entry.getValue().getCurrent();
                                     }
                                  }
                                  throw new NamingException(messageConveyer.getMessage(CANNOT_LOCATE_BEAN_MANAGER));
                               }
                            

                             

                            Pete, what would be the correct implementation for this?

                            • 41. Re: Implementing a non-flat deployment for Weld Integration
                              pmuir

                              Yes, we will need to replace the way we bind the BeanManager into JNDI as part of this. See http://docs.jboss.org/weld/reference/1.0.1-Final/en-US/html/ri-spi.html#d0e6301 - "Binding the manager in JNDI".

                               

                              Marius, do you have some ideas here?

                              • 42. Re: Implementing a non-flat deployment for Weld Integration
                                flavia.rainone

                                With a temporary workaround to the beanManager issue (simply replaced "entry.getKey().getId().equals("flat"))" by "entry.getKey().getClass().getName().contains("org.jboss.weld.integration.")") I ran into an issue involving the service registry. I'm not sure if this is related to the beanManager issue or not, but the problem is that Weld complains if a new BDA created by Deployment.loadBDA method has a clean service registry:

                                 

                                 

                                DEPLOYMENTS IN ERROR:
                                  Deployment "vfs:///home/fla/Development/projects/jbossas-trunk/testsuite/output/lib/weld-translator.ear_WeldBootstrapBean" is in error due to the following reason(s):
                                org.jboss.weld.exceptions.ForbiddenStateException: WELD-000117 Required service org.jboss.weld.injection.spi.EjbInjectionServices has not been specified, **ERROR**
                                
                                    at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:1370) [:2.2.0.Alpha6]
                                    at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:1316) [:2.2.0.Alpha6]
                                

                                 

                                 

                                So, I created a workaround to populate the loaded BDA service registry, just to see if the error would go away. DeploymentImpl initializes the loaded BDA service registry with a copy of the service registries of the BDAs contained in the DeploymentImpl (only services added during bootstrap).

                                 

                                This makes WeldNumberguessExampleUnitTestCase to pass, but WeldTranslatorExampleUnitTestCase still fails, stating that TranslatorControllerBean is ambigously defined:

                                 

                                DEPLOYMENTS IN ERROR:
                                  Deployment "vfs:///home/fla/Development/projects/jbossas-trunkLATEST/testsuite/output/lib/weld-translator.ear_WeldBootstrapBean" is in error due to the
                                following reason(s): org.jboss.weld.exceptions.DeploymentException: WELD-001414 Bean name is ambiguous. Name translator resolves to beans
                                [org.jboss.weld.bean-BaseClassLoader@62b92dc2{vfs:///home/fla/Development/projects/jbossas-trunkLATEST/build/target/jboss-6.0.0-SNAPSHOT/server/all/deployers/resteasy.deployer}-SessionBean-TranslatorControllerBean, org.jboss.weld.bean-BaseClassLoader@7e7186b{vfs:///home/fla/Development/projects/jbossas-trunkLATEST/testsuite/output/lib/weld-translator.ear}-SessionBean-TranslatorControllerBean],
                                **ERROR**
                                
                                    at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:1370) [:2.2.0.Alpha6]
                                    at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:1316) [:2.2.0.Alpha6]
                                    at org.jboss.deployers.plugins.main.MainDeployerImpl.checkComplete(MainDeployerImpl.java:968) [:2.2.0.Alpha6]
                                    at org.jboss.system.server.profileservice.deployers.MainDeployerPlugin.checkComplete(MainDeployerPlugin.java:82) [:6.0.0-SNAPSHOT]
                                    at org.jboss.profileservice.dependency.ProfileControllerContext$DelegateDeployer.checkComplete(ProfileControllerContext.java:125) [:0.1.0.Alpha1]
                                    at org.jboss.profileservice.plugins.deploy.actions.DeploymentStartAction.doPrepare(DeploymentStartAction.java:104) [:0.1.0.Alpha1]
                                    at org.jboss.profileservice.management.actions.AbstractTwoPhaseModificationAction.prepare(AbstractTwoPhaseModificationAction.java:100) [:0.1.0.Alpha1]
                                    at org.jboss.profileservice.management.ModificationSession.prepare(ModificationSession.java:87) [:0.1.0.Alpha1]
                                    at org.jboss.profileservice.management.AbstractActionController.internalPerfom(AbstractActionController.java:234) [:0.1.0.Alpha1]
                                

                                 

                                So, the problem is that Weld finds two EjbDescriptors of the same bean. One in the BDA that represents weld-translator.ear, included in the corresponding DeploymentImpl, and another one in the bda that has been loaded by the Deployment, representing resteasy.deployer.

                                 

                                If I still initialize the loaded BDA service registry with a copy of the other BDAs service registry, but this time adding a new, clean, JBossEJBServices to the loaded BDA serviceRegistry, and putting no EjbInjectionServices in it, I get a message complaining that the injection point has unsatisfied dependencies:

                                 

                                 

                                DEPLOYMENTS IN ERROR:
                                  Deployment "vfs:///home/fla/Development/projects/jbossas-trunkLATEST/testsuite/output/lib/weld-translator.ear_WeldBootstrapBean" is in error due to the following reason(s): org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies.  Injection point:  field org.jboss.test.deployers.weld.translator.ejb.TranslatorControllerBean.translator;  Qualifiers:  [@javax.enterprise.inject.Default()], **ERROR**
                                
                                    at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:1370) [:2.2.0.Alpha6]
                                    at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:1316) [:2.2.0.Alpha6]
                                

                                 

                                 

                                If anybody wants to retrace my steps, there is a patch attached to Jira that can be applied to JBoss AS trunk. You can check loadBDA implementation here.

                                 

                                So, what is expected from the ServiceRegistry of a newly created BDA? Should it be initialized with some services? Which ones?

                                • 43. Re: Implementing a non-flat deployment for Weld Integration
                                  flavia.rainone

                                  Ales Justin wrote:

                                   

                                  but it could be made optional to do this at boot time instead.

                                  The easiest way to do this would be to add a deployer and somesort of weld-lib repository service to the bootstrap process.

                                  e.g. part of bootstrap.xml sub-systems, which would simply take a set of lib locations to check,

                                  and spit out a set of lib jars that contain META-INF/beans.xml -- note, there is no Weld dependency, hence can be easily put into bootstrap


                                  Ales, why should I add it to bootstrap?

                                  I mean, can't I just scan the lib dirs as part of the first weld deployment instead of doing it on bootstrap? What are the advantages of doing otherwise?

                                  Another question: once I determine that a specific jar in lib has the META-INF/beans.xml file, what is the cleanest way of retrieving the corresponding lib ClassLoader?

                                  • 44. Re: Implementing a non-flat deployment for Weld Integration
                                    pmuir

                                    Looks like the problem is that the services have got a bit out of control in JBoss AS, and that JBossEjbServices has ended up being dual purposed as an EJB discovery mechanism, and as an impl of EjbInjectionServices. So when you copy it, you end up copying the discovered ejbs as well.

                                     

                                    I think the best course of action is to split the two bits of JBossEjbServices into it's two parts  - discovery and injection.