[cdi-dev] [JBoss JIRA] (CDI-456) fix Bean#getBeanClass() definition

Jozef Hartinger (JIRA) issues at jboss.org
Mon Sep 8 03:27:02 EDT 2014


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

Jozef Hartinger commented on CDI-456:
-------------------------------------

Anatole, you are completely right. But why does it work this way?

The behavior is driven by the following statement in the specification:
{quote}A bean is available for injection in a certain module if the *bean class* is required to be *accessible to classes in the module*, according to the class
accessibility requirements of the module architecture.{quote}

Let's expand your example a bit to demonstrate this. Let's say that your producers are called {{MyProducer1}}, {{MyProducer2}}, {{MyProducer3}} and are packaged in war1, war2 and war3, respectively.

Now, let's inject {{MyBean}} in war1. {{MyProducer1.create()}} is the first candidate. Since the bean class of {{MyProducer1.create()}} is {{MyProducer1}} and since this class is accessible within war1, we can use {{MyProducer1.create()}} to create a {{MyBean}} instance. For {{MyProducer2}} and {{MyProducer3}} this is not the case as we assume wars are isolated. This is expected and in line with your conclusion.

Notice that although {{MyProducer1.create()}} produces {{MyBean}} instances, {{MyProducer1}} is its bean class. If we made {{MyBean}} the bean class of {{MyProducer1}}, {{MyProducer2}} and {{MyProducer3}} (*as this ticket proposes*), all three producer methods would be available for injection in any of the wars, which is obviously not desired! The aforementioned CDI accessibility rule determines the accessibility of the bean by its bean class and therefore we cannot pronounce the return type of a producer method as its bean class.

\\
----
\\
Custom Bean<T> implementations are very similar. Image now that instead of using {{MyProducer}} classes, our example uses {{MyBeanProvider}} classes defined as:

{code:JAVA}
public class MyBeanProvider implements Bean<MyBean> {

   public T create(CreationalContext<T> creationalContext) {
      return new MyBean();
   }

...
}
{code}

Again, we have {{MyBeanProvider1}}, {{MyBeanProvider2}}, {{MyBeanProvider3}} in war1, war2, war3, respectively. Each bean provider is registered by an extension.

What should {{MyBeanProvider1.getBeanClass()}} return? Let's assume it returns {{MyBeanProvider1.class}}. Once we apply the accessibility rule of CDI we can see that each war again gets its respective bean producing MyBean instances and that the bean isolation follows classloader isolation. This is again the expected behavior, matching Anatole's example.

If we however follow the "simplification proposed by this ticket" and return {{MyBean.class}} from {{MyBeanProvider1.getBeanClass()}} then, not unlike with producers, {{MyBeanProvider1}} will be visible from all the three wars, which is not desired. This would be because {{MyBean.class}} is accessible from all the three wars. The CDI accessibility rule determines the accessibility of the bean by its bean class and therefore we cannot just blindly return a bean type from {{Bean.getBeanClass()}}.

Hope this makes it clearer that {{Bean.getBeanClass()}}
* exists for a reason
* it is not a shortcut to bean types and there is often absolutely no relation between Bean<T>.getTypes() and Bean<T>.getBeanClass()
* although probably not the ideal way of addressing modularity and isolation (and subject to improvement in CDI 2.0), it works
* cannot be redefined to simply return the bean type - besides breaking backward compatibility this would also break how other parts of CDI work



> fix Bean#getBeanClass() definition
> ----------------------------------
>
>                 Key: CDI-456
>                 URL: https://issues.jboss.org/browse/CDI-456
>             Project: CDI Specification Issues
>          Issue Type: Bug
>          Components: Beans
>            Reporter: Mark Struberg
>
> currently Bean#getBeanClass() is defined to return the class of the bean it produces but has one important exception: in case of a producer method or field it must return the class of the owner bean of this method or field.
> Imo this only causes troubles and doesn't add any benefit. 
> * At the time when 'using' the Bean (create and destroy) we always ONLY need the type which is to be created.
> * At the time we create interceptors we ONLY need the type which is to be created;
> * At the time we create the normalscoping proxies we ONLY need the type which is to be created;
> In fact the only time we need the ownerBean is when scanning the methods and fields in it. And for creating we really need the owner-Bean and not it's bean-class!
> In OWB we worked around this by having our own method getReturnType() which consistently returns the type which gets created.



--
This message was sent by Atlassian JIRA
(v6.3.1#6329)


More information about the cdi-dev mailing list