How many state information is saved when client mode - jsf

How to define the max number of component trees in client mode? How to prevent calling #PostConstruct method?
I'm developing an application by JavaEE7 with glassfish 4.1.
If I remember correctly, when javax.faces.STATE_SAVING_METHOD is client, there is no limit of component tree.
But when I opened more than 25 tabs in Chrome and operate the first tab, that tab's managed bean will construct and call #PostConstruct method.
I think this behavior seems losing component tree to me.
The following is source code of my application.
test.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="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:panelGrid columns="5" cellpadding="5" >
<p:commandButton id="returnButton" value="return"
action="#{testEditBean.return()}"
immediate="true"
/>
</h:panelGrid>
</ui:composition>
testBean.java
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named(value = "testBean")
#ViewScoped
public class TestBean implements Serializable {
#PostConstruct
public void index() {
}
public String doReturn() {
String ret = "/content/tmp/testSearch.xhtml";
return ret;
}
}
[postscript 2016/01/28]
I understand that a HTTP session stored view scoped beans (max 25) and view state only stored component tree.
This is my new question.
Unless we change mojjara 2.x to another JSF implementation, we couldn't open more than 25tabs?
"more than 25 tabs" contains this case that "an user open 2 tabs, and 23 transition occur in 2nd tab."

Related

c:if and c:choose fail to conditionally build ui:composition [duplicate]

This question already has answers here:
understand the purpose of jsf ui:composition
(1 answer)
How to include another XHTML in XHTML using JSF 2.0 Facelets?
(2 answers)
Closed 5 years ago.
Been struggling with this for a bit now.
I have an Apache Shiro login.xhtml page that loads at startup.
Once authenticated, the user is redirected to an index.xhtml page in the same folder as the Apache Shiro login.xhtml page (both are in the webapp folder).
I want to prevent non authenticated users from loading the UI by using this in my index.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://xmlns.jcp.org/jsf/core"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:jsf="http://xmlns.jcp.org/jsf"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
<c:if test="${authUserDetail.userAuthenticated}">
<ui:composition template="/WEB-INF/templates/masterTemplate.xhtml">
<ui:define name="title">Title Page</ui:define>
<ui:define name="content">
<ui:include src="/WEB-INF/home/home_page.xhtml"/>
</ui:define>
</ui:composition>
</c:if>
<c:if test="${!authUserDetail.userAuthenticated}">
<h:outputLabel
value="You are not authorized to access this page."/>
</c:if>
</html>
With a backing bean AuthUserDetail.java looking like this:
package com.mycomp.view.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.omnifaces.cdi.ViewScoped;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import java.io.Serializable;
#Named
#ViewScoped
public class AuthUserDetail implements Serializable {
private boolean userAuthenticated = false;
public AuthUserDetail() {
Subject currentUser = SecurityUtils.getSubject();
this.userAuthenticated = currentUser.isAuthenticated();
}
public boolean isUserAuthenticated() {
return userAuthenticated;
}
public void setUserAuthenticated(boolean userAuthenticated) {
this.userAuthenticated = userAuthenticated;
}
}
If I test without by replacing the <ui:composition... code (only using a single <h:outputLabel> it seems to work. But using it as is, always renders the complete page even if the user is not logged in (using Google Chrome's incognito feature).
What am I missing???

ViewExpiredException redirect not working with JSTL tag forEach in view

Environment:
I have an EAR application with WildFly 10.0.0.Final. It has one module for the web application which is based on JSF Mojarra 2.2.12-jbossorg-2 20150729-1131 (using PrimeFaces 6 for the UI and Omnifaces 2.5.1 for additional utilities).
Use Case:
My Problem is around view expiration. I simplified my app to a small bean/view showcase which contains the problem. The use case is pretty simple: if the view is expired and the user triggers some action, he should be redirected to the view expired page. I am using the Omnifaces FullAjaxExceptionHandler for this.
Problem:
The redirect on view expiration is working in nearly all cases. But it is not working anymore as soon as I use the JSTL tag <c:forEach/> in my view. Then, the HTTP Request simply has a Status (failed) in my Chrome Dev Tools and nothing happens.
The following Bean/View combination shows the problem:
View: text.xhtml
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head id="head">
<title>Test</title>
</h:head>
<h:body>
<h:form>
<p:commandButton action="#{TestBean.throwError()}" value="Throw" update=":test"/>
</h:form>
<h:panelGroup id="test">
Test
</h:panelGroup>
<c:forEach items="#{TestBean.list}" var="item">
#{item.toString()}
</c:forEach>
<p>
<input type="button" value="Invalidate session"
onclick="$.get('#{request.contextPath}/invalidatesession?#{now.time}', alert('Session invalidated!'))"/>
</p>
</h:body>
</html>
Bean: Test.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
#ViewScoped
#Named(value = "TestBean")
public class Test implements Serializable
{
private static final long serialVersionUID = -6513676596620667863L;
private List<String> list = new ArrayList<>();
#PostConstruct
public void init()
{
this.list.add("aaaaa");
this.list.add("bbbbb");
this.list.add("ccccc");
}
public void throwError()
{
throw new IllegalArgumentException("bla");
}
public List<String> getList()
{
return this.list;
}
}
It's pretty much the FullAjaxExceptionHandler Show Case of Omnifaces with the JSTL tag <c:forEach/>. As soon as I remove it from my View, everyhting works fine.

Unable to resolve "Managed Bean" issue while working with Java Serves Faces 2.2 [duplicate]

This question already has an answer here:
Eclipse won't autocomplete bean methods in EL when I use javax.annotation.ManagedBean
(1 answer)
Closed 6 years ago.
Template Client.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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<body>
<f:view contracts="#{themeSelector.themeName}">
<ui:composition template="/template.xhtml">
<ui:define name="top">
<h:form>
<h:outputLabel value="Theme" for="menu"></h:outputLabel>
<h:selectOneMenu id="menu" label="ThemeMenu" value="#{themeSelector.themeName}">
<f:selectItem itemLabel="Dark" itemValue="dark"></f:selectItem>
<f:selectItem itemLabel="Normal" itemValue="normal"></f:selectItem>
</h:selectOneMenu>
<h:message for="menu"></h:message>
<h:commandButton id="Submit" value="Submit" action="templateClient"></h:commandButton>
</h:form>
</ui:define>
</ui:composition>
</f:view>
</body>
</html>
ThemeSelector.java
package com.rshingha.example;
import javax.annotation.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
/**
*
* #author rshingha
*/
#ManagedBean
#RequestScoped
public class ThemeSelector {
private String themeName="dark";
public ThemeSelector()
{
}
public String getThemeName() {
return themeName;
}
public void setThemeName(String themeName) {
this.themeName = themeName;
}
}
Issue:
Following line in TemplateClient.xhtml
<f:view contracts="#{themeSelector.themeName}">
Here value of "contracts" attribute is not getting resolved, even when I am doing "Ctrl+click" on property name "themeName", its not going to that property in bean file
Interesting thing is when I am hardcoding value for "contracts" attribute then its working.
I also tried with #Named annotation , but same is happening in that case with one exception:
When I am doing "Ctrl+click" on property name "themeName", its navigating to that property in bean file
Please suggest anything , I am stuck
You got wrong import for #ManagedBean. Use this one javax.faces.bean.ManagedBean from JSF. If you want to use #Named (which is CDI technology) then you should also change imports for scopes, request scope would be javax.enterprise.context.RequestScoped.

Refreshing a JSF/PrimeFaces interface from the backing Bean

My goal is to display a text on a web page, with JSF and/or PrimeFaces. The text is updated in real time by a process on the server side.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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">
<h:body>
<f:view id="view">
<f:event type="preRenderView" listener="#{MyBean.init}"/>
<h:form>
<p:outputLabel id="output" value="#{MyBean.text}"/>
</h:form>
</f:view>
</h:body>
</html>
My backing bean maps the text to p:outputLabel. I also added to the bean a method foo() that modifies the text. This method is called by another process running in the background (it holds a pointer to the bean).
#ManagedBean(name="MyBean")
#SessionScoped
public class MyBean {
private String text = "text";
public void init() {
MyOtherClass.getPointer(this);
}
public String getText() {
return text;
}
public String foo(String s) {
text = text + s;
// ...and refresh ?
}
}
What I cannot do so far, is to update/refresh the view automatically each time the text is updated. The best I could do is to let the user manually refresh the web page, or to use p:poll to refresh at regular intervals.
I have researched this, and I have found very similar threads; the answer is usually to use FacesContext.getCurrentInstance() (JSF) or RequestContext.getCurrentInstance() (PrimeFaces) to access the component and refresh it. I tried, but the context is not available in foo().
I guess it's a lifecycle issue. I have a very limited knowledge of JSF. Any help is appreciated.
You can't access a faces context from a bean when it is updated from a non jsf backend call. Use PrimeFaces push for this.

CDI SessionScoped Bean results in two instances in same session

I've got two instances of a SessionScoped CDI bean for the same session. I was under the impression that there would be one instance generated for me by CDI, but it generated two. Am I misunderstanding how CDI works, or did I find a bug?
Here is the bean code:
package org.mycompany.myproject.session;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpSession;
#Named #SessionScoped public class MyBean implements Serializable {
private String myField = null;
public MyBean() {
System.out.println("MyBean constructor called");
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)fc.getExternalContext().getSession(false);
String sessionId = session.getId();
System.out.println("Session ID: " + sessionId);
}
public String getMyField() {
return myField;
}
public void setMyField(String myField) {
this.myField = myField;
}
}
Here is the Facelet code:
<?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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html" encoding="UTF-8">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form id="form">
<h:inputText value="#{myBean.myField}"/>
<h:commandButton value="Submit"/>
</h:form>
</h:body>
</f:view>
</html>
Here is the output from deployment and navigating to page:
INFO: Loading application org.mycompany_myproject_war_1.0-SNAPSHOT at /myproject
INFO: org.mycompany_myproject_war_1.0-SNAPSHOT was successfully deployed in 8,237 milliseconds.
INFO: MyBean constructor called
INFO: Session ID: 175355b0e10fe1d0778238bf4634
INFO: MyBean constructor called
INFO: Session ID: 175355b0e10fe1d0778238bf4634
Using GlassFish 3.0.1
Ryan, as covener already wrote, the constructor will also get called for each and every proxy for that bean. This is a standard behaviour of all proxy mechanisms which provide not only interface-proxying (like java.lang.reflect.proxy stuff) but real class-proxying.
Also imagine that the ct will also be called for each and every serialization. So if you work on a heavily load balanced cluster, you will see this lots of times. So please use #PostConstruct for beans in general.
LieGrue,
strub
It's likely that your CDI implementation calls the underlying beans default constructor when newing up proxies to use for injection points -- this is the default behavior of javassist which is used in weld and openwebbeans.
Avoid heavy lifting in your default constructor, moving it into #PostConstruct if you can!

Resources