5 Replies Latest reply on Jul 20, 2012 8:58 AM by pmuir

    Enabling Injectors in several jars issue

    dzcs

      Hi All,

      I have found out that the behaviour of weld in JBoss AS7 differs from weld for older containers. The point of my question is the following. For older containers I use weld 1.1.8.Final and as it says in reference documentation I register interceptors in the same jar where I define them by naming them in beans.xml, which is under META-INF. For weld servlet it was enough to register them and to enable them for whole war package. Example:

       

      war

      |- WEB-INF

              |- beans.xml                                -> just <beans></beans>

               |- web.xml                                   -> listener registration

               |- jbsoss-web.xml                        -> context path, realm name, ds mappings

               \- lib

                   | ...... jars

                  |- somename1.jar                    -> defines interceptors, binding annotations, producers

                   |          \- META-INF

                   |                  \- beans.xml         -> lists all interceptors in interceptors section

                  |

                   \- somename2.jar                    -> uses Injections (from producers above), annotations interceptor bindings defined in jar above.

                              \- META-INF

                                     \- beans.xml         -> just <beans></beans> to show that it must be controlled.

       

       

      Now I tried to do the same trick with AS7 (of course removing weld from war and removing weld listener in web.xml). So what - AS7 Weld was totally ignoring my registration of interceptors. As I found out it wants to have registration in the same jar where I use them - my interceptors. In my example it would be "somename2.jar". That means I have to remove list of interceptors from beans.xml in somename1.jar and insert this list of interceptors in beans.xml file in somename2.jar. Fine. It works. More over it is still working with my older container with weld listener enabled.

       

      Now. I have somename3 and somename4 jars, which are using my interceptors. If I follow the logic of AS7 I will have to register my interceptors in beans.xml of both jar archives. Only in this case it would work in AS7. But it would not work in older container, because weld will fail with exception that the interceptors enabled twice. - This is the issue number one.

       

      The second issue is that actually I dont whant that my application developer even know something about the interceptors which needs to be enabled in their jars. What they need to know, that if they annotate some class or some method with some special annotation the system will do something. I thought it was the main idea of the CDI to separate that concerns.

       

      Please correct me if I misunderstood anything. Any advices? Thank you in advance.

        • 1. Re: Enabling Injectors in several jars issue
          alesj

          I think you're right.

          Afaik, this is due to lack of exact spec on this topic.

           

          Env integration is part of Weld SPI, and AS7 has this different then plain servlet.

          The servlet part if pretty simple, flat deployment, where AS7 has more exact beans archive visibility.

           

          For this to work the same, we would need to enhance servlet integration.

          * https://github.com/weld/core/tree/master/environments/servlet

           

          For my sandbox apps, I usually have diff mvn profiles for diff envs.

          Which helps me push proper beans.xml files.

          It's a bit of pita, but it gets the job done.

          1 of 1 people found this helpful
          • 2. Re: Enabling Injectors in several jars issue
            dzcs

            What I didn't understood is where are you going to change the behavior in weld standalone or in as7? I think the right behavior has standalone version, because inside of web application it must be flat. I assemple my application from different jars and I can put one or another package with appropriate interceptor/producer set in libs.

             

            The application developer, say developer of restful services, should not be aware of which interceptors shall use his classes in his jar. He shall use binding annotations, injections, etc. and tell the system that his jar use CDI by including empty beans.xml in META-INF. It is not in responsibility of application developer to choose right interceptors. At the end when web application will be assembled the right set of jars can be included in web application lib which would enable (by their beans.xml) appropriate interceptors/producers set. It can be even decided to do not include interceptors in web application to avoid any interception.

             

            If the wish list still open then I would add some more wish. What the Weld shall also do is a check if producers are there for injection points, because absense of producers can cause problems. But check for interceptors IMHO can be optional. Normally it would not cause a problem. If both checks would be builtin to weld, then it would be nice to have a possibility to disable interception of some binding annotations.

            • 3. Re: Enabling Injectors in several jars issue
              alesj

              Well the CDI 1.0 spec defines the interceptors, decorators per bean archive.

              In this respect the servlet standalone impl is wrong.

              I do agree that this behavior is mostly more common, but the more fine grained - as per the spec - is also needed sometimes.

               

              I suggest you check with new CDI 1.1 spec.

              It does sound like a valid request; e.g. to have this configurable, etc.

              • 4. Re: Enabling Injectors in several jars issue
                struberg

                Ales, the spec is really clear about it.

                See section "12.1 Bean Archives":

                A library jar, EJB jar, application client jar or rar archive is a bean archive if it has a file named beans.xml in the
                META-INF directory.
                

                Further (exemplaric)

                In an application deployed as a war, the container searches every bean archive bundled with or referenced by the war. The bean archives might be library jars or the WEB-INF/classes directory.
                

                There is just nothing to discuss about the fact that the spec says that each JAR is a Bean Archive on it's own. What JBossAS7 does (special treatment of WEB-INF/beans.xml) is cool for users but not in sync with CDI-1.0. Btw in OpenWebBeans we agreed to completely ignore BDA in the default configuration and just treat whole WebApps as flat structure.

                 

                Please feel free to join this effort and help working on https://issues.jboss.org/browse/CDI-18 in which we try to define the new global enablement.

                • 5. Re: Enabling Injectors in several jars issue
                  pmuir

                  Mark Struberg wrote:

                   

                  Ales, the spec is really clear about it.

                  See section "12.1 Bean Archives":

                  A library jar, EJB jar, application client jar or rar archive is a bean archive if it has a file named beans.xml in the
                  META-INF directory.
                  

                  Further (exemplaric)

                  In an application deployed as a war, the container searches every bean archive bundled with or referenced by the war. The bean archives might be library jars or the WEB-INF/classes directory.
                  

                  There is just nothing to discuss about the fact that the spec says that each JAR is a Bean Archive on it's own. What JBossAS7 does (special treatment of WEB-INF/beans.xml) is cool for users but not in sync with CDI-1.0. Btw in OpenWebBeans we agreed to completely ignore BDA in the default configuration and just treat whole WebApps as flat structure.

                   

                  Please feel free to join this effort and help working on https://issues.jboss.org/browse/CDI-18 in which we try to define the new global enablement.

                   

                  Actually, that is exactly what it says, sorry Mark ;-)

                   

                  "library" is a specific term, defined by the Java EE specification, as defined in Section EE.8.2.

                   

                   

                  The Java EE platform provides several mechanisms for applications to use optional packages and shared libraries (hereafter referred to as libraries). Libraries may be bundled with an application or may be installed separately for use by any application.

                   

                  Here, we are talking about bundled libraries, and in your example, those bundled in a war:

                   

                  A web application may include libraries in the WEB-INF/lib directory. See the Servlet specification for details. These libraries may reference other libraries, either bundled with the application or installed separately, using any of the techniques described herein.

                   

                  So, from your first quote:

                   

                   

                  A library jar, EJB jar, application client jar or rar archive is a bean archive if it has a file named beans.xml in the META-INF directory.

                   

                  we can see that "bundled libraries", such as those included in WEB-INF/lib are bean archives.

                   

                  From your second quote we can see that the container should treat each bundled liberary as a bean archive, and apply the various rules discussed in the spec for it.

                   

                  However, I agree entirely that you should simply be enable or disable CDI for a deployment (such as a war, ear or rar), rather than per bean archive, and I also agree that we need global enablement of alternatives, interceptors and decorators.

                   

                  From my perspecitve, bean archives are simply an abstraction over the loose classloading defined by Java EE, which serves to simplify the way the spec is written (rather than describe the entire range of options each time, we can define once our abstraction, and then reference it). The enablement based on the bean archive abstraction is problematic, however the resolution rules built on top of it are correct.