Access a Managed Bean created by JSF in a servlet through a session - session

I'm trying to communicate JSF variables to a servlet, the way I found to do this was storing these variables in the session and then accessing them in the servlet. It worked fine in my first tests, but now, for apparent no reason, it's just not working.
Now, the servlet cannot find a session, it returns null. As if was not strange enough, it returns null just when i'm using Firefox and Chrome, if I use IE it returns the session correctly. I already restarted all browsers to restart sessions, but it still doesn't work.
My problem is: I need to communicate an attribute in my composite component to the servlet, here is what I'm doing:
...
<composite:implementation>
<f:metadata>
<f:event type="preRenderView" listener="#{Plupload.inicialize(cc.attrs.value, cc.attrs.servletPath,cc.attrs.runtimePreferences,cc.attrs.maxFileSize,cc.attrs.resizingWidth, cc.attrs.resizingHeight,cc.attrs.resizingQuality, cc.attrs.allowedTypes)}" />
</f:metadata>
...
</composite:implementation>
Plupload is a SessionScoped bean, with its method "initialize" I pass all the attributes I need to the session.
In the servlet I do the following:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession(false);
if (session == null) System.out.println("null session");
plupload = (Plupload) session.getAttribute("Plupload");
...
}
The result when doPost is executed is "null session" printed in the screen and a NullPointerException throwed by line:
plupload = (Plupload) session.getAttribute("Plupload");
Of course, unless I'm executing it in IE.
Thanks in advance for any answer.

Related

Spring MVC redirect to page with custom parameter when session expired

I can not find any solutions for Spring to redirect to page together with parameters when session is timed out. I need to redirect to login page with error like "Session expired". I have tried filter and method session.isNew(). But it does not work since when request reaches login page it always already has session. Also HttpSessionEvent handler does not work because does not allow to access to request attributes and redirect to page.
The easiest way would be to create an Interceptor that adds the Refresh header to every response with a time just after session expiry.
public class RefreshInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle (
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView
) throws Exception {
//if session != null and user is authenticated then...
response.setIntHeader("Refresh", figureOutWhenSessionExpires() + A_SMALL_DELAY );
super.postHandle(request, response, handler, modelAndView);
}
}

Spring AsyncUncaughtExceptionHandler : Show error on JSF page

My email-sending code (a Spring managed bean) is executed asychronous (using Springs #Async Annotation) because our email-server seems rather slow (takes 3-4 seconds until the mail is sent). The email method throws an checked excpetion if the email cannot be sent.
Now I'm sending emails from my JSF-managed bean (i.e. my controller), e.g. to send credentials to newly created users and want to show a growl Message to inform the (admin-)user that the email sending code threw an excpetion (I know that there will be a delay, but thats seems ok as it does not block the gui thread).
What I've done so far:
I implemented my custom AsyncUncaughtExceptionHandler, i.e. the method:
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
#Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
// inform user that something went wrong (growl message)
}
}
This handler is then specified in Spring's XML config:
<bean id="exceptionHandler" class="org.myproject.util.CustomAsyncExceptionHandler" />
<task:annotation-driven executor="asyncExecutor" scheduler="asyncScheduler" exception-handler="exceptionHandler" />
<task:executor id="asyncExecutor" pool-size="5" />
<task:scheduler id="asyncScheduler" pool-size="10" /
The problem is that I cannot access the FacesContext in this exceptionHandler (which is a spring-managed bean).
How can I do this and if not, is there another way to let the user know that the async method threw an excpetion?

Broken HttpSession integrity in distributed WAS7 environment

The project is running on WAS7 with load balancing environment, using JSF2.1 and primefaces4. After authentication filter the userinfo is to put it into session. when viewing the page backend bean is getting the user info from session using facescontext like below, bean scope is viewscoped
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context
.getExternalContext().getRequest();
HttpSession session = request.getSession(false);
UserInfo userInfo= null;
if(session != null) {
userInfo= (UserProfile) session
.getAttribute("UserInfo");
// do some logic
}
Its working fine as expected. when more number user (concurrently) accessing the page or doing same operation in the page at the same time, some times session gives wrong object i.e. other users info object not mine. Based on the user info the all business logic is getting executed, so the page shows wrong info.
Any idea why is this happening, and a solution to prevent this if any ?

JSF 2 Partial Requests doesn't use FacesContext from the Factory

It seems like the partial requests don't use the faces context instances that are created by FacesContextFactory implementations.
Here's the code in UIViewRoot#processDecodes that indicates the same
if (context.getPartialViewContext().isPartialRequest() &&
!context.getPartialViewContext().isExecuteAll()) {
context.getPartialViewContext().processPartial(PhaseId.APPLY_REQUEST_VALUES);
} else {
super.processDecodes(context);
}
It seems like the PartialViewContext stores the default FacesContextImpl implementation within it and uses it to call lifecycle methods. (Notice that the processPartial method doesn't take a context object, because it uses it own internally stored one)
Is this a bug or this code in there for a specific reason?
Thanks
FacesContext instances are unique per thread, and The FacesServlet creates a ThreadLocal<FacesContext> on the beginning of the request while acquiring the FacesContext (which is the contract of FacesContextFactory#getFacesContext) and removes it on the end of the response associated with the HTTP servlet request (by calling the FacesContext#release).
Whenever you do a FacesContext#getCurrentInstance() in your JSF code, you'll always get the same instance throughout the entire HTTP servlet request/response processing.
About the method UIViewRoot#processDecodes,I really don't see any line which probably can indicate that method uses it's own created instance rather than the passed one. Which line made you think that?
It can be seen in the FacesServlet#service method that it creates the FacesContext from The FacesContextFactory, here is a excerpt from the FacesServlet#service method which shows this -
// Acquire the FacesContext instance for this request
FacesContext context = facesContextFactory.getFacesContext
(servletConfig.getServletContext(), request, response, lifecycle);
// Execute the request processing lifecycle for this request
try {
...
} catch (FacesException e) {
...
}
finally {
// Release the FacesContext instance for this request
context.release();
}
Considering this, I don't feel UIViewRoot#processDecodes can have the FacesContext instance which is not from FacesContextFactory.
Since you're saying - you have set some additional parameters to the FacesContext which get returned from FacesContextFactory, that means you have your own custom implementation of FacesContextFactory, if this is the case then are you sure that your instance is injected in the FacesServlet and not mojarra's com.sun.faces.context.FacesContextFactoryImpl (if you're using mojarra)?
Here's how i got it to work. Below is the code in my custom faces context factory
public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle) throws FacesException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
ExternalContextFactory externalContextFactory = (ExternalContextFactory) getFactory(FactoryFinder.EXTERNAL_CONTEXT_FACTORY);
ExternalContext externalContext = externalContextFactory.getExternalContext(context, request, response);
// CustomFacesContext extends from FacesContextImpl
CustomFacesContext facesContext = new CustomFacesContext(externalContext, lifecycle);
ExceptionHandlerFactory exceptionHandlerFactory = (ExceptionHandlerFactory) getFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY);
ExceptionHandler exceptionHandler = exceptionHandlerFactory.getExceptionHandler();
facesContext.setExceptionHandler(exceptionHandler);
}

Captcha servlet causes java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed

I am creating a CAPTCHA input using SimpleCaptcha, and did validation of the Captcha input. I am created a captcha input with the following codes.
HTML Code:
<form action="submit_proceed.do" method="post">
<img src="captchaImg" /><input type="text" name="captcha" value=""><br />
<input type="submit" value="Submit" name="submit" />
</form>
JavaServlet Code :
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Iterator;
import nl.captcha.Captcha;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
List errorMsgs = new LinkedList();
try{
// Validate Captcha
HttpSession session = request.getSession(true);
String userCaptcha = request.getParameter("captcha");
Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
if (!captcha.isCorrect(userCaptcha)) {
errorMsgs.add("Please input the correct Captcha value.");
}
} catch (RuntimeException e) {
errorMsgs.add("An unexpected error: " + e.getMessage());
RequestDispatcher view = request.getRequestDispatcher("/error.view");
view.forward(request, response);
}
However I kept getting this error:
StandardWrapperValve[Captcha]: PWC1406: Servlet.service() for servlet Captcha threw exception
java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed
How do I create a session on my servlet? How can I resolve this issue?
Thank you very much.
Cannot create a session after the response has been committed
The exception message is pretty clear. There's means of an illegal state. You cannot set/change the response headers anymore when the response is already been committed. A response is committed when the headers are already been sent to the client side. This is a point of no return.
The response will be committed whenever the outputstream has been flushed (in)directly. That can happen when you write more than 2K to the response (depends on server config however), or did flush() manually, or did a sendRedirect() call.
Whenever the session needs to be created, the server needs to set a cookie in the response header so that it can identify the particular client and associate it with a HttpSession instance in the server memory. But that's not possible if the response is already committed, hence this exception.
Back to the root cause of this problem:
Servlet.service() for servlet Captcha threw exception
It is the servlet with the servlet-name of Captcha which caused this problem. You need to check/debug the entire request-response chain to see which servlets/filters are all invoked and which of them might have committed the response before the Captcha servlet was able to create the session. I can't help you more further as this information is missing in your topicstart.
At least, in the as far given code example, I see that you're unnecessarily calling response.getWriter(). I am not sure how the real world code look like, maybe you've stripped some lines, but chances are that you're actually writing to it and that might be the root cause of the problem. If you write too much or did a flush on it, then the resopnse will be committed. Do not write to the response inside a Servlet which is supposed to be a controller. There you normally use the JSP for. Or if it is for debugging purposes, use the stdout (System.out.println()) or a Logger.
The offending code is in nl.captcha.servlet.SimpleCaptchaServlet Servlet. If you change it to StickyCaptcha the problem will go away but specifically the following are the offending lines in SimpleCaptcha Servlet.
CaptchaServletUtil.writeImage(resp, captcha.getImage());
req.getSession().setAttribute(NAME, captcha);
Actually the code is writing the image file to response (which is usually greater than default 2k).
So for the time being you can use the StickyCaptcha or checkout the code and fix the issue.
Move this line:
HttpSession session = request.getSession(true);
to be first statement in doPost method.
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(true);
response.setContentType("text/html;charset=UTF-8");
//...
}
This should help.
Seems, that you already sent the header to the client before handling the post. If you create a session, the server needs to send the session ID to the client. This is usually done by sending a cookie. I suppose you check your code for whether you execute the action handling before you send anything back to the client.
create session by adding this
javax.servlet.http.HttpSession session = request.getSession();
try{
javax.servlet.http.HttpSession session = request.getSession();
// Validate Captcha
String userCaptcha = request.getParameter("captcha");
Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
if (!captcha.isCorrect(userCaptcha)) {
errorMsgs.add("Please input the correct Captcha value.");
}
} catch (RuntimeException e) {
...
}
This line
(Captcha) session.getAttribute(Captcha.NAME);
implies that the session should already exist before this particular request is being processed, hence I wonder is there is some initialisation you are supposed to do before sending your original form. This should be specified by the framework your are using.
For example you might have an initial serlvet that
creates the image, figures out the value of Capcha.Name
creates the session
session.setAttribute(Capcha.NAME, theName)
emit the html (or forward() to a JSP)
You could do that all in a JSP, or you could have your servlet forward to one.
Are there any examples of usage of this catcha library you could examine?

Resources