Java EE 6 and CDI - jsf

I'm just starting learning CDI and Java EE 6 but I found this piece of code that I want to fully understand.
#Stateful
#Model
public class MemberRegistration {
#Inject
private EntityManager em;
#Inject
private Event<Member> memberEventSrc;
private Member newMember;
#Produces
#Named
public Member getNewMember() {
return newMember;
}
}
Then... I saw that a jsf page referenced this newMember object like this:
<h:inputText value=#{newMember.name}/>
So my question is : It doesn't matter if I put an #Named annotation inside an variable of any object, it will be accessible anyway from JSF code?
Also, what's the usage of #Produces in this case, and finally is #Stateful preferred over #Stateless in Java EE 6? If that's the case why?

Despite its simplicity this bean sure does a lot of things ;)
Either the #Named (CDI) or #ManagedBean (JSF-native) annotation is required to make a bean known to JSF. However, Java EE has the concept of stereotypes, which are a kind of composite annotations that combine a number of other ones.
In this case #Model is such a stereotype, it combines #Named and #RequestScoped.
#Produces annotates a factory method; a method that knows where to get an instance of some type from. It can be combined with a so-called qualifier annotation, e.g. #Foo, after which you can use that annotation to inject something in some bean. In this case however it's combined with #Named, which makes newMember available to JSF. Instead of creating the bean as would happen when e.g. an #RequestScoped bean is encountered first, under the covers the getNewMember() method will be called when JSF wants an instance. See Dependency Injection in Java EE 6 for more info.
#Stateful is normally not preferred over #Stateless when used standalone. #Stateless beans are pooled and execute one method for a client (typically in a transactional context). Their stateful counterpart is not pooled and without CDI, the caller has to keep track of its life-cycle (by eventually calling an #Remove annotated method). Here, the bean is also assigned a scope (request, via #Model), so the container will take care of that.
The likely reason for using this annotation here is probably to make the bean's methods transactional. Although the fragment as given doesn't show its usage I guess there's a version of this class with more methods that make use of the EntityManager. Transactions will come into play there.
(Note, combining annotations this way gives the Java EE developer lots of power, but it does put several concerns in one bean which is contrary to the mantra that a bean should do one thing and do that well. An alternative is an #Model annotated bean focussing on view concerns only, that's injected with #Stateless beans that encapsulate the business logic instead of an EntityManager.)

Related

Injecting commonly used CDI beans in abstract parent class

This is more of a good practice question...
We're converting JSF managed beans to CDI beans in JSF 2.2 . While doing this, it seems in a LOT of beans, we need a few sessionscoped beans.
We initially intended to #Inject those, but another option would be to inject them into a protected variable in a parent "FacesBean" class.
Would this be good practice?
Does #Inject also work in #ManagedBean classes that were not yet converted to CDI?
So one by one:
1) Good practice?
If you have a class hierarchy, I suggest you #Inject it into a private field in the parent and then create a getter method with minimum needed visibility (probably protected). Just stick to general good practice rules around encapsulation in Java.
2) #ManagedBean and #Inject?
As long as you use bean discovery mode all (use empty beans.xml), your classes will be automatically picked up as managed beans - including those annotated with #ManagedBean. And as soon as it is a bean, injection works. So yes, injection will work as long as the class can become a bean automatically (e.g. it is not #Vetoed or unproxyable etc.)

Managed Bean not being instantiated at #ApplicationScoped and eager=true

I have the following UserView class:
#ManagedBean(name="usersView", eager=true)
#ApplicationScoped
public class UserView
{
...
public void setUsers(...)
{
...
}
}
I then have another class, UserService which tries to access this bean and then call this method, as follows:
UserView usersView = (UserView) FacesContext.getCurrentInstance().getExternalContext().getSessionMap("usersView");
usersView.setUsers(...)
My issue is, is that usersView keeps coming back as null and hence the method cannot be called.
My end goal is to use this data in a PrimeFaces datatable, like so:
<p:dataTable var="user" value="#{usersView.users}" ...>
I have also tried changing the scope to SessionScoped, but it is still null and I cannot figure out why.
Any suggestions would be greatly appreciated.
The getExternalContext().getXxxMap().get("beanName") approach won't autocreate beans if they don't exist yet. Managed beans will only be autocreated when an EL expression referencing the bean is evaluated. Accessing the scope map doesn't do that. For that, use #ManagedProperty in the source bean instead. You can specify an EL expression in its value.
#ManagedProperty("#{userView}")
private UserView userView; // +setter (no getter required).
Note that this only works if the source bean has the same or a narrower scope than the target bean. If that's not the case, consider managing beans using CDI instead of JSF. You can then use #Inject instead of #ManagedProperty (which doesn't require a setter by the way). Moreover, #ManagedBean and friends is deprecated in upcoming JSF 2.3.
As to eager=true, this has only effect on #ApplicationScoped beans. See also the javadoc (emphasis mine).
...
If the value of the eager() attribute is true, and the managed-bean-scope value is "application", the runtime must instantiate this class when the application starts. This instantiation and storing of the instance must happen before any requests are serviced. If eager is unspecified or false, or the managed-bean-scope is something other than "application", the default "lazy" instantiation and scoped storage of the managed bean happens.
...
See also:
How to choose the right bean scope?
Difference between #ManagedProperty and FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("bean")
Get JSF managed bean by name in any Servlet related class
Backing beans (#ManagedBean) or CDI Beans (#Named)?

CDI (Weld) + DeltaSpike + Converstation

I'm currently trying to get CDI (Weld to be more precise) to work with JSF 2 and a long running conversation. I'm starting the conversation in #ConversationScoped my backing bean. I'm also creating a #ConversationScoped entity manager. Sadly the entity I'm editing in my backing bean always get's a LazyInitializationException when JSF is trying to write a #ManyToMany mapped field. It seems that the entity get's detached from the entitymanager. In my EntityManagerProducer (see below) the method createEntityManager() is not called bevore the LazyInitializationException is thrown, so I'd assume that the entitymanager is actually session scoped. But from what I understand my code does not generate an extended persistence context (since I could not figure how to do that programmatically).
As far as I know DeltaSpike does not yet offer anything for dealing with long running conversations in JSF. Can anybody suggest a method on how to implement long running conversations with CDI using Weld + DeltaSpike (preferably on a Tomcat with weld-servlet)?
#ApplicationScoped
public class EntityManagerProducer {
#Inject
#PersistenceUnitName("myUnit")
private EntityManagerFactory emf;
#Produces
#ConversationScoped
public EntityManager createEntityManager() {
return emf.createEntityManager();
}
public void closeEm(#Disposes EntityManager em) {
em.close();
}
}
The lazy initialization exception actually does not come from extended persistence contexts or CDI or DeltaSpike. It's simply the same behaviour as described here: selectManyCheckbox LazyInitializationException on process validation
JSF 2 clones the PersistentBag of my entity causing it to get detached. I also worked around by sprinkling lot's of
<f:attribute name="collectionType" value="java.util.ArrayList" />
throughout my JSF code.
Having the EntityManager in a conversation scope is only one side of the equation, what scope are your entities in ?
In order to avoid detaching the entities they should also be conversation scoped.
As a side note :
I found that instead of dealing with entities in a long running scope , it is much easier to reattach them in each request scope.

#Inject-ed value null in #FacesComponent

I have the impression that CDI is not working with classes that have a #javax.faces.component.FacesComponent. Is this true?
Here's my example, that doesn't work. The MyInjectableClass is used at other points in the code where injection is not a problem, so it must be about the #FacesComponent annotation I think.
The class I want to inject:
#Named
#Stateful
public class MyInjectableClass implements Serializable {
private static final long serialVersionUID = 4556482219775071397L;
}
The component which uses that class;
#FacesComponent(value = "mycomponents.mytag")
public class MyComponent extends UIComponentBase implements Serializable {
private static final long serialVersionUID = -5656806814384095309L;
#Inject
protected MyInjectableClass injectedInstance;
#Override
public void encodeBegin(FacesContext context) throws IOException {
/* injectedInstance is null here */
}
}
Unfortunately, even for JSF 2.2 #FacesComponent, #FacesValidator and #FacesConverter are not valid injection targets (read What's new in JSF 2.2? by Arjan Tijms for more details). As Arjan points out:
It’s likely that those will be taken into consideration for JSF 2.3 though.
What can you do for now? Well, you've got basically two choices:
Handle CDI injection via lookup, or switch to EJB and do the simpler EJB lookup;
Annotate tour class with #Named instead of #FacesComponent, #Inject the component the way you did and register your component in faces-config.xml. As the UI component instance is created via JSF Application#createComponent(), not via CDI you will also need a custom Application implementation as well (exactly like OmniFaces has for those converters/validators).
And, by the way, you've got two issues with what you've got this far: (1) what is meant by #Named #Stateful when the former is from a CDI world and the latter is from EJB world and (2) are you sure you intend to keep state in a faces component that's basically recreated on every request?
#FacesCompnent is managed by JSF and injection is not supported into them.
Passing the value in from the XHTML page via a composite component attribute worked for us.

Are #ManagedBeans obsolete in JavaEE6 because of #Named in CDI/Weld?

Because of CDI (and its implementation Weld), every POJO in JEE6 can be annotated with #Named, which makes the POJO accessible to the view.
Does that mean that ManagedBeans are completely obsolete now?
Or did I miss something where #ManagedBean still makes sense?
In short, #ManagedBean makes sense for applications that use JSF but do not use JSR 299 (whatever the reason is). Below a longer explanation from Gavin King:
Re: Comparisons to #ManagedBean annotations in JSF2?:
While looking through the Weld examples, and the older WebBeans
documentation, it looks like a
competitor to the new #ManagedBean JSF
2.0 annotations. Is there any information on when we'd want to use
one over the other?
It's a good question, and I'm not
really in full agreement with the
answers that have been posted so far.
The new EE Managed Beans specification
defines a base component model for
Java EE, together with a very basic
set of container services (#Resource,
#PostConstruct, #PreDestroy).
The idea is that other specifications
(beginning with EJB, CDI, JSF and the
new Java Interceptors spec) build upon
this base component model and layer
additional services, for example
transaction management, typesafe
dependency injection, interceptors. So
at this level, the managed beans, CDI,
interceptors and EJB specifications
all work hand-in-hand and are highly
complementary.
Now, the Managed Beans specification
is quite open-ended with respect to
identifying exactly which classes are
managed beans. It does provide the
#ManagedBean annotation as one
mechanism, but it also allows other
specifications to define different
mechanisms. So, for example:
The EJB specification says that a class obeying certain programming
restrictions with a #Stateless or
#Stateful annotation deployed in an
EJB jar is a managed bean.
The CDI specification says that any class with an appropriate constructor
deployed in a "bean deployment
archive" is a managed bean.
Given that EJB and CDI provide
arguably more convenient ways to
identify a managed bean, you might
wonder precisely what #ManagedBean is
needed for. The answer, as alluded to
by Dan, is that if you have CDI
available in your environment (for
example, if you are using EE6), then
#ManagedBean is just not really
needed. #ManagedBean is really there
for use by people who are using JSF2
without CDI.
OTOH, if you do annotate a bean
#ManagedBean, and you do have CDI in
your environment, you can still use
CDI to inject stuff into your bean.
It's just that the #ManagedBean
annotation is not required in this
case.
To summarize, if you do have CDI
available to you, it provides a far
superior programming model to the
#ManagedBean/#ManagedProperty model
that JSF2 inherits from JSF1. So
superior, in fact, that the EE 6 web
profile does not require support for
#ManagedProperty etc. The idea being
that you should just use CDI instead.
You have a choice. Either use the #ManagedBean from JSF2 to bind beans into your forms, or use the #Named annotation from CDI. If you plan on only doing JSF, you can stick to #ManagedBean, but if you want to integrate with EJB's, or make use of CDI's #ConversationScoped, then go the CDI route.
Personally I feel the next version of JSF should deprecate the #ManagedBean, and standardize on CDI. The duality is confusing to newcomers.
CDI has no view scope, because it doesn't have the notion of a view, so if you need that scope, CDI in its pure form can't do it. View scope basically means request scope + being AJAX-ready. It's not a JSF view, like a page named xyz.xhtml, even though you see JSF <f:viewParam> and the likes. A frequent use case with view-scoped beans is how to get GET parameters into a such a bean. Also read this.
Note that CDI rather lives at the EJB/service layer than the JSF/presentation layer. This blog has a nice overview.
As such #ManagedBean cannot be fully replaced by CDI, again if you're using #ViewScoped beans - at least not without extending CDI or using the Seam 3 Faces module. Using view-scoped beans is almost always going to happen when using AJAXed JSF 2-based GUI toolkits like RichFaces, PrimeFaces, IceFaces etc.
Mixing annotations from the wrong Java EE 6 packages can get you in trouble unexpectedly, again when using RichFaces or a similar API:
#javax.faces.bean.ManagedBean
#javax.faces.bean.[Jsf]Scoped
are for components used solely at the presentation layer, here by RichFaces, PrimeFaces, etc. Some rich components seem to have problems with CDI-annotated and JSF-annotated helper beans. If you get strange behavior from your beans (or beans that seem to do nothing) the wrong mix of annotations might be the cause.
Mixing JSF and CDI, like
#javax.inject.Named
#javax.faces.bean.[Jsf]Scoped
is possible and works in most cases when referenced from JSF pages, however there are some little-known issues/drawbacks, e.g. when using a JSF scope which CDI doesn't have:
Also the combination #Named #ViewScoped won't work as intended. The JSF-specific #ViewScoped works in combination with JSF-specific #ManagedBean only. Your CDI-specific #Named will behave like #RequestScoped this way. Either use #ManagedBean instead of #Named or use CDI-specific #ConversationScoped instead of #ViewScoped.
Then
#javax.inject.Named
#javax.faces.bean.[Cdi]Scoped
can be used for CDI beans directly referenced from your JSF pages AFAIK. I haven't had any problems with the above combinations so far, so you could consider #ManagedBean obsolete here.
What's left is the service layer, here mostly transactional EJB service beans declared as
#javax.ejb.*
mostly #javax.ejb.Stateless. You can even annotate and use EJBs directly from JSF pages - though I'm not sure if this design is desirable. To reference (inject) any components annotated with #javax.ejb.*, e.g. #Stateless, prefer #Inject over #EJB as described here. (Probably an ancestor of this answer...)
Finally, a very nice overview of Java EE 6 annotations can be found here:
http://www.physics.usyd.edu.au/~rennie/javaEEReferenceSheet.html
Note: the above info is not from an expert, but simply my own take/sight from a newcomers perspective on this ridiculously confusing Java EE 6 annotations spaghetti. More insight has yet to be developed. I hope this answer can endure to be a general, practical answer to this confusion - even though it has gone a little overboard in the context of the original question.
As i Just read in the Weld Reference (p. 12), #ManagedBean is now superflous:
You can explicitly declare a managed
bean by annotating the bean class
#ManagedBean, but in CDI you don't
need to. According to the
specification, the CDI container
treats any class that satisfies the
following conditions as a managed
bean:
It is not a non-static inner class. It is a concrete class, or is
annotated #Decorator.
It is not annotated with an EJB component-defining annotation or
declared as an EJB bean class in
ejb-jar.xml.
It does not implement javax.enterprise.inject.spi.Extension.
It has an appropriate constructor—either:
the class has a constructor with no parameters, or
the class declares a constructor annotated #Inject.

Resources