I'm wondering if it's possible to set up or rewrite a servlet so that it can get a FacesContext.getCurrentInstance().
What I have is a database of images that is accessed through a JSF application. On a particular page, there are inline images like: <graphicImage value="ImageServlet?image_id=5" />
ImageServlet.java retrieves the image data and streams it back to your web browser.
This would work if it weren't for the fact that there's some security checking in the database retrieval code, which retrieves the session's user using FacesContext (different users are allowed to access different images). But since the servlet is just a plain servlet and not JSF, FacesContext.getCurrentInstance() will return null. Usually, database retrievals are done through JSF pages, but the ImageServlet is a special case.
Now, it is quite possible to modify the above code in such a way that it disables the regular security check and does the security check on its own using a regular servlet request.getSession(), but this would not be good practice, since having two parallel and functionally identical security check code would make it difficult to maintain (and easy to introduce future security problems with the images).
Is there any way to write or configure a servlet like this so that it can have access to these JSF services? Maybe write some kind of custom servlet that extends FacesServlet and put it in web.xml or something like that?
If you're using J2EE role-based (container) security you can just invoke isUserInRole() on the request for broad role access control or use getRemoteUser() to get the userId if you need to do something like validate on a per-user basis.
JSF is a framework, and the JSF context only exists duing a JSF request. Http Requests to non-JSF objects such as servlets and JSP's therefore can't query the JSF context for the simple reason that the request isn't in a JSF context.
It confused me, too, originally. The simple answer is that JSF is injecting session and request scope values into the JSF context. It has no magically-persistent data of its own. So if you want to access information, place it in the same places you would for a completely non-JSF app. The servlets and JSPs will be happy, and you can make the information also available to JSF beans by wiring it in via faces-config.xml.
An IDE is no substitute for an Intelligent Developer.
Joined: Jan 26, 2002
That's interesting about JSF injecting values into the context. I wonder if I could do the same? I don't know anything about the injection and inversion of control coding patterns.
What my image security code is trying to do is retrieve a JSF managed session bean for the user, which it can access through the HttpSession, which in turn it can access via static FacesContext FacesContext.getCurrentInstance(). Is there an equivalent way in a non-JSF app to retrieve the HttpSession? I obviously don't want to have to pass it from ImageServlet.doGet(HttpRequest) down through the bowels of the code, as the static FacesContext.getCurrentInstance() has been convenient up until now for doing security checks at the deepest levels.
I can think of two possible ways to solve my problem. I wonder if you think either of these would be feasible:
1. Emulate and copy the JSF context set-up methodology used by FacesServlet, in my ImageServlet so that code called from ImageServlet has access to FacesContext. Maybe I can look at the open source MyFaces and see how it sets up a JSF context?
2. Instead of making my image database retrieval page a servlet, make it a JSF. Is it even possible to write a JSF page that streams out an image? I wasn't sure, and it seemed like a job for a servlet, which was why I wrote ImageServlet.
Joined: Jan 26, 2002
I found a way around the problem. I looked at the source code for FacesContext.java in the Apache MyFaces project, and noted that it used thread local storage using java.lang.ThreadLocal, so I used the same technique to store the session information I needed.