[
https://issues.jboss.org/browse/CDI-456?page=com.atlassian.jira.plugin.sy...
]
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)