Blank page after validation fails in JSF page - validation

I'm using Primefaces and trying to use bean validation but when validation fails instead of getting an appropriate message I just get a blank pages.
Heres the JSF code
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<ui:composition template="/WEB-INF/xhtml/templates/main.xhtml">
<ui:param name="header" value="small-header" />
<ui:define name="content">
<div style="margin-top: 60px;"></div>
<h1>Member Sign In</h1>
<h:form>
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />
<h:panelGrid columns="3">
<h:outputLabel value="Username : "/>
<p:inputText id="username" value="#{signInView.username}"/>
<p:message for="username" style="color:red" />
<h:outputLabel value="Password :"/>
<p:password id="password" value="#{signInView.password}"/>
<p:message for="password" style="color:red" />
</h:panelGrid>
<p:commandButton style="margin-top: 20px;"
value="Sign In"
action="#{signInView.signIn}"
validateClient="false"
ajax="false"/>
</h:form>
<h:outputText>By signing in you agree to abide by our terms and conditions.</h:outputText>
<div style="margin-top: 50px;"></div>
<h:outputText>Not currently a member ?
<p:link outcome="/content/join/join" value="sign up for free"></p:link>
</h:outputText>
<div style="margin-top: 150px;"></div>
</ui:define>
</ui:composition>
And here is the main template file
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<h:outputStylesheet library="css" name="style.css" />
<h:outputScript library="js" name="menu.js" />
<link href='http://fonts.googleapis.com/css?family=Roboto:300,300italic' rel='stylesheet' type='text/css'/>
<title>
<ui:insert name="title">TODO: Add title here</ui:insert>
</title>
</f:facet>
</h:head>
<h:body>
<ui:include src="/WEB-INF/xhtml/includes/main/title_banner.xhtml">
<ui:param name="header" value="#{header}" />
</ui:include>
<ui:include src="/WEB-INF/xhtml/includes/menu/main_menu.xhtml"/>
<div class='white-bg'>
<div id="content">
<ui:insert name="content">TODO: Add content here</ui:insert>
</div>
</div>
<ui:include src="/WEB-INF/xhtml/includes/main/footer.xhtml" />
</h:body>
And on the ManagedBean 'username' is annotated with '#Size(min=2,max=5)' just for testing. If I enter a username of length smaller than 2 or larger than 5 after hitting the Sign In button I get a blank page.
Any ideas why this is happening?
Thanks.

Since you just post partial xhtml code, I cannot suggest you why problem occurs.
However, I give an example to demonstrate how to use bean validation
login.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html" encoding="UTF-8">
<!-- ################################################################# -->
<!-- ## Header -->
<h:head>
<f:facet name="first">
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
</f:facet>
</h:head>
<h:body>
<h:form>
<p:messages id="messages"
showDetail="true"
autoUpdate="true"
closable="true" />
<h:panelGrid columns="3">
<h:outputLabel value="Username : "/>
<p:inputText id="username" value="#{signInView.username}"/>
<p:message for="username" style="color:red" />
<h:outputLabel value="Password :"/>
<p:password id="password" value="#{signInView.password}"/>
<p:message for="password" style="color:red" />
</h:panelGrid>
<p:commandButton style="margin-top: 20px;"
value="Sign In"
action="#{signInView.signIn}"
validateClient="false"
ajax="false"/>
</h:form>
</h:body>
</f:view>
</html>
menu.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html" encoding="UTF-8">
<!-- ################################################################# -->
<!-- ## Header -->
<h:head>
<f:facet name="first">
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
</f:facet>
</h:head>
<h:body>
Menu page
</h:body>
</f:view>
</html>
managedbean
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.validation.constraints.Size;
/**
*
* #author Wittakarn
*/
#SessionScoped
#ManagedBean(name = "signInView")
public class SignInView implements Serializable{
#Size(min=2,max=5)
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String signIn(){
System.out.println("username = " + username);
return "/menu.xhtml";
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<welcome-file-list>
<welcome-file>login.xhtml</welcome-file>
</welcome-file-list>
<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>*.jsf</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>

Related

JSF Handle Exception in Ajax events

I followed this solution and works perfectlly when a ViewExpiredException happen, but when i inspect (firefox utility) the view error redered, i see that its replacing it, but just inside the body tag of the normal view, i mean, the view which was the cause of the Exception. The view error had a css class declared in his own body tag, but i don't know, why doesn't replace the whole view error, instead just take all the content (after his body tag) of the view error and inserted inside the body tag of the normal view?
To get this behavior, i have a login view (normal view that i refer above) and just have to wait until session expire, then i try to login (submit the form of the view) and this trigger a ExceptionHandler to render de view error.
Here are some snippet:
login.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
</f:facet>
<title>PrimeFaces</title>
</h:head>
<h:body styleClass="login-body">
<div class="login-panel ui-fluid">
<div class="ui-g">
<div class="ui-g-12 logo-container">
<p:graphicImage name="images/logo-colored.png" library="theme-layout" />
<h1>Login to Your Account</h1>
<h2>WELCOME</h2>
</div>
<div class="ui-g-12">
<p:inputText placeholder="User" />
</div>
<div class="ui-g-12">
<p:password placeholder="Password" feedback="false"/>
</div>
<div class="ui-g-12 chkbox-container">
<p:selectBooleanCheckbox id="remember-me" />
<p:outputLabel for="remember-me" value="Remember Me"/>
</div>
<div class="ui-g-12 button-container">
<p:commandButton type="submit" value="Log in" icon="fa fa-user" styleClass="orange-btn" action="#{menu.login}" update="frmLoginPromo">
</div>
</div>
</div>
<h:outputStylesheet name="css/layout-#{guestPreferences.layout}.css" library="theme-layout" />
</h:body>
</html>
error.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
</f:facet>
<title>PrimeFaces - Error </title>
</h:head>
<h:body styleClass="exception-body">
<div class="exception-panel">
<p:graphicImage name="images/icon-error.png" library="theme-layout" />
<h1>Error Occured</h1>
<p>An error occured, please try again later.</p>
</div>
<h:outputStylesheet name="css/layout-blue.css" library="theme-layout" />
</h:body>
</html>
CustomExceptionHandler.java
#Override
public void handle() throws FacesException{
final Iterator<ExceptionQueuedEvent> lclExceptionQueue = getUnhandledExceptionQueuedEvents().iterator();
final FacesContext lclFacesContext = FacesContext.getCurrentInstance();
final Map<String, Object> requestMap = lclFacesContext.getExternalContext().getSessionMap();
while (lclExceptionQueue.hasNext()){
ExceptionQueuedEvent event = lclExceptionQueue.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
Throwable lclThrowable = context.getException();
try{
if (lclThrowable instanceof ViewExpiredException){
lclFacesContext.setViewRoot(lclFacesContext.getApplication().getViewHandler().createView(lclFacesContext, "/error.xhtml"));
lclFacesContext.getPartialViewContext().setRenderAll(true);
lclFacesContext.renderResponse();
}
}finally{
lclExceptionQueue.remove();
}
}
getWrapped().handle();
}
Here is how looks like, after error view is rendered
Inspecte view error
Please, tell me what am doing wrong?
Since you are already using PrimeFaces, I'd opt for not developing your own exceptionhandlers. PrimeFaces already has one that can handle both ajax and non-ajax requests.
For the people not using PrimeFaces, I'd suggest to use the OmniFaces exceptionhandling
For PrimeFaces 6.2 the documentation contains the information to configure this in chapter 11.3 (it is the same chapter btw for PF 6.1)
In summary (ALL quotes are from the PF documentation)
Configure an el resolver and the exceptionhandler
<application>
<el-resolver>
org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver
</el-resolver>
</application>
<factory>
<exception-handler-factory>
org.primefaces.application.exceptionhandler.PrimeExceptionHandlerFactory
</exception-handler-factory>
</factory>
Configure errorpages if you want to in web.xml
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/ui/error/error.jsf</location>
</error-page>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/ui/error/viewExpired.jsf</location>
</error-page>
You can then use information about the exceptions in EL in the error pages
<h:outputText value="Message:#{pfExceptionHandler.message}" />
<h:outputText value="#{pfExceptionHandler.formattedStackTrace}" escape="false" />
There is more info, for which I'd suggest to consult the documentation.
And for ajax exceptions you can do
<p:ajaxExceptionHandler type="javax.faces.application.ViewExpiredException"
update="exceptionDialog" onexception="PF('exceptionDialog').show();" />
<p:dialog id="exceptionDialog" header="Exception: #{pfExceptionHandler.type}
occured!" widgetVar="exceptionDialog" height="500px">
Message: #{pfExceptionHandler.message} <br/>
StackTrace: <h:outputText value="#{pfExceptionHandler.formattedStackTrace}" escape="false" />
<p:button onclick="document.location.href = document.location.href;"
value="Reload!"/>
</p:dialog>
The configuration for OmniFaces is fairly similar.
See also:
Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request

selecting primefaces datatable not working

I have a problem with selection primefaces datatable. When I choose any record my setter doesn't invoke. I found couple solution like change template or change to ViewSCope I'm changing everything but still does't work
template.xhtml
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsf/composite/custom"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title><ui:insert name="title">Default title</ui:insert></title>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Social Test</title>
</f:facet>
<f:facet name="middle">
<h:outputStylesheet name="bootstrap/css/bootstrap.css" />
<h:outputStylesheet name="css/style.css" />
<h:outputStylesheet name="bootstrap/css/bootstrap-social.css" />
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" />
<h:outputScript name="bootstrap/js/bootstrap.js" />
<!-- h:outputScript name="js/script.js" /-->
</f:facet>
<f:facet name="last">
</f:facet>
</h:head>
<h:body>
<div id="header"></div>
<div id="menu"></div>
<div id="content">
<ui:insert name="content"></ui:insert>
</div>
<div id="footer"></div>
</h:body>
</html>
ticketEdit.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition template="/template/template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsf/composite/custom"
xmlns:p="http://primefaces.org/ui">
<ui:define name="content">
<h2 class="form-signin-heading">#{labRes.add_ticket}</h2>
<h:form id="form">
<p:accordionPanel>
<p:tab title="#{labRes.train_details}">
<h:panelGrid columns="2" cellpadding="10">
<c:autoComplete
completeMethod="#{ticketBean.trainAutoCompleteBean.complete}"
minQueryLength="2"
converter="#{ticketBean.trainAutoCompleteBean.converter}"
nameLable="#{labRes.train_number}"
autoValue="#{ticketBean.selectedTrain}" forceSelection="true"
queryDelay="500" effect="fade" cid="ticketAuto" listener="null"
labelStyleClass="labelPaddingParameter" ajax="true"
update="#form" />
<c:inputText id="nr" cid="cnr"
nameLable="#{labRes.train_number}" disabled="true"
inputValue="#{ticketBean.selectedTrain.name}"
labelStyleClass="labelPaddingParameter" />
</h:panelGrid>
</p:tab>
<p:tab title="#{labRes.train_details}">
<h:panelGrid columns="1" cellpadding="10" id="pgTrainDetails">
<c:calendar pattern="MM-dd-yyyy" value="#{ticketBean.day}"
isListener="true" update=":form" ajax="true"
nameLable="#{labRes.departure_date}" cid="depDat"
listener="#{ticketBean.onDateSelect}" />
<p:dataTable var="schedule" value="#{ticketBean.tripSchedules}"
selectionMode="single"
selection="#{ticketBean.selectedSchedule}"
rowKey="#{schedule.id}" styleClass="pickListWidth"
paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5" id="scheduleTable">
<f:facet name="header">
<c:calendar pattern="MM-dd-yyyy" value="#{ticketBean.day}"
isListener="true" update=":form" ajax="true"
nameLable="#{labRes.departure_date}" cid="depDat"
listener="#{ticketBean.onDateSelect}" />
</f:facet>
<p:column headerText="#{menRes.id}" sortBy="#{schedule.id}"
style=" text-align:center">
<h:outputText value="#{schedule.id}" />
</p:column>
<p:column headerText="#{labRes.departure_time}"
sortBy="#{schedule.departure}" style="text-align:center">
<h:outputText value="#{schedule.departure}" />
</p:column>
</p:dataTable>
</h:panelGrid>
</p:tab>
<p:tab title="#{labRes.ticket_details}">
<h:panelGrid columns="2" cellpadding="10">
</h:panelGrid>
</p:tab>
</p:accordionPanel>
</h:form>
</ui:define>
My bean (I'm using Spring) but I have to use #ViewScope because spring does't contain #Scope('view')
// the same annotations in AbstractBean
#Component
#ViewScope //faces bean package
public class TicketBean extends AbstractBean {
... code ...
public TripSchedule getSelectedSchedule() {
return selectedSchedule;
}
public void setSelectedSchedule(TripSchedule selectedSchedule) {
this.selectedSchedule = selectedSchedule;
}
Thanks for help !
I think you need to add some ajax to the datatable:
<p:ajax event="rowSelect"/>
<p:ajax event="rowUnselect"/>

Update datatable after fileupload using PrimeFaces

Below is my code for my file upload page and I can't figure out why when the upload is done it doesn't update my datatable with if the upload was successful or not. I could do a like a do not render til after update but don't think that is supported with the fileupload command. I did a system out on my list and it does have the values in it so the list is fully populated and ready to display but my datatable isn't showing anything? Am I missing something?
Tomcat 7.0
JSF 2.2.1
Chrome/IE/Firefox
PrimeFaces 5.0
<?xml version="1.0" encoding="UTF-8"?>
<!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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
template="templates/template.xhtml">
<ui:define name="title">Ingest</ui:define>
<ui:define name="metadata">
</ui:define>
<ui:define name="content">
<h:form>
<p:fileUpload fileUploadListener="#{ingestBean.ingestListener}"
label="choose" invalidFileMessage="Invalid file: "
allowTypes="/(\.|\/)(xml)$/" multiple="true" update="#form">
</p:fileUpload>
<p:dataTable var="errors" value="#{ingestBean.errorList}" id="errorTable">
<p:column headerText="File Name">
<h:outputText value="#{errors.fileName}" />
</p:column>
<p:column headerText="Status">
<h:form>
<h:commandLink action="#{ingestBean.getErrorInfo}"
value="errors.status">
<f:param name="id" value="#{errors.id}" />
</h:commandLink>
</h:form>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
</html>
Edit: After a bunch of testing and code rewriting I have got it partially working but it seems like it doesn't like to render in my template code... So I was wondering if there may be something wrong in my template code.
Template code:
<!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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html" id="fview">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><ui:insert name="title">Page template with PrimeFaces</ui:insert></title>
<ui:debug />
<f:metadata>
<ui:insert name="metadata" />
</f:metadata>
<h:head>
<style>
#leftPanel {
z-index: 1 !important;
}
#leftPanel div {
overflow: visible;
}
</style>
</h:head>
<h:body onload="statusDialog.hide();">
<h:outputStylesheet library="css" name="style.css" />
<p:ajaxStatus onstart="statusDialog.show();"
onsuccess="statusDialog.hide();" />
<p:layout fullPage="true" resizeTitle="resize"
style="background-color:#FFFFFF;">
<p:layoutUnit position="north" size="68" id="north">
<ui:include src="header.xhtml" />
</p:layoutUnit>
<p:layoutUnit position="west" size="202" header="Menu" id="leftPanel">
<ui:include src="menu.xhtml" />
</p:layoutUnit>
<p:layoutUnit styleClass="layoutUnitCenter" position="center">
<h:form id="mainForm">
<ui:insert name="content" />
</h:form>
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
After a bunch of testing and deleting and rewriting like all my code I have figured out it was a stupid error with layouts and the <f:view> so I removed that and
<p:ajaxStatus onstart="statusDialog.show();"
onsuccess="statusDialog.hide();" />
And everything seemed to work fine!

JSF 2.1 preRenderEvent not working on GET request

I can't get the preRenderView event listener to work on a GET request in JSF 2.1.
I have found a lot about it but nothing seems to work e.g.:
Conditional redirection in JSF
http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/#get-prerenderview-event
http://developer.am/j2eetutorial/jsf/?page=jsf-2-prerenderviewevent-example
JSF, Spring, and the PreRenderViewEvent
http://balusc.blogspot.dk/2011/09/communication-in-jsf-20.html#ProcessingGETRequestParameters
I have a template with 4 insert blocks and I have tried to insert the event code at all those places but without any luck. I have tried both with and without the f:metadata tag surrounding it.
<f:event type="preRenderView" listener="#{applicationData.redirectIfNoResults}" />
Bean:
#ManagedBean
#ApplicationScoped
public class ApplicationData implements Serializable {
public void redirectIfNoResults() throws IOException {
if (getTotal() < 1) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/noResults.xhtml");
}
}
...
}
Template:
<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<ui:insert name="beforeHeader" />
<f:view>
<ui:insert name="inView" />
</f:view>
<h:head>
<meta http-equiv="cache-control" content="no-store" />
<link href="style.css" rel="stylesheet" type="text/css" />
<title>Quick Poll</title>
<ui:insert name="header" />
</h:head>
<h:body>
<h1>Quick Poll</h1>
<ui:insert name="content" />
</h:body>
</html>
View:
<ui:define name="content">
#{applicationData.question}?<p/>
<h:panelGrid columns="3" border="0">
Yes:
<h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.yes/applicationData.total}"/>
#{applicationData.yes}
<h:outputText value="No:"/>
<h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.no/applicationData.total}"/>
#{applicationData.no}
</h:panelGrid>
</ui:define>
</ui:composition>
Please help me figure out how to get it working..
Update 1:
I have made changes as suggested by BalusC but it is still not working..
Template:
<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="cache-control" content="no-store" />
<link href="style.css" rel="stylesheet" type="text/css" />
<title>Quick Poll</title>
<ui:insert name="header" />
</h:head>
<h:body>
<h1>Quick Poll</h1>
<ui:insert name="content" />
</h:body>
</html>
View:
<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
template="template.xhtml">
<ui:define name="content">
<f:event listener="#{applicationData.redirectIfNoResults}" type="preRenderView"></f:event>
#{applicationData.question}?<p/>
<h:panelGrid columns="3" border="0">
Yes:
<h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.yes/applicationData.total}"/>
#{applicationData.yes}
<h:outputText value="No:"/>
<h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.no/applicationData.total}"/>
#{applicationData.no}
</h:panelGrid>
</ui:define>
</ui:composition>
That <f:view> isn't rightly used, it has to wrap the entire view. Remove it (JSF will implicitly create one), or at least let it wrap the entire view, including <h:head> and <h:body> tags.
By the way, the <f:event> does not need to go in a <f:metadata>. That applies only to <f:viewParam>. A <f:event> listener which depends on results of <f:viewParam> is indeed often for sole self-documentary purposes also placed in the same <f:metadata> block, but that is thus not a requirement of <f:event> itself.
In your case, it'd be easier to just put it in <ui:define name="content">.
ComponentSystemEvent seems to be missing in the method signature.
Method needs to look like this:
public void newRequest(final ComponentSystemEvent event) {
System.out.println("Someone requested me");
}
And then place a caller in the template or in the seperate views, that won't do any difference.
<f:event listener="#{userSessionAction.newRequest}" type="preRenderView"></f:event>
I ended up making a solution with a PostConstruct method in a view scope bean.
Like this: Initializng a Backing Bean With Parameters on Page Load with JSF 2.0
Bean:
#ManagedBean
#ViewScoped
public class ResultsController {
#ManagedProperty(value="#{applicationData.total}")
private int total;
#ManagedProperty(value="#{applicationData.yes}")
private int yes;
#ManagedProperty(value="#{applicationData.no}")
private int no;
#PostConstruct
public void postConstruct() {
if (getTotal() < 1) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
try {
ec.redirect(ec.getRequestContextPath() + "/noResults.jsf");
} catch (IOException e) {
System.out.println("noResults.jsf redirect failed.");
e.printStackTrace();
}
}
}
...
}
View:
<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
template="template.xhtml">
<ui:define name="content">
#{applicationData.question}?<p/>
<h:panelGrid columns="3" border="0">
Yes:
<h:panelGrid bgcolor="black" height="20" width="#{300*resultsController.yes/resultsController.total}"/>
#{resultsController.yes}
<h:outputText value="No:"/>
<h:panelGrid bgcolor="black" height="20" width="#{300*resultsController.no/resultsController.total}"/>
#{resultsController.no}
</h:panelGrid>
</ui:define>
</ui:composition>

ViewExpiredException, Page could not be restored

I've tried to follow different posts on how to handle the ViewExpiredException in Mojarra 2.1.0 (with RichFaces 4) on GlassFish 3.1. But what I define in web.xml doesn't seams to have any effect. I use form base security and the user has to logon to access the content. I just want Glassfish (catalina) to redirect the user to a simple JSF page when the session times-out, with a link back to the login page.
I always get the the following error message;
javax.faces.application.ViewExpiredException: viewId:/app_user/activity/List.xhtml - View /app_user/activity/List.xhtml could not be restored.
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:202)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:113)
Who can I redirect the user when the user session has timed-out and trap the exception in the server log ?
Greetings, Chris.
layout.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"
xmlns:rich="http://richfaces.org/rich">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- Had no effect
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
-->
<h:outputStylesheet name="css/default.css"/>
<h:outputStylesheet name="css/cssLayout.css"/>
<title>
<h:outputText value="Partner Tapestry - " /> <ui:insert name="title">Browser Title</ui:insert>
</title>
</h:head>
<h:body>
<div id="top" >
<ui:insert name="top">Top Default</ui:insert>
</div>
<div id="messages">
<rich:messages id="messagePanel"/>
</div>
<div id="content">
<ui:insert name="content">Content Default</ui:insert>
</div>
</h:body>
</html>
web.xml
...
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
2
</session-timeout>
</session-config>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/faces/resources/sessionExpired.xhtml</location>
</error-page>
...
login.xhtml
<ui:composition template="/resources/masterLayout.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j">
<ui:define name="title">
<h:outputText value="Login"></h:outputText>
</ui:define>
<ui:define name="top">
<h:outputText value="Welcome" />
</ui:define>
<ui:define name="content">
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="username" value="Username" />
<h:inputText id="username" value="#{userController.userAuthentication}" />
<br />
<h:outputLabel for="password" value="Password" />
<h:inputSecret id="password" value="#{userController.passwordAuthentication}" />
<br />
<h:outputText value=" " />
<a4j:commandButton action="#{userController.login()}" value="Login"/>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
finally sessionExpire.xhtml
<ui:composition template="/resources/masterLayout.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j">
<ui:define name="title">
<h:outputText value="Session Exired"></h:outputText>
</ui:define>
<ui:define name="top">
<h:outputText value="Session expired, please login again" />
</ui:define>
<ui:define name="content">
<h:form>
<a4j:commandLink action="/resources/login?faces-redirect=true" value="Login" />
</h:form>
</ui:define>
</ui:composition>
Your approach should work perfectly fine for synchronous POST requests. However, you're using asynchronous (ajax) POST requests. Exceptions on ajax requests needs to be handled by either the jsf.ajax.addOnError init function in JavaScript or a custom ExceptionHandler.
See also
javax.faces.application.ViewExpiredException and error page not working
JSF: Cannot catch ViewExpiredException
Solved the problem by following this link on implementing a ExceptionHandlerFactory. A nice solution where you can have an exception navigation rule, but maybe a bit long. Thanks for the help #BalusC.

Resources