[jsr-314-open] getting behind CDI
Jeremy Grelle
Jeremy.Grelle at springsource.com
Wed Dec 23 15:13:52 EST 2009
Ahh, I see...I made the mistake of assuming that CDI was already exposing such beans via EL. Indeed, having to resolve the bean from JNDI isn't too pleasant. Looking at the spec, I see now that @Named is necessary to give a bean an EL name.
WRT @javax.annotation.ManagedBean, Spring just uses the value as the bean id, rather than registering anything with JNDI, thus it becomes resolvable via EL as long as you register the provided SpringBeanELResolver.
Agreed, then, since we do support the use of @Named at the class level in Spring, it makes sense to settle on it for the sake of more consistent examples.
Cheers,
Jeremy
On Dec 23, 2009, at 11:38 AM, Dan Allen wrote:
On Wed, Dec 23, 2009 at 10:24 AM, Cay Horstmann <cay at horstmann.com<mailto:cay at horstmann.com>> wrote:
On 12/19/2009 08:25 AM, Dan Allen wrote:
If the developer wants to target a native Java EE technology stack, we
should consider recommending platform managed beans
(@javax.annotation.ManagedBean) with CDI services. If the developer's
scope is broader, then we could suggest for them to consider alternative
bean containers such as Spring. It's even possible to recommend the use
of @javax.annotation.ManagedBean with @javax.inject.Inject to have a
bean which is portable to both Java EE and Spring, likely the ideal
recommendation for setting a common ground.
Hopefully we can all agree that it's time to look past the rudimentary
JSF managed bean facility. I don't think we do anyone a service by
showing them the @javax.faces.ManagedBean in examples because it's just
not going to stand up to the long-term challenges the developer is going
to face.
I am sorry to be so dense here, but how does @javax.annotation.ManagedBean work with JSF 2.0? I just tried out
@javax.annotation.ManagedBean("user")
public class UserBean implements Serializable { ... }
The JSF EL does not pick this up, even in an EE6 container (GlassFish v3). This isn't really surprising. The JSR316 spec mandates that the name is turned into a JNDI name, but it specifies no interaction with an EL.
I tried adding an empty beans.xml to check whether that would trigger a lookup by the CDI implementation, but it didn't, and reading the JSR 299 spec, I don't think it should. Is there some other straightforward way of making @javax.annotation.ManagedBean work with the JSF EL?
If not, it would seem to me that we need to use @javax.inject.Named if we want to avoid @javax.faces.bean.ManagedBean.
Shoot, I made the false assumption that the name in @javax.annotation.ManagedBean was the EL name. On the one hand it makes some sense that it is the JNDI name to make it consistent with how the container treats EJBs. But on the other hand, what developers expect in all but a few cases is that it would the EL name.
It's possible to put together an EL resolver the bridge the gap. Below is a hacked together EL resolver that finds @javax.annotation.ManagedBean references in the same module as the web app.
public class ManagedBeanELResolver extends ELResolver {
public Object getValue(ELContext context, Object base, Object property) {
if (property == null) {
return null;
}
String propertyAsString = property.toString();
if (base == null) {
try {
InitialContext ic = new InitialContext();
// we assume the managed bean is in the war
Object result = ic.lookup("java:module/" + propertyAsString);
context.setPropertyResolved(true);
return result;
} catch (NamingException ex) {
}
}
// delegate up the chain
return null;
}
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
public void setValue(ELContext context, Object base, Object property, Object value) {
}
public boolean isReadOnly(ELContext context, Object base, Object property) {
return false;
}
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
return null;
}
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
}
Register in faces-config.xml
<application>
<el-resolver>com.acme.ManagedBeanELResolver</el-resolver>
</application>
I guess the question is, does Spring intend on use the @javax.annotation.ManagedBean name as an EL name? If that is the case, then it's inconsistent between Spring and the platform. If Spring doesn't, perhaps they would consider using @javax.inject.Named (the most logical choice at this point) and we can align on that annotation.
So, as Cay points out, we are back to @javax.inject.Named as the recommendation (unless you want to use that hacked up EL resolver).
-Dan
--
Dan Allen
Senior Software Engineer, Red Hat | Author of Seam in Action
Registered Linux User #231597
http://mojavelinux.com<http://mojavelinux.com/>
http://mojavelinux.com/seaminaction
http://www.google.com/profiles/dan.j.allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jsr-314-open-mirror/attachments/20091223/012b5a23/attachment.html
More information about the jsr-314-open-mirror
mailing list