Accessing FacesContext in servlet - jsf

I'm working on a JSF (v1.2) application. In my application I need a generic servlet which could serve any resource (PDF, Images, Excel, etc). My idea is to ask the caller to send the required information so that I can find out the correct delegator class using some configurations.
This delegator class will take care of serving the correct resource.
For example this is the request url
http://example.com/servlet?delegatorid=abcd
My Servlet code is something like this.
protected void doGet(HttpServletRequest request, HttpServletResponse response){
String delegatorID=request.getParameter("delegatorid");
//Get the configuration from Configuration table
configuration=getConfiguration(delegatorID);
//invoke the method of the delegator class based on this configuration
Object result=invokeMethod(configuration);
//write the response to the stream
}
My question is what is the best way to do this in a JSF project?
Should I completely avoid JSF dependency in this operation? I can find the delegator method and class and invoke it using reflection. Will there be any potential restrictions in future if I avoid JSF dependency. [One problem which I can think about is, in one of the code, I need to get the user information from session. I'm doing this through FacesContext. Since FacesContext is not available, it will fail, I should have another option to get the session.
If I have to introduce JSF dependency, how do I get the FacesContext
here? As far as I know, only the beans that are stored in
application scope can be accessed here. I don't want to do that. Is there any other way of getting it?
Instead of using a servlet, can I do this by invoking a ManagedBean
method directly using the URL? This will give me FacesContext. I
think I need to have a dummy JSP page for the managed bean method to
get invoked.
Could you please let me your thoughts on this?

The FacesContext (and ExternalContext) is just a facade over HttpServletRequest, HttpServletResponse, HttpSession, ServletContext, etcetara along with some JSF specifics which you don't need at all in a plain vanilla servlet. The ExternalContext#getSessionMap() is nothing more than an abstract mapping of HttpSession#get/setAttribute().
In a plain vanilla servlet, the session is just available by request.getSession() and the application by getServletContext() the usual way. See also among others this related question: Get JSF managed bean by name in any Servlet related class.
You can also just refactor code which needs to be shared by JSF and Servlet into an utility method which doesn't have any dependencies on javax.faces.* nor javax.servlet.* classes (or at most only javax.servlet.*) and finally let the callers each pass the necessary information through.

Related

Utility methods in application scoped bean

Do you think it is a good idea to put all widely used utility methods in an application scoped bean?
In the current implementation of the application I'm working on, all utility methods (manipulating with Strings, cookies, checking url, checking current page where the user is etc.) are all put in one big request scoped bean and they are referenced from every xhtml page.
I couldn't find any information on stackoverflow if the approach of putting utility methods in an application scoped bean would be a good or a bad choice.
Why I came across this idea is the need of reusing those methods in a bean of a wider scope then a request scoped bean (like view or session scoped bean). Correct me if I'm wrong but you should always inject same or wider scoped beans i.e. you shouldn't inject request scoped bean inside a view scoped one.
I think using utility methods from application scoped bean should be beneficial (there won't be any new object creations, one object will be created and re-used across all application), but still I would like a confirmation or someone to tell me if that is a wrong approach and why is it wrong.
As to the bean scope, if the bean doesn't have any state (i.e. the class doesn't have any mutable instance variables), then it can safely be application scoped. See also How to choose the right bean scope? This all is regardless of the purpose of the bean (utility or not). Given that utility functions are per definition stateless, then you should definitely be using an application scoped bean. It saves the cost of instantiating on every single request.
As to having utility methods in a managed bean, in object oriented perspective this is a poor practice, because in order to access them from EL those methods cannot be static while they should be. You can't use them as real utility methods in other normal Java classes. Static code analyzers like Sonar will mark them all with a big red flag. This is thus an anti-pattern. The correct approach would be to keep using a true utility class (public final class with private Constructor() with solely static methods) and register all those static methods as EL functions in your.taglib.xml as described in How to create a custom EL function to invoke a static method?
At least, this is what you should be doing when you intend to have a publicly reusable library such as JSTL fn:xxx(), PrimeFaces p:xxx() or OmniFaces of:xxx(). If you happen to use OmniFaces, then you could, instead of creating a your.taglib.xml file, reference the class in <o:importFunctions>. It will automatically export all public static methods of the given type into EL function scope.
<o:importFunctions type="com.example.Utils" var="u" />
...
<x:foo attr="#{u:foo(bean.property)}" />
If you don't use OmniFaces, and this all is for internal usage, then I can imagine that it becomes tiresome to redo all that your.taglib.xml registration boilerplate for every tiny utility function which suddenly pops up. I can rationalize and forgive abusing an application scoped bean for such "internal usage only" cases. Only when you start to externalize/modularize/publicize it, then you should really register them as EL functions and not expose poor practices into public.

Inject ConversationScoped beans within an asynchronous method

I need to call a method annotated with #Asynchronous in EJB from a ConversationScoped bean. Inside this method I create instances of some classes using #Inject to inject ConversationScoped beans.
Is it somehow possible to set the context of the asynchronous method to given Conversation?
I hope you can help me.
No, absolutely not. EJBs do per definition not run in web container, but in EJB container. In essence, having any web-related artifact/dependency (including javax.faces.* classes) inside an EJB class is a red alert. You're not supposed to inject/access any class from the client tier (the WAR) in the business tier (the EJB/EAR). Moreover, conversation scoped beans are tied to a HTTP request parameter and this information is nowhere available in an EJB container.
Whatever problem you're trying to solve and for which you incorrectly thought that this all would be the right solution, it has to be solved differently. As an educated guess, I think you just need to let the EJB fire a CDI event or take a callback argument.
See also:
JSF Service Layer

java.io.NotSerializableException: org.primefaces.model.DefaultStreamedContent

I have a simple jsf 2.1 that used to work fine on Java EE 6 using primefaces 3.4.
When I migrated to glassfish 4.0 and primefaces 5.1 I've got the following exceptions each time I redeploy the project on Netbeans:
java.io.NotSerializableException: org.primefaces.model.DefaultStreamedContent
java.io.NotSerializableException: org.primefaces.component.datatable.DataTable
Even if this exception is thrown, the project is deployed and run correctly!
What could be wrong?
You've declared those types as a property of a view or session scoped managed bean. You should absolutely not do that. You should declare them as a property of a request scoped bean.
View and session scoped beans must be Serializable because view scoped beans are reused/shared across multiple requests on the same view in the same session, and session scoped beans are reused/shared across multiple requests in the same session. Anything tied to a specific HTTP session must be Serializable, because it enables the server to store sessions on disk, so it could be shared among other servers in a cluster, or survive server restarts.
The DefaultStreamedContent (and the InputStream it is wrapping, if any) may absolutely not be created and assigned as a view/session scoped bean property, not only because it's not serializable, but also because it can be read only once. You need to create this in the getter method only. This is indeed a rather special case which is fleshed out further in this answer: Display dynamic image from database with p:graphicImage and StreamedContent
The DataTable is a JSF component which you most likely referenced via binding attribute. It may absolutely not be assigned as a view/session scoped bean property, because UI components are inherently request scoped. Reusing the same UI component instance across multiple restored views in the same session may cause its state being shared across multiple requests (NOT threadsafe thus!) and/or potential "Duplicate Component ID" errors. See also a.o. How does the 'binding' attribute work in JSF? When and how should it be used?
NotSerializableException is thrown when an instance of a class must implement the Serializable interface.
If the class that throws the exception does not belong to a third-party library, find the class and make it implement the serializable interface.
If you do not want to serialize the objects in the class, you can mark the objects as transient, to make the serializable runtime ignore the objects.
You can read about it here

How to access #ViewScoped managed beans from Servlets?

I would like to access a view scope managed bean inside a Servlet.
I searched for similar question and got these ones:
how to get beans from view scope which uses FacesContext.getCurrentInstance(), inapplicable inside a Servlet because it should give a null result
JSF - get managed bean by name which treats all other scopes but not viewscope
I'm going to think it is not possible, is it ?
There is the simple solution to change that bean scope to session scope but it is a last chance because I'm worried by memory consumption.
My final need is the following: the managebean contains some data displayed in a dataTable. The same page should include the image (mandatory) of chart representation of those data. The image can be produced by a Servlet but it needs to access the data or reload them from the db.
I also tried the <p:graphicImage> from PrimeFaces 2.X but it is not compatible with viewscope beans. Any suggestion?
That's not possible, no. The view scope is tied to a specific JSF view, which is no means of in a plain HTTP servlet request. Note that you can't access concrete request scoped beans during a plain HTTP servlet request either, they would always return null.
The session scope is the best what you can get. You can just remove the attribute from the session scope once you're finished with it in the servlet.
session.removeAttribute("somename");

What is FacesContext used for?

What is FacesContext used for?
And where exactly is it implemented?
Quote from chapter 6.1 of JSF 2.0 specification:
FacesContext
JSF defines the
javax.faces.context.FacesContext
abstract base class for representing
all of the contextual information
associated with processing an incoming
request, and creating the
corresponding response.
A FacesContext
instance is created by the JSF
implementation, prior to beginning the
request processing lifecycle, by a
call to the getFacesContext method of
FacesContextFactory, as described in
Section 6.6 “FacesContextFactory”.
When the request processing lifecycle
has been completed, the JSF
implementation will call the release
method, which gives JSF
implementations the opportunity to
release any acquired resources, as
well as to pool and recycle
FacesContext instances rather than
creating new ones for each request.
It is specified in class javax.faces.context.FacesContext and in Mojarra implemented in class com.sun.faces.context.FacesContextImpl and in MyFaces implemented in class org.apache.myfaces.context.servlet.FacesContextImpl.
See also:
What is the difference between FacesContext and ExternalContext
A new instance of FacesContext gets created with every new request. The main task of FacesContext is to provide all the information regarding the particular request with which it is associated.
For example : to add messages after certain validation or conversion failure, you can simply add the message to the FacesContext which ultimately displays the desired message on the screen.
Also you can take a look and even stop the JSF lifecycle at any point by calling
FacesContext.responseComplete();
FacesContext contains all of the per-request state information related to the processing of a single JavaServer Faces request, and the rendering of the corresponding response. It is passed to, and potentially modified by, each phase of the request processing lifecycle.
A FacesContext instance is associated with a particular request at the beginning of request processing, by a call to the getFacesContext() method of the FacesContextFactory instance associated with the current web application. The instance remains active until its release() method is called, after which no further references to this instance are allowed. While a FacesContext instance is active, it must not be referenced from any thread other than the one upon which the servlet container executing this web application utilizes for the processing of this request.
reference:
http://docs.oracle.com/javaee/6/api/javax/faces/context/FacesContext.html
The Facescontext is the anchor point for connecting to framework-and
container- specific services. For example, you can obtain the
underlying httprequest and context objects for the page request that's
accessing your backing bean by going through the Facescontext. That
includes the security context a web page request is running under.
The general philosophy behind JSF is that the user-provided components
should be abstract enough not to depend on such details as to whether
they're running in a traditional JSP environment or something more
exotic, so if there's a Facescontext reference in the bean, it's a
potential sign of bad design, especially since beans are expected to
have things injected into them, not go out looking for stuff.
However, sometimes for one reason or another, it's convenient to reach
out of the backing bean and obtain the outlying information, so it's
there if you need it.
Reference: What is the use of Facescontext Context Object

Resources