11 Replies Latest reply on Dec 19, 2012 7:58 AM by mkouba

    Question about alternatives

    ron_sigal

      Given this stereotype:

      @Alternative

      @Stereotype

      @Target(TYPE)

      @Retention(RUNTIME)

      public @interface StereotypeAlternative

      {

      }

       

      this bean:

      @StereotypeAlternative

      public class BookVanillaAlternative extends Book

      {

      }

      and this beans.xml file:

      <beans xmlns="http://java.sun.com/xml/ns/javaee"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

         <alternatives>

            <stereotype>org.jboss.resteasy.cdi.inheritence.StereotypeAlternative</stereotype>

            <class>org.jboss.resteasy.cdi.inheritence.BookVanillaAlternative</class>

         </alternatives>

      </beans>

      I get

      22:36:19,085 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-12) MSC00001: Failed to start service jboss.deployment.unit."resteasy-cdi-ejb-test.war".WeldService: org.jboss.msc.service.StartException in service jboss.deployment.unit."resteasy-cdi-ejb-test.war".WeldService: org.jboss.weld.exceptions.DeploymentException: WELD-001422 Enabled alternative <class>org.jboss.resteasy.cdi.inheritence.BookVanillaAlternative</class> in vfs:/content/resteasy-cdi-ejb-test.war/WEB-INF/beans.xml@6 is not annotated @Alternative

          at org.jboss.as.weld.services.WeldService.start(WeldService.java:83)

          at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]

          at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]

          at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [rt.jar:1.6.0_34]

          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [rt.jar:1.6.0_34]

          at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_34]

      Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001422 Enabled alternative <class>org.jboss.resteasy.cdi.inheritence.BookVanillaAlternative</class> in vfs:/content/resteasy-cdi-ejb-test.war/WEB-INF/beans.xml@6 is not annotated @Alternative

          at org.jboss.weld.bootstrap.Validator.validateEnabledAlternatives(Validator.java:525)

          at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:370)

          at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:380)

          at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:83)

          at org.jboss.as.weld.services.WeldService.start(WeldService.java:76)

          ... 5 more

       

      The exception is thrown here:

       

          private void validateEnabledAlternatives(BeanManagerImpl beanManager) {
              ...
              for (Metadata<Class<?>> clazz : beanManager.getEnabled().getAlternativeClasses()) {
                  if (clazz.getValue().isAnnotation() || clazz.getValue().isInterface()) {
                      throw new DeploymentException(ALTERNATIVE_BEAN_CLASS_NOT_CLASS, clazz);
                  }
                  WeldClass<?> weldClass = Container.instance().services().get(ClassTransformer.class).loadClass(clazz.getValue());
                  if (!weldClass.isAnnotationPresent(Alternative.class)) {
                      throw new DeploymentException(ALTERNATIVE_BEAN_CLASS_NOT_ANNOTATED, clazz);  // <=== HERE
                  }
              }
          }
      

       

      So Weld isn't satisfied with the @Alternative stereotype @StereotypeAlternative on BookVanillaAlternative.  It wants to see @Alternative given explicitly on BookVanillaAlternative.  If I add @Alternative to BookVanillaAlternative, everything works fine. 

       

      Also, If I omit

      <class>org.jboss.resteasy.cdi.inheritence.BookVanillaAlternative</class>

      from beans.xml, everything works fine, but the CDI spec doesn't seem to prohibit its presence:

      5.1.1. Declaring selected alternatives for a bean archive

       

      By default, a bean archive has no selected alternatives. An alternative must be explicitly declared using the
      <alternatives> element of the beans.xml file of the bean archive. The <alternatives> element contains a list of bean
      classes and stereotypes. An alternative is selected for the bean archive if either:

       

      • the alternative is a managed bean or session bean and the bean class of the bean is listed,

       

      • the alternative is a producer method, field or resource, and the bean class that declares the method or field is listed, or

       

      • any @Alternative stereotype of the alternative is listed.

       

      <beans xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
      <alternatives>
         <class>org.mycompany.myfwk.InMemoryDatabase</class>
         <stereotype>org.mycompany.myfwk.Mock</stereotype>
         <stereotype>org.mycompany.site.Australian</stereotype>
      </alternative

       

      So, Weld is treating the "or" as exclusive, and the spec seems to be ambiguous on this point.  Am I missing something?

       

      -Ron

        • 1. Re: Question about alternatives
          luksa

          You probably missed the following sentence in the spec:

           

          Each child <class> element must specify the name of an alternative bean class. If there is no class with the specified name, or if the class with the specified name is not an alternative bean class, the container automatically detects the problem and treats it as a deployment problem.

           

          So I'd say Weld is correct in throwing the exception.

          • 2. Re: Question about alternatives
            ron_sigal

            Hi Marko,

             

            But BookVanillaAlternative is decorated with the @Alternative stereotype @StereotypeAlternative.  Doesn't that make BookVanillaAlternative an alternative?  The spec says

             

            2.7.1.4. Declaring an @Alternative stereotype

             

            A stereotype may declare an @Alternative annotation, which specifies that every bean with the stereotype is an alternative.

             

            • 3. Re: Question about alternatives
              luksa

              Yes, it does make it an alternative. But the paragraph I pasted above talks about "alternative _bean class_".

               

              I see that the paragraph was reworded in the 1.1 spec. It now reads:

               

              Each child <class> element must specify the name of a bean class of an alternative bean. If there is no bean whose bean

              class has the specified name, or if no bean whose bean class has the specified name is an alternative, the container automatically detects the problem and treats it as a deployment problem.

               

              So, in 1.1, I'd say you are allowed to enable a specific alternative bean by specifying its class name, even though the bean is made alternative through a stereotype. In 1.0 however, it is not really clear if this is allowed or not.

               

              Have you checked if Weld 2.0 allows this? If not, it's definitely a bug. Not sure if Weld 1.x should be changed to allow this or not.

              • 4. Re: Question about alternatives
                mkouba

                Well, I don't think this should be allowed. It's counterintuitive. A stereotype means declaring some common metadata. Speaking about alternatives a stereotype should be used to select/deselect all the relevant beans. However my interpretation might be wrong :-).

                 

                Feel free to file a clarification issue: https://issues.jboss.org/browse/CDI

                • 5. Re: Question about alternatives
                  ron_sigal

                  Hi Marko,

                   

                  Sorry for the delay.  Got distracted for a while.

                   

                  I'm trying the parse the difference between the 1.0 and 1.1 spec.  It looks like "alternative bean" and "bean class" are defined, but the phrase "alternative bean class" is not, so I guess that the language in the 1.1 spec corrects the use of an undefined phrase.  Assuming, though, that "alternative bean class" was meant to mean "bean class of an alternative bean", it seems to me that the rules in the two specs are meant to mean the same thing.  If that's true, then it seems that the behavior in Weld 1.2.0 either is correct with respect to both or incorrect with respect to both.  Unless I'm missing something subtle.

                   

                  I downloaded weld-core 2.0.0.Beta1 and tried to run it in AS 7.1.1, but it seems to have some unsatisfied dependencies, and I'm reluctant to start messing with my version of AS 7.1.1.  The last time I did that, it took me two days to figure out how to get it back to a working state. 

                   

                  -Ron

                  • 6. Re: Question about alternatives
                    ron_sigal

                    Hi Martin,

                     

                    re: "Well, I don't think this should be allowed. It's counterintuitive."


                    I can't say whether you're right or not, but I think the rules should be clarified since we seem to be having some trouble interpreting them.

                     

                    -Ron

                    • 7. Re: Question about alternatives
                      pmuir

                      What Ron is doing should definitely be allowed, it's really counter-intuitive to not support it!

                      • 8. Re: Question about alternatives
                        ron_sigal

                        Thanks, Pete.  Heed the Voice of the Master. 

                        • 9. Re: Question about alternatives
                          mkouba

                          Yes, rereading the spec I must admin my understanding was wrong . However I believe a clarification is still needed. If both a stereotype and a bean class is used to select/deselect an alternative bean, there might be a conflict. E.g. if we globally select Mock stereotype with priority 100 and also globally select InMemoryDatabase bean with priority 1000 which is an alternative due to it has Mock stereotype applied, what's the result? InMemoryDatabase with priority 1000 and all other beans with Mock stereotype with priority 100, I think. However this is not specified ATM... and this is not the only example.

                          <alternatives>
                          <class priority="1000">org.mycompany.myfwk.InMemoryDatabase</class>
                          <stereotype priority="100">org.mycompany.myfwk.Mock</stereotype>
                          </alternatives>
                          

                           

                          Also note that the basic behaviour is allowed in CDI 1.1 and works in Weld 2 (tested against Weld 2.0.0.Beta2).

                          • 10. Re: Question about alternatives
                            pmuir

                            Thanks Martin, please can you raise a CDI issue for this?

                            • 11. Re: Question about alternatives
                              mkouba

                              You're welcome : CDI-314