[cdi-dev] [JBoss JIRA] (CDI-129) Clarify behaviour of @ApplicationScoped in EARs

Mark Struberg (JIRA) jira-events at lists.jboss.org
Tue Oct 16 15:48:08 EDT 2012

    [ https://issues.jboss.org/browse/CDI-129?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12726971#comment-12726971 ] 

Mark Struberg commented on CDI-129:

Oki to pick up that stuff again

> ... beans that execute within the same application.
Too bad it's neither in the CDI nor the EE spec defined what they mean with application. Both sometimes refer to web-applications and sometimes to enterprise-applications. It's just not clear. 

@PMuir From the historical perspective. I read through the very early mails in the webbeans dev mailing list and the original intention seems to have been to glue together JSF and EJB. And as such the CDI scopes were meant as replacement for JSF scopes. All the EAR stuff finds a first mentioning in spec drafts in middle 2008. Now guess how JSF ApplicationScoped behaves? Exactly, 1 per JSF Application == 1 per webapp. With other words. There exists a defined behaviour for ApplicationScoped beans in Java EE since 10 years, and it is 1 per webapp!

Oki, lets take aside how we name that baby. The real problem is not how to cope with @ApplicationScoped, but how injecting into anything which has a scope bigger than some class visibility would work. The biggest unique visibility area is a single web-application. Thus we are talking about any scope 'bigger' than 1 per webapp.

It doesn't matter if this is @EnterpriseApplicationScoped or a @Statefuf EJB which is shared across the whole EAR - the underlying problem is the same!
And just to be clear: the containers I tested so far just blow up with the above mentioned scenario.

Oki here it goes.

The scenario is as following

* A shared jar with interface X and @EnterpriseApplicationScoped public class A implements X and an @EnterpriseApplicationScoped public class MailService { @Inject X;. 
* webapp1 with @SessionScoped public class BackingBean1 { @Inject X x;
* webapp2 with @Specializes public class B extends A and  @SessionScoped public class BackingBean2 { @Inject X x;

a.) I've now talked with lots of different folks, including JSR spec leads, and NO ONE did expect that behaviour.

b.) what proxy will be used for the injection point in MailService#x ? Most containers atm just inject a proxy with the Bean of the first request. If webapp2 gets accessed first, then it will create a contextual instance of MailService and the injection point will be filled with the proxy for B. If now a request from webapp1 arrives then the proxy will return an instance of B which will cause a ClassNotFound exception or similar. Because webapp1 cannot see class B. In the best case you will 'only' randomly end up with the wrong class...
This is btw the same if you inject a @SessionScoped or @RequestScoped bean into a bean with a larger scope than 1 per webapp.  @Specializes and @Alternative beans will be randomly broken for any injection point of a bean with a broader scope than 1 per webapp. 

So there are 2 broken situations with most implemented proxies atm
 1. some webapps might get classes/impls which dont belong to them 
 2. some webapps might get NO @Alternative or @Specializes despite being configured

This could perfectly get fixed by such proxies by just implementing the injection point type and do getBeans(injectionPointType) + resolve the instance. But this is not defined that way in CDI as Jozef pointed out. Currently the proxies contain the Beans, so we have no chance to do this properly in a spec conform way for CDI beans. The easiest solution would be to just interpret @ApplicationScoped as 1 per webapp and we are done.

Jozef, could you please also describe your preferred way?

Afair it was 2 options:
Option a.) just disallow @Specializes and @Alternatives for all beans defined in a shared jar. Regardless of it's scope.
Option b.) inject only beans defined in the shared jar into another bean of a shared jar. E.g. MailService would always get an instance of A injected. Imo this is pretty crucial as @Inject X x; in a JSF backing bean would give you a different contextual instance (even of a totally different type) than the same code @Inject X x; in the MailService. 

> Clarify behaviour of @ApplicationScoped in EARs
> -----------------------------------------------
>                 Key: CDI-129
>                 URL: https://issues.jboss.org/browse/CDI-129
>             Project: CDI Specification Issues
>          Issue Type: Clarification
>          Components: Contexts
>    Affects Versions: 1.0
>            Reporter: Mark Struberg
>            Assignee: Pete Muir
>             Fix For: 1.1 (Proposed)
> Since @ApplicationScoped currently is defined in 6.5.2 as to be 'like in the Servlet specification' this means that you will get a new instance for every WebApplication (WAR file).
> There is currently no specified CDI scope for providing a single shared instance for a whole EAR.
> We could (ab-)use @Singleton for that, but this is currently not well defined at all.
> Alternatively we could introduce an own new annotation like @EnterpriseScoped or likes. 

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

More information about the cdi-dev mailing list