JSR-299 EG,

For a while now, the Seam 3 project has been working to solve a portability issue that prevents modules (i.e., extensions) from running on GlassFish (3.0 and 3.1) [1]. After much research, we've determined that this isn't a problem that we have much control over. It's clear that there is an inconsistency in the way the JSR-299 specification is being interpreted with regard to extension loading.

The question is this. Does an extension have to be in an bean archive in order to be loaded?

Section 11.5 states:

"An extension is a service provider of the service javax.enterprise.inject.spi.Extension declared in META-INF/services."

If one assumes that "service provider" refers to the term defined in the jar specification [2], then one would conclude that an extension does not have to be in a bean archive to be recognized (these are orthogonal concerns). However, the Java EE 6 reference implementation (GlassFish) does not honor this interpretation prior to version 3.1-b37, as indicated by [3].

Even with the recent fix to the reference implementation, there is a secondary interpretation problem:

Can an extension register a bean programmatically for a class that resides in another non-bean archive?

This question requires a short example.

Assume one archive, a.jar, has the following contents:

org/opentck/javaee/cdi/spi/beforebeandiscovery/BeanClassToRegister.class

A second archive, b.jar, has the following contents:

org/opentck/javaee/cdi/spi/beforebeandiscovery/AnotherBeanClassToRegister.class
org/opentck/javaee/cdi/spi/beforebeandiscovery/AnotherManualBeanRegistrationExtension.class
org/opentck/javaee/cdi/spi/beforebeandiscovery/ManualBeanRegistrationExtension.class
META-INF/services/javax.enterprise.inject.spi.Extension

AnotherBeanClassToRegister has an injection point of type BeanClassToRegister:

public class AnotherBeanClassToRegister {
   @Inject
   private BeanClassToRegister collaborator;
}

BeanClassToRegister and AnotherBeanClassToRegister are added as beans programmatically in respective extensions listed in the service provider descriptor:

public class ManualBeanRegistrationExtension implements Extension {
   public void registerBeans(@Observes BeforeBeanDiscovery event, BeanManager bm) {
      event.addAnnotatedType(bm.createAnnotatedType(BeanClassToRegister.class));
   }
}

public class AnotherManualBeanRegistrationExtension implements Extension {
   public void registerBeans(@Observes BeforeBeanDiscovery event, BeanManager bm) {
      event.addAnnotatedType(bm.createAnnotatedType(AnotherBeanClassToRegister.class));
   }
}

The two libraries, a.jar and b.jar are bundled in a web archive, test.war

WEB-INF/lib/a.jar
WEB-INF/lib/b.jar
WEB-INF/beans.xml

Deploying this archive to the reference implementation fails with an error message that the injection point from above cannot be satisfied. Clearly there is a visibility problem across bean archives in this case.

Adding META-INF/beans.xml to a.jar and removing the ManualBeanRegistrationExtension from b.jar resolves the issue in the reference implementation.

The fact that there is so much discussion around this issue has led me to the conclusion that it needs to be addressed at the specification level.

These scenarios have been prepared using Open TCK tests (based on Arquillian). [4]

-Dan

p.s. Thanks to Jason Porter for helping track down this issue and drafting the initial the Open TCK tests.

[1] https://issues.jboss.org/browse/SOLDER-47
[2] http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider
[3] http://java.net/jira/browse/GLASSFISH-14808
[4] https://github.com/opentck/javaee_cdi/tree/master/src/test/java/org/opentck/javaee/cdi/spi/beforebeandiscovery

--
Dan Allen
Principal Software Engineer, Red Hat | Author of Seam in Action
Registered Linux User #231597

http://mojavelinux.com
http://mojavelinux.com/seaminaction
http://www.google.com/profiles/dan.j.allen