Viewscoped JSF and CDI bean - jsf

I'm using Java EE 6 on JBoss EAP 6, and my JSF beans are annotated like this:
#ManagedBean #ViewScoped (both from javax.faces.bean package)
However, they are also CDI beans (default constructor, use of #Inject, #PreDestroy etc). I'm reading all the time that you can't mix these annotations (JSF and CDI), but it's apparently working fine: Injections are working, preDestroy is called on view change etc).
Am I missing something? What is the problem? Why not use?

The CDI #Inject works "everywhere" and thus also inside JSF #ManagedBean. The JSF counterpart #ManagedProperty works inside #ManagedBean only. You also can't #Inject a true JSF managed bean in any CDI managed bean (instead, it would be a CDI managed instance). Perhaps this is what you was reading about. General consensus, however, is indeed to preferably not mix them to avoid confusion among starters. JSF utility library OmniFaces has a CDI compatible #ViewScoped for JSF 2.0/2.1.
The #PreDestroy is by the way not specific to CDI, neither is its counterpart #PostConstruct. They should work just fine in both CDI managed beans and JSF managed beans.

Related

JSF Managed beans and decorate pattern

Is there any way to intercept the creation of a JSF backing bean to transparently decorate it?
I'm on Weblogic 10.3 with JDK 1.6, no CDI.
Perhaps subclassing the BeanManager class? But, how register the BeanManager extension to the weblogic jsf implementation?
You can use the #PostConstruct annotation for your init() method. This will ensure correct one-shot JSF backing bean initialization.

Converting JSF Managed beans to CDI Beans

A JSF project needs to be converted to a CDI beans project. There are few issues to solve.
What should we use when replacing #ViewScope
How can we replace #ManagedProperty
Will #EJB will work as previous in CDIs
Any changes needed in configuration files except beans.xml
I'm assuming you're on JSF 2.0 or 2.1, in which case you can use MyFaces CODI, or Seam 3, or Omnifaces for #ViewScoped. For JSF 2.2 it's there out of the box.
#ManagedProperty becomes #Inject.
Yes.
No.

Why are there different bean management annotations

What is the difference between
import javax.annotation.ManagedBean;
import javax.enterprise.context.SessionScoped;
and
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
?
javax.enterprise.context.SessionScoped(JSR 346) and all other annotations under the javax.enterprise.context.* package maintain the context of CDI. CDI provides an alternative, versatile and more powerful mechanism for dependency injection, bean and general resource management within the Java EE space. It's an alternative to JSF managed beans and it's set to even supersede the JSF bean management mechanism in the coming version of JSF.
Currently, JSF and CDI annotated beans are interchangeable within any given Java EE web application (given a handful of minor restrictions). CDI annotated beans however, extend far beyond the realm of the web tier, which is why the Java EE spec is evolving to make CDI the standard bean and DI mechanism.
While CDI might be an obvious choice for all Java EE development, JSF managed beans are portable across servlet containers (Tomcat) and application servers (Glassfish, JBoss, etc.). CDI beans can live within only full application servers. With some legwork however, Tomcat 7 can be wired to support CDI.
Specifically, javax.enterprise.context.SessionScoped is the parallel implementation of the JSF Session Scope within CDI.
javax.faces.bean.SessionScoped (JSR 314) and all other annotations under the javax.faces.bean.* package maintain the JSF-specific dependency injection and bean management mechanism. Beans annotated with JSF annotations however are only useful within the web tier. All the scopes available with JSF annotations have been replicated within the CDI specification.
javax.annotation.ManagedBean (JSR 316) and other DI-related annotations under javax.annotation.* are an attempt to generalize the JSF-based annotations for other uses within the Java EE spec and really shouldn't be used by the end-developer.
Why they exist? Well IMO, the move from JSF beans to CDI beans is a natural evolution of the technology. JSF beans have had a good run but the likes of Spring, Guice and Seam made it obvious that the technology was not sufficient. There was also a need to bridge the gap between the web components and EJBs, and the response to that need is CDI.
See these related questions too:
JSF: Backing beans (#ManagedBean) or CDI Beans (#Named)?
Java EE 6 #javax.annotation.ManagedBean vs. #javax.inject.Named vs. #javax.faces.ManagedBean

JSF/Facelets backing beans and EJB3

I have a few questions on the various options and best practices when using JSF with EJB3.1. The mental model I have, given the daunting amount of choices and combinations available, is far from clear so some questions may not make sense.
JSF/Facelets reference backing beans (I am using the term "backing bean" for beans whose properties are written or read from Facelets pages) through EL code that is agnostic as to the actual annotations used in the bean classes (javax.faces.bean.* or javax.enterprise.context.*).
Is it correct to say that one can toggle between JSF and CDI scope annotations just by changing the imports in the bean classes without any changes to the Facelets xhtml code?
Is it an established pattern that JSF/Facelets should be used only for the xhtml markup code with all scope and lifecycle (plus injection) annotations done using CDI?
In a JBoss AS setting, where is the lifecycle management of the JSF backing beans (using either JSF or CDI annotations) taking place? In the web container or in the EJB3 container?
In a typical web application given that the SessionScoped beans can be provided by CDI, is there any need for using EJB3 beans other than those of type #Entity, e.g. for the last typical step in each "flow" when information is to be persisted in the database?
Is it correct to say that one can toggle between JSF and CDI scope annotations just by changing the imports in the bean classes without any changes to the Facelets xhtml code?
Yes.
Is it an established pattern that JSF/Facelets should be used only for the xhtml markup code with all scope and lifecycle (plus injection) annotations done using CDI?
JSF is moving towards CDI. The new #FlowScoped annotation of the upcoming JSF 2.2 is evidence of this as this extends from the CDI API. The only disadvantage is that CDI doesn't offer a standard annotation for the tremendously useful JSF #ViewScoped annotation. You'd need #ConversationScoped wherein you manually start and end the conversation, or take a look at a CDI extension like MyFaces CODI.
In a JBoss AS setting, where is the lifecycle management of the JSF backing beans (using either JSF or CDI annotations) taking place? In the web container or in the EJB3 container?
The web container (in flavor of a WAR). JSF is built on top of the Servlet API, so it's definitely the web container.
In a typical web application given that the SessionScoped beans can be provided by CDI, is there any need for using EJB3 beans other than those of type #Entity, e.g. for the last typical step in each "flow" when information is to be persisted in the database?
The #Entity is part of JPA, not of EJB. The #Entity is to be used on a model class which is mapped to a database table and usually solely meant to transfer data across the layers. What you're last describing sounds like candidate for a #Stateful EJB. To understand #Stateless vs #Stateful EJBs better, head to this detailed answer: JSF request scoped bean keeps recreating new Stateful session beans on every request?

View Scope in CDI Weld

I want to use the #ViewScoped - scope in my application for the backing beans of some web pages. Also I use CDI to inject the dependecies into the backing beans.
However, when I use a backing bean annotated like this
#ManagedBean
#ViewScoped
#Inject
someDependency (...)
the #Inject annotation will not inject anything and i get a NullPointerException as soon as i am accessing the dependency.
However, when I decorate the backing bean with
#Named
#ViewScoped
#Inject
someDependency (...)
the injection works fine, but now the #ViewScoped is ignored as it is not part of CDI / Weld.
How can I use #ViewScoped together with CDI Weld?
The problem is that you are mixing simple managed beans with CDI managed beans and they don't work together. Managed Beans is a simple framework for defining beans and their injected beans. CDI is a separate beast with all sorts of extra goodness.
However, Managed beans can't use CDI Injection points but can use the ViewScope while CDI beans use CDI injection points and all that good stuff but the ViewScope isn't available.
To resolve the issue you have to either go with CDI and use the Seam-Faces library to use view scope, or drop CDI and stick with simple managed beans which is a simple implementation.
Cheers,
Andy
You can get #javax.faces.bean.ViewScoped to work by including the Seam Faces 3.1.0 jar in your project.
Failing that (i.e. you're using GlassFish 3.1.1 or earlier), you can simply copy ViewContextExtension.java, ViewScopedContext.java and javax.enterprise.inject.spi.Extension from Seam Faces 3.1.0 into your own project, ensuring you use the same path to the files as Seam Faces does. The java files can be copied verbatim. All lines except the one ending with ViewContextExtension should be removed from javax.enterprise.spi.Extension.
I am using the latter method successfully in GlassFish 3.1.1 and will try the former method one GlassFish 3.1.2 is released.
No, it's not directly supported. Seam3 is supposed to provide such extras that CDI does not. Check it out.
You can implement the #NormalScope to create your own CDI Scope witout using any other framework or waiting for new JEE7
CDI fires an event AfterBeanDiscovery after each bean call
You can use CDI extension to #Observes this event and add you context implementation
In your scope implementation you can :
Use Contextual to get your bean by its name from FacesContext ViewRoot Map and return it after each ajax call back
Use CreationalContext if the bean name from first step is not found to create it in the FacesContext ViewRoot Map
for a more in-depth explanation i recommand this link : http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/
I don't use Seam, just normal JSF + PrimeFaces. I just found this and I am going to give it a try... you might want to as well.
Weld in combination with Seam-Faces would provide it but it's broken. An interesting thread about it and an alternative for it is e.g. at http://forum.primefaces.org/viewtopic.php?f=3&t=7585
I think Apache CODI or Seam 3 solves this. There is a new project called DeltaSpike that might be doing this, think it continues Seam 3.
In Java EE 7, this problem will be solved as I understand that all beans are CDI beans, so there is no JSF beans.

Resources