Question about alternatives
ron_sigal Dec 5, 2012 10:56 PMGiven 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
for (Metadata<Class<? extends Annotation>> stereotype : beanManager.getEnabled().getAlternativeStereotypes()) {
if (!beanManager.isStereotype(stereotype.getValue())) {
throw new DeploymentException(ALTERNATIVE_STEREOTYPE_NOT_STEREOTYPE, stereotype);
}
boolean b = !isAlternative(beanManager, stereotype.getValue());
if (!isAlternative(beanManager, stereotype.getValue())) {
throw new DeploymentException(ALTERNATIVE_STEREOTYPE_NOT_ANNOTATED, stereotype);
}
}
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);
}
}
}