JSF preRenderView not triggered when navigating to page without using Redirect - jsf

I have created a preRender method to be called when the user navigate to that specific page, I use:
<f:metadata>
<f:event listener="#{targetClass.prerender()}"
type="preRenderView">
</f:event>
</f:metadata>
but the problem is that this method is not being called when I navigate to this page, unless I use
<redirect />
in the faces-config.xml file.
But, I don't want to use redirect, so the url always point to the login page.
Thank you.

Related

GlassFish is creating a new JSESSIONID on every request

I have a simple page backed by a named bean. The page is also using primefaces, but I am not doing anything ajax in that page. The applications is hosted on Glassfish 5.1.
#Named("cardsView")
#RequestScoped
public class CardsViewBean implements Serializable {
...
}
This is the xhtml page. As you can see I am passing the bean to the master xhtml, not sure if it's the best practice or the source of the problem.
<ui:composition template="/fragment/master.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:ipc="http://java.sun.com/jsf/composite/component">
<ui:param name="bean" value="${cardView}" />
<ui:define name="content">
.....
</ui:define>
</ui:composition>
It is my understanding that the request scoped bean lives just for the request.
However when I look to the browser inspector I can see that each time I hit the page a new JSESSIONID is created. So I think that there is clearly something I have wrongly configured but I am not sure where to look.
In fact, there is 2 request per page.
Initial request and postback request.
first, client makes a request to get the page. it is complete request by itself.
request: http://example.com/index
response: html page.
After user hits submit button or another button or link, browser requests another page again.
request: http://example.com/login
response: another page.
In another word, Jsf or any Ui framework holds information between 2 requests for us by various techniques and methods
see this question about Initial request and postback request
and Jsf lifecycle
and primeFaces lifeCycle show case
last Point: session has timeout in jservlet and you can config it using web.xml and If this time pass, your session expires and gives you another session
Happy Coding!

simple jsf commandbutton work on every single page except home page

A Java EE 8/SE 8 web application in deployement runnnig on Glassfish 5 build 25 both production and development, uses jsf 2.3. users create accounts and login. there is a 'logout' button for loging out.
Problem: 'logout' button works as expected everywhere on the website. EXCEPT home page (example.com) & (example.com/home.xhtml). the problem does not exists on my local computer. only in production (example.com).
So I have a template called : index.xhtml . all pages use it, including home.xhtml:
<ui:composition template="index.xhtml">
<ui:define name="top-bar">
<c:if test="#{request.remoteUser ne null}">
<h:form ><h:commandButton value="Log out" action="#{registerAdvanced.logout}"/></h:form>
</c:if>
</ui:define>
and
#Named
#RequestScoped
public class RegisterAdvanced extends BaseBacking implements Serializable {
public String logout() {
try {
getRequest().logout();
getContext().getExternalContext().getSessionMap().remove("user");
return REDIRECT_PAGE;
} catch (ServletException ex) {
return REDIRECT_PAGE;
}
}
}
Users login & logout fairly easily until I noticied that clicking on logout on the home page (home.xhtml) prints a null pointer exception AND redirect to 404 error page.
[[/home.xhtml #450,77 value="#{passesTestBean.displayPassSummaryList}": java.lang.NullPointerException
javax.el.ELException: /home.xhtml #450,77 value="#{passesTestBean.displayPassSummaryList}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:119)
at com.sun.faces.facelets.component.UIRepeat.getValue(UIRepeat.java:314)
at com.sun.faces.facelets.component.UIRepeat.getDataModel(UIRepeat.java:256)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:507)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:557)
at com.sun.faces.facelets.component.UIRepeat.processDecodes(UIRepeat.java:861)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1258)....
part of jsf where there is a call to value="#{passesTestBean.displayPassSummaryList}" is 100% seperate to logout and PassesTestBean CDI is request scope.
so the problem is SOMEHOW when I click on logout button. PassesTestBean is called for no reason and not since jsf must Initialize (since Request Scoped). it ends up returning null.
Now remember this only happens in: production at example.com AND only home page of all pages.
I'm thinking of writing a page only for loging out: has a log out button only.
Check for null pointer exception
getRequest().logout(); //here
getContext().getExternalContext().getSessionMap().remove("user");//here

Omnifaces ViewScoped generates a POST call

My app is using Tomee 7.0.5, Java 8, MySql, JSF 2.2, Omnifaces 2.7. Primefaces 6.1, Prettyfaces 3.3.3. I tried to use Omnifaces' ViewScoped annotation together with #Named in my backing bean. It is required to use OWASP to validate requests. For some unknown reason a click on a link is converted to a POST request and since this link is used to navigate to another page there is no token yet in the request and so the validate request fails. Now, if I use javax.faces.view.ViewScoped instead everything is fine. I have 12 applications with the same pattern.
Each app has a template with a p:toolbar and links to navigate like:
<h:link outcome="pretty:search" value="Search"
onclick="showSpinningIcon();return true;" />
No errors in Chrome console. what am I missing here?

Create a link to a JSF page in a subfolder

I have a Java web app with the following structure:
- Project
- Web Pages
+ WEB-INF
+ resources
- administration
systemsettings.xhtml
userhandling.xhtml
login.xhtml
index.xhtml
menubar.xhtml
...
+ Source Packages ...
I recently added the administration folder to the Web Pages, and I moved there the two .xhtml pages so I can write more specific URL pattern for my administrator authorization filter.
However, I don't know what is the path for the pages in the administration folder. While <a href='index.xhtml'> works, <a href='administration/systemsettings.xhtml'> doesn't, throws java.io.FileNotFoundException.
Update:
The content of the systemsettings.xhtml was:
<h:body>
<ui:insert name="header" >
<ui:include src="menubar.xhtml" />
</ui:insert>
<div>Administration - System settings</div>
</h:body>
I forgot to update the path to the included page, after the refactor. This can be fixed, as #BalusC suggested, by changing the <ui:include src="menubar.xhtml" /> to <ui:include src="/menubar.xhtml" />.
If a link does not start with a scheme like http://, then it's a relative link which is relative to the current request URI as you see in browser's address bar. If a relative link starts with /, then it's relative to the domain root in request URI. If a relative link does not start with / then it's relative to the currently opened folder in request URI.
If you can't tell about the currently opened folder for sure, then you need to make it a domain-relative link by explicitly prepending the context path as available by #{request.contextPath}.
settings
An alternative is to just use JSF <h:link> component. It will automatically prepend the context path (and also automatically apply the JSF mapping!). The following <h:link> examples generate equivalent HTML.
<h:link value="settings" outcome="/administration/systemsettings.xhtml" />
<h:link value="settings" outcome="/administration/systemsettings" />

jsf navigation question

I have a JSF2 project with a "view user" page that reads the currently selected user from a session bean; userHandler.selectedUser.
The page is intended to be visited by navigating with links in the app.
However, if the user attempts to hit the "view user" page directly by this URL ...
http://localhost:8080/webapp/userView.jsf
... they see the page with no data on it (because there's no selected user in the userHandler).
I think what I'd like to do is redirect the user to the main page of the app if they try to hit it directly like that. What is a simple and elegant way of handling this problem?
Thanks,
Rob
You'd like to hook on the preRenderView event and then send a redirect when this is the case.
<f:metadata>
<f:event type="preRenderView" listener="#{bean.preRenderView}" />
</f:metadata>
with
public void preRenderView() throws IOException {
if (userHandler.getSelectedUser() == null) {
FacesContext.getCurrentInstance().getExternalContext().redirect("home.jsf");
}
}
A way to avoid this problem from the start is to have pages that you don't want to be accessed directly via URL into the WEB-INF folder of your project.
This way, your pages aren't accessible directly via URL.

Resources