#PostConstruct of #ViewScoped is invoked on every request [duplicate] - jsf

This question already has an answer here:
#ViewScoped calls #PostConstruct on every postback request
(1 answer)
Closed 6 years ago.
I've got problem with opening dialog in JSF 2.2.7 and Primefaces 5. I've got button which opens a dialog and the problem is everytime when I click the button #PostConstruct method is executed. Why?
I want to invoke #PostConstruct only 1 time, but I don't want to change to scope to Session (with #SessionScope annotation it works perfectly).
It's my view:
<!DOCTYPE html>
<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:c="http://java.sun.com/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="f1">
<p:dialog widgetVar="trainingDialog2" id="d1">
<h:outputText value="#{userViewBean.errorMessage}" />
</p:dialog>
<br />
<p:dataTable id="dt1" value="#{userViewBean.infoList}" var="item">
<p:column>
<p:commandButton id="btn" update=":f1:d1"
oncomplete="PF('trainingDialog2').show()"
styleClass="ui-icon ui-icon-calendar">
<f:setPropertyActionListener value="#{item.id}"
target="#{userViewBean.errorMessage}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
It's my bean:
package pl.jrola.java.www.vigym.viewcontroller.beans.userview;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;
#ManagedBean(name = "userViewBean")
#ViewScoped
public class UserViewBean implements Serializable {
private static final long serialVersionUID = 6994205182090669165L;
private String errorMessage;
private List<UserProfileInfoBean> infoList;
public List<UserProfileInfoBean> getInfoList() {
return infoList;
}
public void setInfoList(List<UserProfileInfoBean> infoList) {
this.infoList = infoList;
}
public UserViewBean() {
}
#PostConstruct
public void postConstruct() {
this.infoList = new ArrayList<UserProfileInfoBean>();
for (long i = 0; i < 3; i++) {
this.infoList.add(new UserProfileInfoBean(i));
}
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

You're mixing the annotations for JSF beans and CDI beans, effectively making the bean #RequestScoped, because it's the default for a #ManagedBean.
If you use JSF beans use:
javax.faces.bean.ManagedBean;
javax.faces.bean.ViewScoped;
If you wanna go for CDI beans use:
javax.inject.Named;
javax.faces.view.ViewScoped;
If your server supports CDI you should go for CDI beans.
Read more about the default scopes here:
What is the default Managed Bean Scope in a JSF 2 application?

Related

ViewScoped managed bean recreated on every request [duplicate]

I'm having an issue similar to this post and the answer from #BalusC with 3 solutions but:
I'm not using of the mentioned EL expressions
I don't want to go with the second solution (it's complex enough for me like this)
and partial state saving is set to false.
My code is as follows:
index.xhtml:
<?xml version="1.0" encoding="windows-1256" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Insert title here</title>
</h:head>
<h:body>
<h:form>
<p:panelMenu id="westMenu">
<p:submenu id="sub1" label="System Monitor">
<p:menuitem id="menu1" value="live monitoring"
action="#{menusBean.activateMenu('sub1_menu1')}"
update=":centerPane,westMenu"
disabled="#{menusBean.active['sub1_menu1']}" />
<p:menuitem id="menu2" value="reports"
action="#{menusBean.activateMenu('sub1_menu2')}"
update=":centerPane,westMenu"
disabled="#{menusBean.active['sub1_menu2']}" />
</p:submenu>
<p:submenu id="sub2" label="Charging System Nodes" />
<p:submenu id="sub3" label="Additional Nodes" />
</p:panelMenu>
</h:form>
<h:panelGroup id="centerPane">
...
</h:panelGroup>
</h:body>
</html>
MenusBean.java:
package menus;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.view.ViewScoped;
#ManagedBean
#ViewScoped
public class MenusBean implements Serializable{
private static final long serialVersionUID = -7793281454064343472L;
private String mainPage="sub1_menu1";
private Map<String, Boolean> active;
public MenusBean(){
System.out.println("MenusBean created");
active = new HashMap<>();
active.put(mainPage, true);
active.put("sub1_menu2", false);
}
public boolean activateMenu(String page){
active.put(mainPage, false);
active.put(page, true);
mainPage = page;
for (Map.Entry<String, Boolean> e : active.entrySet())
System.out.println(e.getKey()+":"+e.getValue());
return true;
}
public Map<String, Boolean> getActive() {
return active;
}
}
When executed, I get:
MenusBean created
MenusBean created
MenusBean created
How is this caused and how can I solve it?
This,
import javax.faces.view.ViewScoped;
is the JSF 2.2-introduced CDI-specific annotation, intented to be used in combination with CDI-specific bean management annotation #Named.
However, you're using the JSF-specific bean management annotation #ManagedBean.
import javax.faces.bean.ManagedBean;
You should then be using any of the scopes provided by the very same javax.faces.bean package instead. The right #ViewScoped is over there:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MenusBean implements Serializable{
If you use the wrong combination, the bean behaves as a #RequestScoped bean and be recreated on each call.
Alternatively, if your environment supports CDI (GlassFish/JBoss/TomEE with Weld, OpenWebBeans, etc), then you could also replace #ManagedBean by #Named:
import javax.inject.Named;
import javax.faces.view.ViewScoped;
#Named
#ViewScoped
public class MenusBean implements Serializable{
It's recommended to move to CDI. The JSF-specific bean management annotations are candidate for deprecation in future JSF / Java EE versions as everything is slowly moving/unifying towards CDI.

Dynamically add and remove inputText field using primefaces

I have using primefaces in my project. I need to create and delete field dynamically on my project. Here I am going to attached my code please find it
my xhtml page is
<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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:panelGrid border="0" columns="3" cellpadding="4" columnClasses="control-label">
<h:panelGrid columns="3" cellpadding="4" >
<h:outputText value="Individual Email"/>
<div>
<h:dataTable value="#{utilBean.attachments}" var="attachmentBean" binding="#{utilBean.data}" id="attachments">
<h:column>
<h:inputText id="attachment" value="#{attachmentBean.emailAddress}" binding="#{utilBean.attachment}"/>
</h:column>
<h:column>
<h:commandButton id="delete" value="Delete" immediate="true" actionListener="#{utilBean.deleteAddress}"/>
</h:column>
</h:dataTable>
<h:commandButton id="add" value="Add Email Address" immediate="true" actionListener="#{utilBean.addAddress}" />
</div>
<br/>
</h:panelGrid>
</h:panelGrid>
</ui:composition>
My Bean Is:
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIData;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
#ManagedBean
#SessionScoped
public class UtilBean{
private UIData data=null;
private UIInput attachment = null;
private List<AttachmentBean> attachments = new ArrayList<AttachmentBean>();
public void addAddress(ActionEvent event){
attachments.add(new AttachmentBean());
this.updateAddresses();
FacesContext.getCurrentInstance().renderResponse();
System.out.println("adress size:" + attachments.size());
}
public void deleteAddress(ActionEvent event){
int index = data.getRowIndex();
this.updateAddresses();
this.getAttachments().remove(index);
FacesContext.getCurrentInstance().renderResponse();
}
public void updateAddresses(){
System.out.println("adress sizedfdfdfdf:" + attachments.size());
#SuppressWarnings("unchecked")
List<AttachmentBean> list = (ArrayList<AttachmentBean>)data.getValue();
for(int i =0;i<data.getRowCount();i++){
data.setRowIndex(i);
list.get(i).setEmailAddress((String)getAttachment().getSubmittedValue());
}
data.setRowIndex(0);
}
public UIData getData() {
return data;
}
public void setData(UIData data) {
this.data = data;
}
public UIInput getAttachment() {
return attachment;
}
public void setAttachment(UIInput attachment) {
this.attachment = attachment;
}
public List<AttachmentBean> getAttachments() {
return attachments;
}
public void setAttachments(List<AttachmentBean> attachments) {
this.attachments = attachments;
}
}
And the Attachment Class is
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class AttachmentBean implements Serializable {
private static final long serialVersionUID = 1L;
private String emailAddress;
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public AttachmentBean() {
super();
}
}
I am not able to add textBox by clicking the add button. Please help. Thanks in advance.
You need to put the whole in a <h:form>. See also commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
Another major mistake is here:
<h:dataTable ... binding="#{utilBean.data}">
...
<h:inputText ... binding="#{utilBean.attachment}"/>
Remove those binding attributes. UI components are request scoped and yet you're binding them to a session scoped bean. This would fail hard if you open the same page in multiple browser windows in the same session. See also How does the 'binding' attribute work in JSF? When and how should it be used?.
That said, the #ManagedBean #SessionScoped on AttachmentBean is completely unnecessary. Get rid of those annotations. The #SessionScoped on UtilBean is also rather strange. The #ViewScoped is much better at its place here. See also How to choose the right bean scope?

CommandLink doesn't work. Tried everything

it's my first question on the site :) But first, sorry for my bad english, i'm learning :)
Plz, i need your help. I'm blocked with an application in JSF.
I have this
<?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:h="http://java.sun.com/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<body>
<ui:composition template="./defaultTemplate.xhtml">
<ui:define name="content">
<h1 style="margin-bottom: 0px">#{msg.default_2}</h1>
<br/>
<ul style="padding-left: 0px">
<ui:repeat value="#{categoryMB.categories}" var="categorie">
<h:outputLabel value=" -==- " style="color: #FF8620; font-size: 10px; padding-left: 0px"></h:outputLabel>
<h:form>
<h:commandLink value="#{categorie.categoryname}" action="#{categoryMB.getItemsByCat(categorie.categoryid.id)}"/>
</h:form>
</ui:repeat>
</ul>
<ui:repeat value="#{categoryMB.listItems}" var="item">
<div class="itemCategory">
<h:graphicImage class="item-image" url="#{item.urlimage}"/>
<h:outputLabel value="#{item.price} €" class="prix"></h:outputLabel>
<br/>
<h2><h:outputLabel value="#{item.name}"></h:outputLabel></h2>
<br/>
<h:form>
<h:commandLink value="#{msg.default_14}" action="#{itemMB.linkItem(item.id)}"
></h:commandLink>
</h:form>
</div>
</ui:repeat>
</ui:define>
</ui:composition>
</body> </html>
Everything is good, except the second commandLink !
I can't execute the action. I always return on the same page...
I tried everything i could and i read all subjects about that on the site but i can't find a solution. Please, i'm asking you, help me. I'm going to be crazy.
My bean for categoryMB :
package managedBean;
import entityBean.Item;
import entityBean.Translatecategory;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.view.ViewScoped;
import sessionBean.ItemFacadeLocal;
import sessionBean.TranslatecategoryFacadeLocal;
/**
*
* #author Aurélien
*/
#ManagedBean
#ViewScoped
public class CategoryMB {
#EJB
private ItemFacadeLocal itemFacade;
#EJB
private TranslatecategoryFacadeLocal translatecategoryFacade;
#ManagedProperty("#{internationalizationMB}")
private InternationalizationMB language;
private List<Item> listItems;
/**
* Creates a new instance of CategoryMB
*/
public CategoryMB() {
}
public List<Translatecategory> getCategories () {
return translatecategoryFacade.findByLanguage(language.getLocale().getLanguage());
}
public void getItemsByCat (int idCat) {
setListItems(itemFacade.findByCat(idCat));
}
public InternationalizationMB getLanguage() {
return language;
}
public void setLanguage(InternationalizationMB language) {
this.language = language;
}
public List<Item> getListItems() {
return listItems;
}
public void setListItems(List<Item> listItems) {
this.listItems = listItems;
}
}
And my bean for itemMB :
package managedBean;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
#ManagedBean
#SessionScoped
public class ItemMB implements Serializable {
private int idItem;
/**
* Creates a new instance of ItemMB
*/
public ItemMB() {
}
public int getIdItem() {
return idItem;
}
public void setIdItem(int idItem) {
this.idItem = idItem;
}
public String linkItem(int id)
{
setIdItem(id);
return "item";
}
}
You're mixing CDI #SessionScoped with JSF 2.x #SessionScoped. This is noted in your imports:
import javax.enterprise.context.SessionScoped;
#ManagedBean
#SessionScoped
public class ItemMB implements Serializable {
//...
}
This makes your managed bean to have the default scope, which in JSF 2 is #RequestScoped, so your managed bean will be re created on every request.
Fix your import to:
import javax.faces.bean.SessionScoped;
If you happen to use JSF 2.2.x, start working everything with CDI 1.1. Use #Named for your managed beans and use javax.faces.view.ViewScoped for #ViewScoped.
More info:
What's new in JSF 2.2. CDI compatible #ViewScoped

#ViewScoped bean recreated on every postback request when using JSF 2.2

I'm having an issue similar to this post and the answer from #BalusC with 3 solutions but:
I'm not using of the mentioned EL expressions
I don't want to go with the second solution (it's complex enough for me like this)
and partial state saving is set to false.
My code is as follows:
index.xhtml:
<?xml version="1.0" encoding="windows-1256" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Insert title here</title>
</h:head>
<h:body>
<h:form>
<p:panelMenu id="westMenu">
<p:submenu id="sub1" label="System Monitor">
<p:menuitem id="menu1" value="live monitoring"
action="#{menusBean.activateMenu('sub1_menu1')}"
update=":centerPane,westMenu"
disabled="#{menusBean.active['sub1_menu1']}" />
<p:menuitem id="menu2" value="reports"
action="#{menusBean.activateMenu('sub1_menu2')}"
update=":centerPane,westMenu"
disabled="#{menusBean.active['sub1_menu2']}" />
</p:submenu>
<p:submenu id="sub2" label="Charging System Nodes" />
<p:submenu id="sub3" label="Additional Nodes" />
</p:panelMenu>
</h:form>
<h:panelGroup id="centerPane">
...
</h:panelGroup>
</h:body>
</html>
MenusBean.java:
package menus;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.view.ViewScoped;
#ManagedBean
#ViewScoped
public class MenusBean implements Serializable{
private static final long serialVersionUID = -7793281454064343472L;
private String mainPage="sub1_menu1";
private Map<String, Boolean> active;
public MenusBean(){
System.out.println("MenusBean created");
active = new HashMap<>();
active.put(mainPage, true);
active.put("sub1_menu2", false);
}
public boolean activateMenu(String page){
active.put(mainPage, false);
active.put(page, true);
mainPage = page;
for (Map.Entry<String, Boolean> e : active.entrySet())
System.out.println(e.getKey()+":"+e.getValue());
return true;
}
public Map<String, Boolean> getActive() {
return active;
}
}
When executed, I get:
MenusBean created
MenusBean created
MenusBean created
How is this caused and how can I solve it?
This,
import javax.faces.view.ViewScoped;
is the JSF 2.2-introduced CDI-specific annotation, intented to be used in combination with CDI-specific bean management annotation #Named.
However, you're using the JSF-specific bean management annotation #ManagedBean.
import javax.faces.bean.ManagedBean;
You should then be using any of the scopes provided by the very same javax.faces.bean package instead. The right #ViewScoped is over there:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MenusBean implements Serializable{
If you use the wrong combination, the bean behaves as a #RequestScoped bean and be recreated on each call.
Alternatively, if your environment supports CDI (GlassFish/JBoss/TomEE with Weld, OpenWebBeans, etc), then you could also replace #ManagedBean by #Named:
import javax.inject.Named;
import javax.faces.view.ViewScoped;
#Named
#ViewScoped
public class MenusBean implements Serializable{
It's recommended to move to CDI. The JSF-specific bean management annotations are candidate for deprecation in future JSF / Java EE versions as everything is slowly moving/unifying towards CDI.

Use of JSTL/core tags screws up ViewScoped Bean

I think I have run into a bug in Mojarra 2.1.0. Maybe I missed something but damned if I can see it.
I rely a lot of #ViewScoped beans to save state whilst the browser does a lot of AJAX to the server. I find when I use certain tags, the #ViewScoped bean starts getting re-instantiated when it shouldn't be. Here is my test case backing bean:
/*
* TestStuff.java
*/
package test;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
/**
* Backing bean for test.xhtml -- working out AJAX/SVG connection
*
*/
#ManagedBean
#ViewScoped
public class TestStuff implements Serializable {
private int counter = 0;
public TestStuff() {
log("TestStuff(): {0}", this);
}
public String getRandomNumber() {
int i = (int) (Math.random() * 1000000.0);
return String.format("%d", i);
}
public int getCounter() { return counter; }
public List<String> getStuff() {
return Arrays.asList("big", "bad", "wolf");
}
public void pushButton(ActionEvent evt) {
log("TestStuff.pushButton({0}): {1}",
new Object[] { evt, ++counter });
}
}
And here is the JSF Facelets page that uses it:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>Test Page</title>
</h:head>
<h:body>
<h1>Test Page</h1>
<p>If you are reading this text, the server
is not properly configured.</p>
<ui:composition id="compRoot" template="/template5.xhtml">
<ui:define name="content">
<h1>Test</h1>
<h:form id="formTest">
<p:commandButton value="Do Me"
actionListener="#{testStuff.pushButton}"
update="testUpdate" />
<p:panel id="testUpdate" >
<h:outputText value="Random output is: " />
<h:outputText
value="#{testStuff.randomNumber}"
/>
<h:outputText value=" Counter is: "/>
<h:outputText
value="#{testStuff.counter}"
/>
</p:panel>
<h:panelGrid columns="5" border="1" >
<c:forEach items="#{testStuff.stuff}" var="x">
<h:outputText value="#{x}" />
</c:forEach>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
So here is what goes wrong. When you click on the "Do Me" command button, a new instance of the backing bean gets created each time, just as if it were a #RequestScoped bean. I can see this via the log() call in the constructor.
If you change the bean to #SessionScoped, this doesn't happen. You get one instance of the bean no matter how many times the button is clicked.
HOWEVER -- if you leave it as #ViewScoped, and you take out the c:foreach element and its content, it now no longer re-instantiates the bean each click. In other words it now works as expected.
Is this a mojarra bug or am I doing something wrong here?
This is a known "bug": issue 1665. It's a chicken-egg issue with regard to partial state saving.
In your case, however, you could also just use <ui:repeat>.
<ui:repeat value="#{testStuff.stuff}" var="x">
<h:outputText value="#{x}" />
</ui:repeat>
Your best bet is to try to avoid JSTL tags when using #ViewScoped. The only alternative is to disable partial state saving by a context param in web.xml:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
But it makes the views more memory hogging.

Resources