Access ViewScoped ManagedBean from Servlet - jsf

Background information: I have a file upload applet in my jsf page. This applet expects an adress where it can send it's POST request. (I can't edit this post request to add more fields or something). The post method of my servlet then stores the file. This job can't be done by a managed bean because the servlet has to be annotated with #MultiPartConfig and I can't add this annotation to the jsf managed bean. In order to force the upload applet to use the same session I added an URL attribute named jsessionId to the post request according to this post. In my servlet I am now able to access session scoped beans.
Now I have a ViewScoped bean where I store some form input data which I want to use in the servlet, since adding those inputs to the post request doesn't work (Applet is a third party project (JUploadApplet) and for some reason it doesn't work to add additional form data).
Now is it possible to access the ViewScoped bean from within the servlet ? If I change the scope into SessionScope I am able to process the input but with ViewScoped I get a NullPointerException if I try to access the bean like this :
UploadBean uploadBean = (UploadBean)request.getSession().getAttribute("uploadBean");

This is not possible. Your best bet is to let the view scoped bean generate an unique key, store itself in the session scope by that key and pass that key as additional parameter to the applet and finally let the servlet access the session attribute by that key.
E.g.
private String sessionKey;
#PostConstruct
public void init() {
sessionKey = UUID.randomUUID().toString();
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(sessionKey, this);
}
#PreDestroy
public void destroy() {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(sessionKey);
}
Let the applet pass the sessionKey as request parameter to the servlet, so that the servlet can do
String sessionKey = request.getParameter("sessionKey");
Bean bean = (Bean) request.getSession().getAttribute(sessionKey);
// ...
Note that instead of the bean itself, you can also just store an arbitrary bean/valueobject/etc.

Related

How to initialise a Managed Bean in request scope from a servlet

I have a servlet that will navigate to a JSF page upon some conditions using ExternalContext.redirect.
I need to initialise a Managed Bean in this Servlet and set it in request scope so that my JSF page can directly access the Managed Bean's property and display them on the page load.
I had seen posts that sets the bean using getServletContext()
Like,
getServletContext().setAttribute("beanName",new Bean())
it works.But this approach will be setting the bean in application scope instead of request scope.
Also i tried the following:
request.setAttribute("beanName",new Bean())
it doesnt work
So pls let me know if there is any way to set /initialise a managed bean in a request scope
If it's a request scoped bean, use HttpServletRequest#setAttribute()
BeanName beanName = new BeanName();
request.setAttribute("beanName", beanName);
If its a session scoped bean,
request.getSession().setAttribute("beanName", beanName);

Access session scoped JSF managed bean in web filter

I have SessionScoped bean called userSession to keep track of the user ( username, ifLogged, etc). I want to filter some pages and therefore I need to access the bean from the webFilter I created. How do I do that? I looks like its even impossible to import the bean to be potenitally visible.
Under the covers, JSF stores session scoped managed beans as an attribute of the HttpSession with the managed bean name as key.
So, provided that you've a #ManagedBean #SessionScoped public class User {}, just this should do inside the doFilter() method:
HttpSession session = ((HttpServletRequest) request).getSession(false);
User user = (session != null) ? (User) session.getAttribute("user") : null;
if (user != null && user.isLoggedIn()) {
// Logged in.
}
Or, if you're actually using CDI instead of JSF to manage beans, then just use #Inject directly in the filter.
See also:
Get JSF managed bean by name in any Servlet related class
Prevent accessing restricted page without login in Jsf2
As an alternative you can use CDI-beans and inject your sessionbean normally.

What is the relation between session scoped beans and HttpServletRequest?

While trying to figure out how to implement a login filter for a JSF app I saw these 2 lines of code that I didn't understand that much :
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
LoginBean login = (LoginBean) req.getSession().getAttribute("login");
}
Assuming that LoginBean class is a session scoped bean named "login" , as I noticed the bean is an attribute for the request , what is the relation between them ? are all session scoped bean saved as "attributes" in request sessions ?
are all session scoped bean saved as "attributes" in request sessions ?
That's correct. JSF is just a MVC framework which is built on top of the bare Servlet API, not an entirely standalone framework which can run without the Servlet API. Even more, the JSF core controller FacesServlet is a fullworthy Servlet, so it definitely requires a servlet container to run. The concept "session" is in the Servlet API provided by HttpSession, so it would make fully sense to store JSF session scoped beans in there instead of reinventing it.
Note that JSF request scoped beans are stored as HttpServletRequest attributes and that JSF application scoped beans are stored as ServletContext attributes.
See also:
Get JSF managed bean by name in any Servlet related class
How do servlets work? Instantiation, sessions, shared variables and multithreading

Direct URL to a JSF bean action

Is there any way to get direct URL to a JSF bean action method?
Basically I want to be able to do the following:
click
And this should invoke a method in a JSF bean. Is it possible?
I'm using JSF 1.2.
Do the job in the constructor of the request scoped bean associated with the view behind the URL.
public class Bean {
public Bean() {
// Here.
}
// ...
}
As long as you've a #{bean.something} in the view, then the bean's constructor will be invoked.

How could I read a JSF session bean from a filter?

I'm searching but I can't find the answer, I need secure resources based on permissions, I can't use a filter because FacesContext is not initialized before and I need load the permissions in my session bean. Some solution avoiding use a filter? PhaseListener, ViewHandler and ResourceHandler can't capture an URL resource request, for example I need denied this direct access: http://127.0.0.1:8080/test/resources/images/image.jpg
Thx in advance...
JSF stores session scoped managed beans as an attribute of the HttpSession, which in turn is just available in a Filter by HttpServletRequest#getSession().
HttpSession session = ((HttpServletRequest) request).getSession();
SessionBean sessionBean = session.getAttribute("sessionBean");
// ...
Update: as per the comment you seem to be actually using CDI:
my filter is triggered before than JSF, I always get a null value when I use getAttribute. I'm using CDI with 'Named' and 'SessionScoped' annotations on my Bean because I need use a interceptor to implement security
I understood that you were using JSF's own #ManagedBean and the initial answer only applies to that. If your bean is already managed by CDI's #Named, then just use CDI's own #Inject the usual way in the Filter.
#Inject
private SessionBean sessionBean;
In case of JSF #ManagedBean you should just add a if (sessionBean != null) check. It's irrelevant whether the filter is invoked before JSF servlet or not. Once the session bean has been created by JSF, it won't be null in the filter.

Resources