Servlet filter which is mapped on /home is not invoked when I open /home.xhtml - jsf

I am new to Java Enterprise Edition. I started learning from some YouTube videos, and recently started reading http://docs.oracle.com/javaee/6/tutorial/doc/ I finished chapter 15.
I tried to make my own filter.
I didn't use Java Servlet class. Because I want to use JSF pages, and as far as I know it is only possible to use Managed Beans with JSF pages, Whereas Servlet classes work with JSP. It is OK.
As far as I know the usefulness of login filter:
https://stackoverflow.com/tags/servlet-filters/info
[...] This is particularly useful when you have multiple pages for which
you'd like to check the logged-in user. Instead of copypasting the
same logic over all pages, you can use a Filter to have it in a single
place.
It is useful (as I know) in the case when a user type the URL directly into the browser for a page which require logged in user, so the filter will redirect him to the login page or continue if he is logged in.
I searched for any simple example to learn from but didn't find. I will put my simple example:
I have two JSF pages
one is named home.xhtml (which require logged in user)
the other one is named login.xhtml (filter must redirect to it if non-logged users seek home)
login.xhtml:
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="name:"/> <h:inputText value="#{user.name}"/>
<h:outputLabel value="password:"/> <h:inputSecret value="#{user.password}"/>
</h:panelGrid>
<h:commandButton id="btn" value="login" action="#{user.login()}"/>
</h:form>
home.xhtml:
<h:body>
Hello #{user.name}. You are welcome
</h:body>
User:
#ManagedBean
#SessionScoped
public class User implements Serializable
{
String name;
String password;
Authentication authentication;
public User()
{
authentication = new Authentication();
}
//Getters and Setters for name and password.
public String login()
{
if (this.getName().equals("user") &&(this.getPassword().equals("1234")))
{
authentication.setLoggedIn(true);
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("auth", authentication);
return "home";
}
else
{
authentication.setLoggedIn(false);
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("auth", authentication);
return "login";
}
}
}
Authentication:
#ManagedBean
#SessionScoped
public class Authentication implements Serializable
{
private boolean authenticated;
public Authentication()
{
authenticated = false;
}
public boolean isLoggedIn()
{
return authenticated;
}
public void setLoggedIn(boolean authenticated)
{
this.authenticated = authenticated;
}
}
LoginFilter:
#WebFilter(value = "/home")
public class LoginFilter implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
//throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException
{
HttpServletRequest req = (HttpServletRequest) request;
Authentication auth = (Authentication) req.getSession().getAttribute("auth");
if (auth != null && auth.isLoggedIn())
{
System.out.println("Filter is working");
chain.doFilter(request, response);
} else
{
System.out.println("Filter is working");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath() + "/login.xhtml");
}
}
#Override
public void destroy()
{
//throw new UnsupportedOperationException("Not supported yet.");
}
}
faces-config:
<navigation-rule>
<from-view-id>/login.xhtml</from-view-id>
<navigation-case>
<from-outcome>home</from-outcome>
<to-view-id>/home.xhtml</to-view-id>
<redirect/>
</navigation-case>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
web.xml:
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/login.xhtml</welcome-file>
</welcome-file-list>
Now when I type the URL of home.xhtml page (after clearing history & cookies) into the browser it is assumed to redirect me to login page. But instead it goes to home with empty value for name:
Hello #{user.name}. You are welcome is rendered as Hello . You are welcome
Even System.out.println("Filter is working"); not print anything.

Are you sure the filter is called? If there is nothing printed to System.out I guess not. The problem might be the servlet mapping.
You specified this:
#WebFilter(value = "/home")
public class LoginFilter implements Filter {...}
I think this only matches the url /home. Try to use /* or /home* (which is very limiting, I would not recommend it) instead.
Another thing: If you get Hello #{user.name}. You are welcome as output, then the FacesServlet is probably not called. This might have two reasons:
You use the wrong mapping. Try to call the page with /faces/home.xhtml or /home.jsf instead. The url depends on the type of mapping you have in the web.xml.
The FacesServlet is not configured correctly/at all in the web.xml.

Related

Simple Jetty/JSF file upload won't submit

I've already looked at this one and the related tickets to no avail.
I have, what looks like the, simplest example possible
<h:form enctype="multipart/form-data" prependId="false">
<h:outputText value="File: "></h:outputText>
<h:inputFile value="#{configUploadController.uploadedFile}" />
<h:commandButton value="Save" type="submit" action="#{configUploadController.uploadFile}" style="color: red;"></h:commandButton>
</h:form>
I put a breakpoint in my uploadFile method but it never gits hit. when I remove the enctype from the form it does try to submit but then I get the obvious error...
javax.servlet.ServletException: Content-Type != multipart/form-data
And just for completeness, I remove the <h:inputFile> and enctype and can see my breakpoint being hit. When I set enctype to text/plain it DOESNT hit the breakpoint. However, when I set enctype to gibberish it DOES hit the breakpoint :(
Am I missing a dependency or config somewhere?
And in case it matters, my web.xml...
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- File(s) appended to a request for a URL that is not mapped to a web
component -->
<welcome-file-list>
<welcome-file>status.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<listener>
<description>Initializes Oracle JSF</description>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<!-- Define the JSF servlet (manages the request processing life cycle for
JavaServer Faces) -->
<servlet>
<servlet-name>faces-servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<!-- Map following files to the JSF servlet -->
<servlet-mapping>
<servlet-name>faces-servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
jsf-api-2.2.15
jsf-impl-2.2.15
el-api-2.2
el-impl-2.2
jetty 9.4.18
javax.servlet-api-3.1.0
Instead of working around with a servlet (as per other answer) the actual problem was Jetty needs the multipart config setting up per multipart request.
Simple way to do this would be to add a filter that adds it as necessary, eg.
public class LoginFilter implements Filter {
private static final String MULTIPART_FORM_DATA = "multipart/form-data";
private static final MultipartConfigElement MULTI_PART_CONFIG =
new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String contentType = request.getContentType();
if (contentType != null && contentType.startsWith(MULTIPART_FORM_DATA))
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, MULTI_PART_CONFIG);
filterChain.doFilter(request, response);
}
}
See also:
How to implement FileUpload in embedded Jetty?
So, I haven't spent the time to track down why but jetty doesn't appear to like multipart forms. I got round it by using a servlet. Solution looks like this...
I've gone with ajax approach and a HTML form so I can specify my action, that matches the servlets pattern...
<form action="upload/config" enctype="multipart/form-data" method="post">
<h:inputFile id="file" />
<br />
<h:commandButton type="submit" value="Upload">
<f:ajax execute="file" render="#all"/>
</h:commandButton>
</form>
And the servlet...
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.MultipartConfigElement;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.eclipse.jetty.server.Request;
#WebServlet("upload")
#MultipartConfig
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) {
try {
// This needed to get access to the parts
MultipartConfigElement multipartConfigElement = new MultipartConfigElement((String)null);
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, multipartConfigElement);
Part filePart = request.getPart("file");
try ( InputStream inputStream = filePart.getInputStream(); ) {
// Do what you want with your part
} catch (Exception e) {
resp.setStatus(500);
}
} catch (Exception e) {
resp.setStatus(500);
}
}
}

#PostConstruct of #Named #Sessionscoped called multiple times during single request

I'm trying to execute a "helloWorld" project type to learn CDI, and I'm a little lost, I don't understand the behaviour I notice.
Firstly, I tried to execute the examples from the WELD distribution, after having read its reference documentation : http://docs.jboss.org/weld/reference/latest/en-US/html/, Chapter 6
Well, I don't know why, but whatever I try, they do not work for me. So, I decided to "rewrite" the first exercise, and if I can now see the application running (JBoss EAP), I don't understand what's ocurring now :
MY project :
a Generator (ApplicationScoped) which calculate a random number :
#ApplicationScoped
public class Generator implements Serializable{
private static final int MAX_NUMBER = 100;
private java.util.Random random = new java.util.Random(System.currentTimeMillis());
/**
* Serializable
*/
private static final long serialVersionUID = 7388013951586598074L;
#Produces
public #MaxNumber int getMaxNumber(){
return MAX_NUMBER;
}
java.util.Random getRandom() {
return random;
}
#Produces
#Random
int next() {
//a number between 1 and 100
return getRandom().nextInt(MAX_NUMBER - 1) + 1;
}
}
A Game bean, SessionScoped
#SessionScoped
#Named
public class Game implements Serializable{
/**
* Serializable
*/
private static final long serialVersionUID = 8480529461297926872L;
/**
* The real number
*/
private int number;
/**
* The guessed number
*/
private int guess;
/**
* The limit min/max of number could be (updated for each try)
*/
private int biggest;
private int smallest;
/**
* Remaining guesses
*/
private int remainingGuesses;
#Inject
private #MaxNumber int maxNumber;
#Inject
private #Random Instance<Integer> randomNumber;
public void check(){
if (guess > number) {
biggest = guess - 1;
} else if (guess < number) {
smallest = guess + 1;
} else if (guess == number) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
}
remainingGuesses--;
}
#PostConstruct
public void reset(){
this.smallest = 0;
this.guess = 0;
this.remainingGuesses = 10;
this.biggest = maxNumber;
this.number = randomNumber.get();
}
public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
if (remainingGuesses <= 0) {
FacesMessage message = new FacesMessage("No guesses left!");
context.addMessage(toValidate.getClientId(context), message);
((UIInput) toValidate).setValid(false);
return;
}
int input = (Integer) value;
if (input < smallest || input > biggest) {
((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid guess");
context.addMessage(toValidate.getClientId(context), message);
}
}
public int getNumber() {
return number;
}
public int getBiggest() {
return biggest;
}
public int getSmallest() {
return smallest;
}
public int getRemainingGuesses() {
return remainingGuesses;
}
public void setRemainingGuesses(int remainingGuesses) {
this.remainingGuesses = remainingGuesses;
}
public int getGuess() {
return guess;
}
public void setGuess(int guess) {
this.guess = guess;
}
}
My two annotations (I put MaxNumber, Random is the same with Random name) :
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({TYPE,METHOD,FIELD, PARAMETER})
public #interface MaxNumber {
}
I have my beans.xml, faces-config and web.xml in my WEB-INF folder (nothing else but DOCTYPE, ... in the first 2 files)
and the web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>Try and guess</display-name>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
And, to conclude, my index.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<ui:composition template="/template.xhtml">
<ui:define name="content">
<h1>Guess a number...</h1>
<h:form id="numberGuess">
<div style="color: red">
<h:messages id="messages" globalOnly="false" />
<h:outputText id="Higher" value="Higher!"
rendered="#{game.number gt game.guess and game.guess ne 0}" />
<h:outputText id="Lower" value="Lower!"
rendered="#{game.number lt game.guess and game.guess ne 0}" />
</div>
<div>
I'm thinking of a number between <span id="numberGuess:smallest">#{game.smallest}</span>
and <span id="numberGuess:biggest">#{game.biggest}</span>. You have
#{game.remainingGuesses} guesses remaining.
</div>
<div>
Your guess:
<h:inputText id="inputGuess" value="#{game.guess}" required="true"
size="3" disabled="#{game.number eq game.guess}"
validator="#{game.validateNumberRange}" />
<h:commandButton id="guessButton" value="Guess"
action="#{game.check}" disabled="#{game.number eq game.guess}" />
</div>
<div>
<h:commandButton id="restartButton" value="Reset"
action="#{game.reset}" immediate="true" />
</div>
</h:form>
</ui:define>
</ui:composition>
</html>
Well, now, what's occurring :
When I try to access my page, the reset method (marked with PostConstruct) is called several times before index.xhtml is shown. The values shown are the expected one (as it's the first time we access the page)
I try to put a number and click on the guess button and, the method reset is called several times (I don't know really why), and my method check (the expected one), one time, to do its job. But then the reset method is called again, and the page shown is in the same state as it was at the beginning.
So the question is :
- Why the reset method is called more than once at the beginning ?
- Why the reset method is called then?
Thanks you
Cheloute
Well,
I thought that javax.enterprise.context.SessionScoped and javax.faces.bean.SessionScoped were equivalent, but I was wrong :)
I supposed my Game bean was actually with a Dependent scope, as javax.faces.bean.SessionScoped wasn't process as the expected SessionScoped...

How to upload files without turning it to temporary file? (NetBeans JSF Primefaces)

Good day to all!
I've been making a simple web Application using Netbeans, JSF and Primefaces that can upload .csv, .jpeg/.jpg and .pdf files. I made 2 folders which was stored in drive C: (uploaded folder and tmp folder).
I assigned the "uploaded" folder to where the uploaded files are stored and the "tmp" for the .tmp of the uploaded files. I've been through many question threads and video tutorial which I followed correctly.
I also downloaded the commons fileupload and commons io and added it to the library. It is working fine, it displays that it is uploading and even saw the .tmp file on the folder i assigned it to.
But I cannot see the uploaded files on my "uploaded" folder.
So, my question is,
How can I upload these files into my "uploaded" folder.
Here are my codes:
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form enctype="multipart/form-data" >
<p:fileUpload fileUploadListener="#{FileUploadControl.fileUploadControl}"
mode="advanced"
update="messages"
auto="true"
sizeLimit="10000000"
allowTypes="/(\.|\/)(gif|jpe?g|csv|pdf)$/"
/>
<!-- -->
<p:growl id="messages" showDetail="true"/>
</h:form>
</h:body>
</html>
FileUploadControl.java
package controller;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.primefaces.model.UploadedFile;
#ManagedBean
#SessionScoped
public class FileUploadControl implements Serializable {
private String destination = "C:\\uploaded\\";
private UploadedFile file;
public UploadedFile getFile() {
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
}
public FileUploadControl() {
}
public void TransferFile(String fileName, InputStream in) {
try {
OutputStream out = new FileOutputStream(new File(destination + fileName));
int reader = 0;
byte[] bytes = new byte[(int) getFile().getSize()];
while ((reader = in.read(bytes)) != -1) {
out.write(bytes, 0, reader);
}
in.close();
out.flush();
out.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public void upload() {
String extValidate;
if (getFile() != null) {
String ext = getFile().getFileName();
if (ext != null) {
extValidate = ext.substring(ext.indexOf(".")+1);
} else {
extValidate = "null";
if (extValidate.equals("pdf")) {
try {
TransferFile(getFile().getFileName(), getFile().getInputstream());
} catch (IOException ex) {
Logger.getLogger(FileUploadControl.class.getName()).log(Level.SEVERE, null, ex);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Wrong", "Error Uploading file..."));
}
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Succesful", getFile().getFileName() + "is uploaded."));
} else {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Wrong_ext", "only extension .pdf"));
}
}
} else {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Wrong", "Select File!"));
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!--File upload commons -->
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
<init-param>
<param-name>thresholdSize</param-name>
<param-value>51200</param-value>
</init-param>
<init-param>
<param-name>uploadDirectory</param-name>
<param-value>C:\tmp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<!--File upload commons -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
Thank you for your response and help. looking forward to it!
The main reason it's failing as at now is that you haven't bound the value attribute to your backing bean variable, so getFile() will always return null and upload will do nothing.
You're still probably not going to get any results because it appears that you're trying to combine two different modes of operation of the <p:fileUpload/> component.
Simple mode
You don't define a fileUploadListener
You define a value attribute on the component and bind to the UploadedFile type attribute in your backing bean (which you have)
Advanced mode
You don't define a value attribute
You define a fileUploadListener which is bound to a method in your backing bean (which you also have)

Detect JSF session timeout/refresh/back/forward and return to login screen

I have a JSF 1.2 application that has a session going on and whenever the session timeouts or the user presses the browse back or refresh page, the session gets messed up and things start to behave unexpectedly.
I would like to simply bring the user back to a predefined login screen whenever that happens.
Authentication is handled inside the JSF application.
Thanks in Advance!
Try using PhaseListener
Example:
MyPhaseListener.java
public class MyPhaseListener implements PhaseListener {
public void afterPhase(PhaseEvent event) {
//If you have a login, so you have a user in session. Try to retrieve this value
//and it will return null if the user is not logged in or theres no more session
//and...
if (null == FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("myUserInSession") {
//Redirect to login using mapped navigation configs in faces-config.xml
try {
NavigationHandler nh = FacesContext.getCurrentInstance().getApplication().getNavigationHandler();
nh.handleNavigation(FacesContext.getCurrentInstance(), null, "stringToReturnLogin");
} catch (Exception e) {
}
//OR using redirect
try {
FacesContext.getCurrentInstance().getExternalContext().redirect("http://localhost:xxxx/App_Context/Page.xhtml");
} catch (Exception e) {
}
}
}
public void beforePhase(PhaseEvent event) {
//Do nothing
}
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
Configuring the listener in faces-config.xml
<faces-config version="1.2" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
(...)
<lifecycle>
<phase-listener>yourPackage.MyPhaseListener</phase-listener>
</lifecycle>
(...)
</faces-config>
Yes, you dont need to put ".java".
I know this is late but here goes anyway.
You probably want to put the following in your web.xml
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/faces/sales/index.xhtml</location>
</error-page>
That will redirect the ViewExpiredException. I guess that will hold for any other exceptions that come up.

Redirecting on session timeout in JSF-Richfaces-facelet

I am using JSF with RichFacecs to create a web portal .I want to redirect the user to the login page on session time out. I was trying to throw a SecurityException in session expiry/logged out stage as follows
<error-page>
<exception-type>java.lang.SecurityException</exception-type>
<location>/Login.jsf</location>
</error-page>
But this is not working for me. Which is the right way of handling this ?
This should do it :
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/sessionExpired.jsf</location>
</error-page>
you should put a timeout in your web.xml and register a timeout filter as shown in this thread: Auto-logout in JSF Application
in case of ajax, your redirection has to be done like that:
String facesRequestHeader = httpServletRequest
.getHeader( "Faces-Request" );
boolean isAjaxRequest = facesRequestHeader != null
&& facesRequestHeader.equals( "partial/ajax" );
if( isAjaxRequest )
{
String url = MessageFormat.format( "{0}://{1}:{2,number,####0}{3}",
request.getScheme(), request.getServerName(),
request.getServerPort(), timeoutPath );
PrintWriter pw = response.getWriter();
pw.println( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
pw.println( "<partial-response><redirect url=\"" + url
+ "\"></redirect></partial-response>" );
pw.flush(););
}
else
{
httpServletResponse.sendRedirect( timeoutPath );
}
The solution is to use Richfaces own session expired event.
Add this to the page prone to expire:
<a4j:region>
<script language="javascript">
A4J.AJAX.onExpired = function(loc, expiredMsg){
alert('expired!');
window.location = "/login.jsf";
}
</script>
</a4j:region>
More info can be found at the RichFaces documentation:
http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/ArchitectureOverview.html#SessionExpiredHandling
I had some problems when I making A4J requests after session expiration.
I put this
<context-param>
<param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
<param-value>true</param-value>
</context-param>
in my web.xml, for me it solves the problem.
Another solution is to create CustomViewHandler that extends ViewHandler
and override restoreView method
#Override
public UIViewRoot restoreView(FacesContext facesContext, String viewId) {
/**
* {#link javax.faces.application.ViewExpiredException}. This happens only when we try to logout from timed out pages.
*/
UIViewRoot root = null;
root = parent.restoreView(facesContext, viewId);
if(root == null) {
root = createView(facesContext, viewId);
}
return root;
}
Then you need to add it to your faces-config.xml
<view-handler>com.demo.CustomViewHandler</view-handler>
This will prevent you from getting ViewExpiredException's

Resources