JSF Handle Exception in Ajax events - ajax

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

Related

Blank page after validation fails in JSF page

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>

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!

Trouble to display deployJava button on ajax rerender

I'm having trouble displaying the deploy-java button on ajax rerender
<h:form id="deployJavaForm" rendered="#{myBean.shouldRender}">
<h:outputScript library="js" name="http://java.com/js/deployJava.js" target="head" />
<script type="text/javascript">
deployJava.createWebStartLaunchButton('blah.jnlp', '1.7.0');
</script>
</h:form>
when
myBean.shouldRender == true
and the form is updated the only thing being displayed (on a white page) is the deployJava-button and the request is left hanging. if shouldRender is true on the initial request, page and button is displayed correctly.
Im using primefaces in case it can help.
What I want to do is to have the button to be displayed correctly regardless if its part of a ajax rerender or a complete initial request.
Update:
I did my homework and created a minimal example that still reproduces the problem. It seems I still get the same problems regardless if script declaration is in head or in body (I have copy of deployJava.js in resources/js)
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<!-- <script type="text/javascript" src="http://java.com/js/deployJava.js" />-->
</h:head>
<h:body>
<h:outputScript library="js" name="deployJava.js" target="head" />
<h:form id="djForm">
<script type="text/javascript">
deployJava.createWebStartLaunchButton(
'test.jnlp', '1.7.0');
</script>
<p:commandButton value="update" update="djForm" />
</h:form>
</h:body>
</html>
edit: (specialgems)
below test give same problem as observed earlier.
<h:outputScript>
deployJava.createWebStartLaunchButton(
'test.jnlp', '1.7.0');
</h:outputScript>
edit: added picture
after click of update button, only deployJava button is rendered and page is loading
edit (daniel): both on success and oncomplete give same behaviour :(
<h:form id="djForm">
<h:outputScript>
function abcefg() {
deployJava.createWebStartLaunchButton('test.jnlp', '1.7.0');
}
</h:outputScript>
<p:commandButton value="update" update="djForm" onsuccess="abcefg()" />
</h:form>
Alternatively to using js and css visibility described in my comment you can write own composite button component. Using Firebug you can investigate which markup is generated by the deployJava.createWebStartLaunchButton script and add it by yourself statically. So your component could be:
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite">
<head>
<title>deployJava Button component</title>
</head>
<body>
<composite:interface>
<composite:attribute name="version" required="true"
type="java.lang.String" />
<composite:attribute name="url" required="true"
type="java.lang.String" />
</composite:interface>
<composite:implementation>
<a onmouseover="window.status=''; return true;"
href="javascript:if (!deployJava.isWebStartInstalled("#{cc.attrs.version}")) {if (deployJava.installLatestJRE()) {if (deployJava.launch("#{cc.attrs.url}")) {}}} else {if (deployJava.launch("#{cc.attrs.url}")) {}}"><img
border="0" src="//java.com/js/webstart.png" /></a>
</composite:implementation>
</body>
</html>
so your page will be:
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:comps="http://java.sun.com/jsf/composite/comps"
xmlns:p="http://primefaces.org/ui">
<h:head>
<!-- <script type="text/javascript" src="http://java.com/js/deployJava.js" />-->
</h:head>
<h:body>
<h:outputScript library="js" name="deployJava.js" target="head" />
<h:form id="djForm">
<comps:deployJavaButton version="1.7.0" url="test.jnlp" rendered="#{myBean.shouldRender}" />
<p:commandButton value="update" update="djForm" />
</h:form>
</h:body>
</html>
The main idea is to avoid executing button creation script twice and more.
May be using h:panelGroup instead of h:form will help. Something like that:
<h:form id="djForm">
<h:panelGroup rendered="#{myBean.shouldRender}">
<script type="text/javascript">
deployJava.createWebStartLaunchButton(
'test.jnlp', '1.7.0');
</script>
</h:panelGroup>
<p:commandButton value="update" update="djForm" />
</h:form>

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