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;
?
cdijsfmanaged-bean
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;
?
JSP is a Java view technology running on the server machine which allows you to write template text in client side languages (like HTML, CSS, JavaScript, ect.). JSP supports taglibs, which are backed by pieces of Java code that let you control the page flow or output dynamically. A well-known taglib is JSTL. JSP also supports Expression Language, which can be used to access backend data (via attributes available in the page, request, session and application scopes), mostly in combination with taglibs.
When a JSP is requested for the first time or when the web app starts up, the servlet container will compile it into a class extending HttpServlet
and use it during the web app's lifetime. You can find the generated source code in the server's work directory. In for example Tomcat, it's the /work
directory. On a JSP request, the servlet container will execute the compiled JSP class and send the generated output (usually just HTML/CSS/JS) through the web server over a network to the client side, which in turn displays it in the web browser.
Servlet is a Java application programming interface (API) running on the server machine, which intercepts requests made by the client and generates/sends a response. A well-known example is the HttpServlet
which provides methods to hook on HTTP requests using the popular HTTP methods such as GET
and POST
. You can configure HttpServlet
s to listen to a certain HTTP URL pattern, which is configurable in web.xml
, or more recently with Java EE 6, with @WebServlet
annotation.
When a Servlet is first requested or during web app startup, the servlet container will create an instance of it and keep it in memory during the web app's lifetime. The same instance will be reused for every incoming request whose URL matches the servlet's URL pattern. You can access the request data by HttpServletRequest
and handle the response by HttpServletResponse
. Both objects are available as method arguments inside any of the overridden methods of HttpServlet
, such as doGet()
and doPost()
.
JSF is a component based MVC framework which is built on top of the Servlet API and provides components via taglibs which can be used in JSP or any other Java based view technology such as Facelets. Facelets is much more suited to JSF than JSP. It namely provides great templating capabilities such as composite components, while JSP basically only offers the <jsp:include>
for templating in JSF, so that you're forced to create custom components with raw Java code (which is a bit opaque and a lot of tedious work) when you want to replace a repeated group of components with a single component. Since JSF 2.0, JSP has been deprecated as view technology in favor of Facelets.
Note: JSP itself is NOT deprecated, just the combination of JSF with JSP is deprecated.
Note: JSP has great templating abilities by means of Taglibs, especially the (Tag File) variant. JSP templating in combination with JSF is what is lacking.
As being a MVC (Model-View-Controller) framework, JSF provides the FacesServlet
as the sole request-response Controller. It takes all the standard and tedious HTTP request/response work from your hands, such as gathering user input, validating/converting them, putting them in model objects, invoking actions and rendering the response. This way you end up with basically a JSP or Facelets (XHTML) page for View and a JavaBean class as Model. The JSF components are used to bind the view with the model (such as your ASP.NET web control does) and the FacesServlet
uses the JSF component tree to do all the work.
Use actionListener
if you want have a hook before the real business action get executed, e.g. to log it, and/or to set an additional property (by <f:setPropertyActionListener>
), and/or to have access to the component which invoked the action (which is available by ActionEvent
argument). So, purely for preparing purposes before the real business action gets invoked.
The actionListener
method has by default the following signature:
import javax.faces.event.ActionEvent;
// ...
public void actionListener(ActionEvent event) {
// ...
}
And it's supposed to be declared as follows, without any method parentheses:
<h:commandXxx ... actionListener="#{bean.actionListener}" />
Note that you can't pass additional arguments by EL 2.2. You can however override the ActionEvent
argument altogether by passing and specifying custom argument(s). The following examples are valid:
<h:commandXxx ... actionListener="#{bean.methodWithoutArguments()}" />
<h:commandXxx ... actionListener="#{bean.methodWithOneArgument(arg1)}" />
<h:commandXxx ... actionListener="#{bean.methodWithTwoArguments(arg1, arg2)}" />
public void methodWithoutArguments() {}
public void methodWithOneArgument(Object arg1) {}
public void methodWithTwoArguments(Object arg1, Object arg2) {}
Note the importance of the parentheses in the argumentless method expression. If they were absent, JSF would still expect a method with ActionEvent
argument.
If you're on EL 2.2+, then you can declare multiple action listener methods via <f:actionListener binding>
.
<h:commandXxx ... actionListener="#{bean.actionListener1}">
<f:actionListener binding="#{bean.actionListener2()}" />
<f:actionListener binding="#{bean.actionListener3()}" />
</h:commandXxx>
public void actionListener1(ActionEvent event) {}
public void actionListener2() {}
public void actionListener3() {}
Note the importance of the parentheses in the binding
attribute. If they were absent, EL would confusingly throw a javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
, because the binding
attribute is by default interpreted as a value expression, not as a method expression. Adding EL 2.2+ style parentheses transparently turns a value expression into a method expression. See also a.o. Why am I able to bind <f:actionListener> to an arbitrary method if it's not supported by JSF?
Use action
if you want to execute a business action and if necessary handle navigation. The action
method can (thus, not must) return a String
which will be used as navigation case outcome (the target view). A return value of null
or void
will let it return to the same page and keep the current view scope alive. A return value of an empty string or the same view ID will also return to the same page, but recreate the view scope and thus destroy any currently active view scoped beans and, if applicable, recreate them.
The action
method can be any valid MethodExpression
, also the ones which uses EL 2.2 arguments such as below:
<h:commandXxx value="submit" action="#{bean.edit(item)}" />
With this method:
public void edit(Item item) {
// ...
}
Note that when your action method solely returns a string, then you can also just specify exactly that string in the action
attribute. Thus, this is totally clumsy:
<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />
With this senseless method returning a hardcoded string:
public String goToNextpage() {
return "nextpage";
}
Instead, just put that hardcoded string directly in the attribute:
<h:commandLink value="Go to next page" action="nextpage" />
Please note that this in turn indicates a bad design: navigating by POST. This is not user nor SEO friendly. This all is explained in When should I use h:outputLink instead of h:commandLink? and is supposed to be solved as
<h:link value="Go to next page" outcome="nextpage" />
See also How to navigate in JSF? How to make URL reflect current page (and not previous one).
Since JSF 2.x there's a third way, the <f:ajax listener>
.
<h:commandXxx ...>
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>
The ajaxListener
method has by default the following signature:
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
In Mojarra, the AjaxBehaviorEvent
argument is optional, below works as good.
public void ajaxListener() {
// ...
}
But in MyFaces, it would throw a MethodNotFoundException
. Below works in both JSF implementations when you want to omit the argument.
<h:commandXxx ...>
<f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
Ajax listeners are not really useful on command components. They are more useful on input and select components <h:inputXxx>
/<h:selectXxx>
. In command components, just stick to action
and/or actionListener
for clarity and better self-documenting code. Moreover, like actionListener
, the f:ajax listener
does not support returning a navigation outcome.
<h:commandXxx ... action="#{bean.action}">
<f:ajax execute="@form" render="@form" />
</h:commandXxx>
For explanation on execute
and render
attributes, head to Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes.
The actionListener
s are always invoked before the action
in the same order as they are been declared in the view and attached to the component. The f:ajax listener
is always invoked before any action listener. So, the following example:
<h:commandButton value="submit" actionListener="#{bean.actionListener}" action="#{bean.action}">
<f:actionListener type="com.example.ActionListenerType" />
<f:actionListener binding="#{bean.actionListenerBinding()}" />
<f:setPropertyActionListener target="#{bean.property}" value="some" />
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandButton>
Will invoke the methods in the following order:
Bean#ajaxListener()
Bean#actionListener()
ActionListenerType#processAction()
Bean#actionListenerBinding()
Bean#setProperty()
Bean#action()
The actionListener
supports a special exception: AbortProcessingException
. If this exception is thrown from an actionListener
method, then JSF will skip any remaining action listeners and the action method and proceed to render response directly. You won't see an error/exception page, JSF will however log it. This will also implicitly be done whenever any other exception is being thrown from an actionListener
. So, if you intend to block the page by an error page as result of a business exception, then you should definitely be performing the job in the action
method.
If the sole reason to use an actionListener
is to have a void
method returning to the same page, then that's a bad one. The action
methods can perfectly also return void
, on the contrary to what some IDEs let you believe via EL validation. Note that the PrimeFaces showcase examples are littered with this kind of actionListener
s over all place. This is indeed wrong. Don't use this as an excuse to also do that yourself.
In ajax requests, however, a special exception handler is needed. This is regardless of whether you use listener
attribute of <f:ajax>
or not. For explanation and an example, head to Exception handling in JSF ajax requests.
Best Answer
javax.enterprise.context.SessionScoped
(JSR 346) and all other annotations under thejavax.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 thejavax.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 underjavax.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: