12 Replies Latest reply on Aug 7, 2009 9:32 AM by pmuir

    Java EE inter-module accessibility for Web Beans

    pmuir

      JSR-299 requires that [3]:

      Beans packaged in a certain Java EE module or library are available for injection, lookup and EL resolution to classes and
      JSP/JSF pages packaged in some other Java EE module or library if and only if the first module or library is required to be
      accessible to the other module or library by the Java EE platform specification.

      Note that, in some containers, a bean class might be accessible to some other class even when this is not required by the
      Java EE platform specification. For the purposes of this specification, a class is not considered accessible to another class
      unless accessibility is explicitly required by the Java EE platform specification.


      For Web Beans, we will require that the Java EE container provides the deployment structure information. My current proposal is to require the container to provide a BeanDeploymentArchive[1] instance per module/library. The BeanDeploymentArchive contains a list of other BeanDeploymentArchive which it can access, as well as a list o the classes and deployment descriptor it contains. In the case of an EJB module, the container additionally exposes the EJB metadata for that module [2].

      The Web Beans bootstrap would require the root BeanDeploymentArchive as an input. In the case of a EAR, the root BeanDeploymentArchive would return an emtpy class iteration, and null for the beans.xml URL, and accessible modules/libraries as normal.

      I'm interested in feedback both on the API design (and how well it matches EE class accessibility rules in other's opinions), and on how to implement this in JBoss AS.

      [1]https://svn.jboss.org/repos/webbeans/ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/spi/BeanDeploymentArchive.java
      [2]https://svn.jboss.org/repos/webbeans/ri/trunk/spi/src/main/java/org/jboss/webbeans/ejb/spi/EJBModule.java
      [3]http://in.relation.to/Bloggers/JSR299ProposedFinalDraftSubmitted#attachment1, Section 5.1

        • 1. Re: Java EE inter-module accessibility for Web Beans
          pmuir

           

          "pete.muir@jboss.org" wrote:
          JSR-299 requires that [3]:
          The Web Beans bootstrap would require the root BeanDeploymentArchive as an input. In the case of a EAR, the root BeanDeploymentArchive would return an emtpy class iteration, and null for the beans.xml URL, and accessible modules/libraries as normal.


          Unfortunately this design fails to take account of the fact that bean deployment archives may be added programmatically by CDI extensions (which may define Beans based on classes in other deployment archives). To allow for this I've added in a deployment as a first class construct [4].

          The loadBeanDeploymentArchive method allows programmatic retrieval/addition of a BeanDeploymentArchive. If this deployment archive wasn't previously recognised as a bean deployment archive, it is added to the deployment archive graph at this point. Having completed the initialization step which allows custom bean definition, the bean deployment archive graph is re-read by Web Beans, and used to apply accessibility rules at runtime.

          This also corrects the weirdness in making an EAR a BeanDeploymentArchive. In the case of an EAR it would list modules such as a war WEB-INF/classes, an EJB jar or libraries as it's accessible archives; in the case of a war, it would list WEB-INF/classes and libraries.

          [4] https://svn.jboss.org/repos/webbeans/ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/spi/Deployment.java

          • 2. Re: Java EE inter-module accessibility for Web Beans
            alesj

            I've implemented an initial version of this - it's commited in the WB-ri-int trunk.

            But thinking about it, the Deployment API seems wrong or useless. :-)
            At least in the way it's then currently used.

            The issues I see are the following:
            (a) why "List of BDAs" or what determines the order
            (b) "Circular dependencies will be detected and ignored by the container"

            I though the whole point of having BeanDeploymentArchive was to be able to get all accessible BDA's.
            e.g. one jar in ear sees all other jars, but doesn't see war's classes/ and lib/*.jar

            Currently I just map the hierarchy/structure,
            but this seems pretty much the same as existing flat Deployment.

            Perhaps all we need is getAccessibleBDAs on BDA?

            • 3. Re: Java EE inter-module accessibility for Web Beans
              alesj

               

              "alesj" wrote:
              I've implemented an initial version of this

              Ah, forgot to mention that it's not complete. :-)

              I'm missing a way to get all EJBs per this BDA.
              e.g. per Module and per URL/jar --> how to get EJBs, as definition might be split: interfaces in one jar, impl in another

              • 4. Re: Java EE inter-module accessibility for Web Beans
                wolfc

                Interfaces are always accessible on the CP for EJB impls. The BDA containing the EJBs should have no trouble returning them.

                • 5. Re: Java EE inter-module accessibility for Web Beans
                  pmuir

                   

                  Perhaps all we need is getAccessibleBDAs on BDA?


                  There are two differences between Deployment and BeanDeploymentArchive.

                  First is to allow representing both EAR and WAR. Whilst it would be sensible to represent a WAR as a BDA, it wouldn't make sense to represent an EAR as a BDA (it doesn't have any classes in it, it doesn't have any beans.xml in it).

                  Second is that Deployment supports loadBeanDeploymentArchive which allows Web Beans to discover which BDA any class in the classpath is in.

                  For example, take an archive (not CDI enabled) like:

                  foo.jar
                  - Foo.class

                  some user might, using a CDI API, add a custom Bean to application which uses Foo as it's "beanClass". At this point WB needs to know where Foo fits into the accessibility graph, and hence which EE modules can load it. At this point WB will call loadBeanDeploymentArchive(Foo.class) so it can associate the custom bean with it's accessiblity rules. It's further complicated by the fact that the BDA returned at this point wasn't previously a BDA, so needs adding into the accessibility hierarchy (so WB will re-request the entire graph after the deployment phase in which users can add beans).

                  • 6. Re: Java EE inter-module accessibility for Web Beans
                    alesj

                    And we'll also need to change how we gather all container names to declare dependency on them:

                     // call dynamic dependency creator for EJBs
                     ParameterMetaDataBuilder install = bootstrap.addInstallWithParameters("createDepenencies", "DynamicDependencyCreator", null, ControllerState.CONFIGURED);
                     install.addParameterMetaData(Object.class.getName(), bootstrapName);
                     install.addParameterMetaData(Iterable.class.getName(), bootstrap.createInject(ejbServicesValue.getUnderlyingValue(), "ejbContainerNames"));
                    



                    • 7. Re: Java EE inter-module accessibility for Web Beans
                      pmuir

                       

                      "alesj" wrote:
                      I've implemented an initial version of this - it's commited in the WB-ri-int trunk.

                      But thinking about it, the Deployment API seems wrong or useless. :-)


                      Remember that what the EE spec(s) provide are accessibility rules for classes, not a classloading structure. It's possible to implement the rules in fairly flat, simple fashion, as JBoss does. It would also be possible to produce a much more rigid, hierarchical structure that implements the rules. WB is the RI of 299, so needs to support any impl of the rules.

                      But let's take another case entirely - an OSGi container - here there are some complex rules based on imports that define what classes are and aren't accessible, and this structure needs to be able to represent this too.

                      (a) why "List of BDAs" or what determines the order


                      What order? Order isn't particularly important, CDI supports multiple beans that resolve to the same type/binding. It narrows these down itself.

                      I guess I can add some note to the API that the returned list should be ordered in the way the CL would read archives for classloading.

                      (b) "Circular dependencies will be detected and ignored by the container"


                      It's quite easy to define a circular accessibility structure such as:

                      ejb-jar1.jar defines it can access ejb-jar2.jar, and ejb-jar2.jar defines it can access ejb-jar1.jar. In this case you would add ejb-jar1.jar to the BDA list for ejb-jar2.jar, and ejb-jar2.jar to the BDA list for ejb-jar1.jar.

                      I though the whole point of having BeanDeploymentArchive was to be able to get all accessible BDA's.
                      e.g. one jar in ear sees all other jars, but doesn't see war's classes/ and lib/*.jar

                      Currently I just map the hierarchy/structure,
                      but this seems pretty much the same as existing flat Deployment.


                      Yes it is - and tbh I didn't expect much more complex for JBoss AS as it uses a very flat classloading structure.

                      Things I want to check we support:

                      * using an ejb-jar not deployed inside the app, but deployed at the top level
                      * using extensions defined in manifest.mf http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes and http://java.sun.com/javase/6/docs/technotes/guides/extensions/spec.html



                      • 8. Re: Java EE inter-module accessibility for Web Beans
                        pmuir

                         

                        "alesj" wrote:
                        I'm missing a way to get all EJBs per this BDA.
                        e.g. per Module and per URL/jar --> how to get EJBs, as definition might be split: interfaces in one jar, impl in another


                        "wolfc" wrote:
                        Interfaces are always accessible on the CP for EJB impls. The BDA containing the EJBs should have no trouble returning them.


                        The dependence is on the EJB, not it's interface definition. In practice, this means they should be defined as present in the BDA which defines their implementation, as Carlo says. If the interface isn't loadable by the impl, then you have a classloading problem anyway, and you won't get as far as starting WB.

                        • 9. Re: Java EE inter-module accessibility for Web Beans
                          alesj

                           

                          "pete.muir@jboss.org" wrote:

                          Yes it is - and tbh I didn't expect much more complex for JBoss AS as it uses a very flat classloading structure.

                          This is what we currently have.
                          But this can easily change once we have proper jboss-classloading.xml files to limit public API exposure, ...

                          "pete.muir@jboss.org" wrote:

                          * using an ejb-jar not deployed inside the app, but deployed at the top level

                          You mean we should be able to track external EJBs and add them as accessible BDA?

                          How does this again play with all listed BDAs and circularity problem?
                          e.g. if I list it in one WB app Deployment/BDAs, I them must exclude it in another (its original app) ...

                          "pete.muir@jboss.org" wrote:

                          * using extensions defined in manifest.mf http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes and http://java.sun.com/javase/6/docs/technotes/guides/extensions/spec.html

                          This looks like normal manifest lib listing, and is already supported - while building classpath.
                          Hence it should already be included in the recent new impl.

                          • 10. Re: Java EE inter-module accessibility for Web Beans
                            pmuir

                             

                            "alesj" wrote:

                            "pete.muir@jboss.org" wrote:

                            * using an ejb-jar not deployed inside the app, but deployed at the top level

                            You mean we should be able to track external EJBs and add them as accessible BDA?

                            How does this again play with all listed BDAs and circularity problem?
                            e.g. if I list it in one WB app Deployment/BDAs, I them must exclude it in another (its original app) ...


                            Exactly, this is why Web Beans allows the container to put circularities into the BDA graph. Inside Web Beans we remove the cycles by removing the first BDA to reoccur when we walk a particular path by tracking what BDAs we have already seen in this path. This is why the Javadoc says "Circular dependencies will be detected and ignored by the container" - thats not very clear, it now says "Cycles in the accessible BeanDeploymentArchive graph are allowed. If a cycle is detected by Web Beans, it will be automatically removed by Web Beans. This means any implementor of this interface don't need to worry about circularities."

                            Note that the graph can only be changed during deployment, at runtime it is static and we can cache the transitive closure of BDAs a BDA can access which means we have low overhead.

                            Of course, the container may already have a non-circular structure in place, so that could be

                            "pete.muir@jboss.org" wrote:

                            * using extensions defined in manifest.mf http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html#Main%20Attributes and http://java.sun.com/javase/6/docs/technotes/guides/extensions/spec.html

                            This looks like normal manifest lib listing, and is already supported - while building classpath.
                            Hence it should already be included in the recent new impl.


                            Great. We will add some TCK tests soon to verify this deployment structure, so we'll get results then :-)

                            • 11. Re: Java EE inter-module accessibility for Web Beans
                              alesj

                               

                              "pete.muir@jboss.org" wrote:

                              Note that the graph can only be changed during deployment, at runtime it is static and we can cache the transitive closure of BDAs a BDA can access which means we have low overhead.

                              I'm still not sure this is sufficient.

                              Afais we need two distinct BDAs methods
                              (a) one that is used at initialization -> non-circular
                              (b) one that exposes accessible BDAs from a current BDA

                              This way a user could use (b) to examine current BDA and its accessible BDAs for potential WB match; injection points, types, whatever exists in WB, ...

                              "pete.muir@jboss.org" wrote:

                              Great. We will add some TCK tests soon to verify this deployment structure, so we'll get results then :-)

                              I think the best approach is to get some test to fail/expose some issues you cannot handle with the current impl,
                              and I'll have a look and properly implement that.

                              The architecture is now in place to easily swap the behavior,
                              I might even port back the old-new impl you reverted if I see it fits,
                              or I'll do a complete new hack . :-)

                              • 12. Re: Java EE inter-module accessibility for Web Beans
                                pmuir

                                I talked to Ales about this.

                                The first confusion was that Ales didn't think that WB would work with circularities in the BDA graph - it will. I have updated the JavaDoc to be clearer that circularities in the BDA graph are allowed. Note that the current WB impl doesn't support circularities completely - this code is to be finished.

                                Secondly, we agreed to change all SPI methods from Iterable -> Collection to allow more flexibility on both the integrator and Web Beans sides.