#ConversationScoped bean reconstructed during page-to-page navigation - jsf

I just found a strange behavior when I change from one page to another.
I'm using CDI, Jsf 2.2 API 2.2.8, Omnifaces 2.2, Primefaces 5.2, wildfly 8.2.
Most of the controllers and pages work as expected, but some of them, when I access the page, call the method #PostConstruct, which starts the conversation, then, when I leave the page, the #PostConstruct is called again. I realized that something in page.xhtml is the cause, so I started to look for it. But is a strange behaviour anyway.
Following my code and some examples:
Controller which uses abstract class methos like beginconversation() and list()
import javax.inject.Named;
import javax.enterprise.context.ConversationScoped;
#Named
#ConversationScoped
public class PromptConfigurationController extends BaseController<PromptConfiguration> implements Serializable {
public PromptConfigurationController() {
super(PromptConfiguration.class);
}
#PostConstruct
public void init() {
list();
loadFilters();
}
}
Abstract class
public abstract class BaseController<T extends BaseEntity> {
public void list() {
logger.info("list()");
items = getService().findAll(entityClass);
item = null;
beginConversation();
}
protected void beginConversation() {
logger.info("beginConversation()");
if (conversation != null && conversation.isTransient()) {
conversation.begin();
conversation.setTimeout(CONVERSATION_TIMEOUT);
logger.info("Conversation iniciada: " + conversation.getId());
}
}
}
some xhtml pages which I found problem and the solution (when I found) was:
Error:
<f:convertDateTime pattern="#{webChatSearchController.dateHelper.getLocalizedDatePattern()}" />
The method above just return a pattern.
Working
<f:convertDateTime dateStyle="dd/MM/yyyy" pattern="dd/MM/yyyy" />
Error:
<p:commandButton id="commandButton-active" action="#{satisfactionSurveyController.changeQuestionStatus(true)}" update="form-content" binding="#{satisfactionSurveyController.activeButton}" value="#{bundle['common.active.3.message']}">
Working:
<p:commandButton id="commandButton-active" action="#{satisfactionSurveyController.changeQuestionStatus(true)}" update="form-content" value="#{bundle['common.active.3.message']}" disabled="#{satisfactionSurveyController.disableActiveButton}">
The problem was just the "binding".
Error:
<p:dataTable id="dataTable-group-email" var="emailMonitor" value="#{emailMonitorController.listEmailGroup}" selectionMode="single" rowKey="#{emailMonitor}" filteredValue="#{emailMonitorController.listEmailGroupFiltered}">
Working:
<p:dataTable id="dataTable-group-email" var="emailMonitor" value="#{emailMonitorController.listEmailGroup}" selectionMode="single" rowKey="#{emailMonitor}" >
Just removing 'filteredValue' started working. But without it, I can't use the filter properties.
The navigation is made by a menu of primefaces, all the pages are the same logic:
<p:menuitem id="satisfactionSurvey" action="#{satisfactionSurveyController.listPage}" value="#{bundle[satisfactionSurvey.message']}" ajax="false" immediate="true">
<f:param name="nocid" value="true" />
</p:menuitem>
and the Method:
public String listPage() {
return baseViewPath + "/list.xhtml?faces-redirect=true";
}

Related

poll doesn't work with setted var

I want to use one html page with two ManagedBeans. Depending on the parameter in the URL, I want to set the bean name through JSTL variable. For example:
<c:set var="bean" value="#{webModule1}" scope="request" />
or
<c:set var="bean" value="#{webModule2}" scope="request" />
I have class which was use all this time, so for sure this works:
#ManagedBean(name = "webModule1")
#ViewScoped
public class WebModule1 implements Serializable {
protected WebModulesFormBean form;
#PostConstruct
public void init() {
if (!firstInit()){
this.form= new WebModulesFormBean();
}
//some code
}
public void process() {
if(this.form.isActive()){
//some code
}
}
}
And new one:
#ManagedBean(name = "webModule2")
#ViewScoped
public class WebModule2 extends WebModule1 {
public void process() {
if(this.form.isActive()){
//code with some changes
}
}
}
This solutions works with value attribute and form in not null, for example:
<p:treeTable value="#{bean.form.root}" var="node" id="modulesTree">
But I have problem with this piece of code:
<p:poll listener="#{bean.process()}" widgetVar="documentOutcome" autoStart="#{bean.form.start}" update="modulesTree" async="false"
interval="1" id="myPoll2" />
When listener is called, NullPointerException appears.
And this problem is with all p:polls (I have a few), so this is not a problem with method code.
Problem is that 'form' is null, although at the beginning variable 'form' is initialized and treeTable is shown at the page. So 'form' starts to be null when the listener is called.
Thanks!
I have a solution!
The problem was with:
<c:set var="bean" value="#{webModule1}" scope="request" />
scope="request" was not enough and in my understanding this scope meant that when poll was called, a new bean reference was created and form variable was null because it was not a firstInit().
scope="view" is the solution.
Thank you for comments!

a4j:support in a reRender is not working

I have a button. If this is pressed, a checkbox should be rendered.
This of course works pretty well. The checkbox should, when changed call a function, which should just System.out.println() something so I see it's called.
The problem is: just the simple checkbox function, without the rerendering works pretty well. But as soon as the a4j:support is rerendered, it's not working, the System.out.println() is never called
This looks so easy, but I don't know why it's not working at all!
Any hint/trick?
This is old environment, so JSF 1.2 only.
My xhtml
<s:div id="sdBoolCheckboxtest">
#{testController.testRerenderBool}
<s:div id="sdRerender" rendered="#{testController.testRerenderBool}">
<h:selectBooleanCheckbox id="myscheckbox" value="#{testController.testBool}">
<a4j:support ajaxSingle="true" event="onclick" immediate="true"
status="globalStatus" action="#{testController.testCheckbox()}" />
</h:selectBooleanCheckbox>
</s:div>
</s:div>
</h:form>
My Java class:
#Name("testController")
#AutoCreate
public class TestController {
private boolean testBool = false;
public boolean isTestRerenderBool() {
return testRerenderBool;
}
public void setTestRerenderBool(boolean testRerenderBool) {
this.testRerenderBool = testRerenderBool;
}
private boolean testRerenderBool;
public void switchtestRerenderBool(){
System.out.println("switch");
testRerenderBool = !testRerenderBool;
}
public void testCheckbox(){
System.out.println("drin");
}
public boolean isTestBool() {
return testBool;
}
public void setTestBool(boolean testBool) {
this.testBool = testBool;
}
}
Okay, i got it working, with these changes:
First i added #Scope(ScopeType.CONVERSATION) to the TestController
#Name("testController")
#AutoCreate
#Scope(ScopeType.CONVERSATION)
public class TestController {
...
}
And as a second change, I changed the <s:div to an <a4j:outputPanel
<a4j:outputPanel id="sdBoolCheckboxtest">
This solved my problem, but I'm still wondering why I need the #Scope(ScopeType.CONVERSATION) (I found the hint with the a4j:outputPanel here)
Any explanation would be helpful, thanks!

Button not submit PrimeFaces 3.5

i'm using jsf + primefaces 3.5. And my button isn't calling one method in my managed bean.
I have this xhtml:
<h:form>
<p:inputText id="name" value="#{userMB.userSelected.name}" />
<p:commandButton id="btnSave" value="Salvar" actionListener="#{userMB.save}"/>
</h:form>
And my managed bean is:
#ManagedBean
#SessionScoped
public class UsuarioMB implements Serializable{
User userSelected;
public void save(){
System.out.println(userSelected.getName());
//call my daos and persist in database
}
}
The most curious is that if i remove the , the method is called!
If i put a atribute in p:commandButton "imediate = true ", the method is called, BUT, the information (userSelected.name) is null !
Thanks very much :)
It failed because it threw a NullPointerException because you never initialized userSelected.
Add this to your bean:
#PostConstruct
public void init() {
userSelected = new User();
}
If you have paid attention to the server logs, you should have seen it. As to the complete absence of feedback about the exception in the webbrowser, whereas in normal synchronous (non-ajax) you would have seen a HTTP 500 error page, it's because you're sending an ajax request without apparently an ExceptionHandler configured.
That it works when you set immediate="true" on the button is simply because it will then bypass the processing of all input components which do not have immediate="true" set.
See also:
What is the correct way to deal with JSF 2.0 exceptions for AJAXified components?
You have not given a name to the managedbean UsuarioMB. As suche it will be named usuarioMB.
#ManagedBean – marks this bean to be a managed bean with the name
specified in name attribute. If the name attribute in #ManagedBean is
not specified, then the managed bean name will default to class name
portion of the fully qualified class name.
read more about it in this blog: http://mkblog.exadel.com/2009/08/learning-jsf2-managed-beans/
Secondly, if your code above is complete, you are lacking public getter and setter for userSelected.
Thirdly you are missing the ActionEvent as you have declared a parameterless actionlistener, see Differences between action and actionListener
In order to get you code working you will need to change your xhtml to
<h:form>
<p:inputText id="name" value="#{usuarioMB.userSelected.name}" />
<p:commandButton id="btnSave" value="Salvar" actionListener="#{usuarioMB.save}"/>
</h:form>
And your managed bean as follows
import javax.faces.event.ActionEvent;
// ...
#ManagedBean
#SessionScoped
public class UsuarioMB implements Serializable{
private User userSelected;
public void save(ActionEvent event){
System.out.println(userSelected.getName());
}
public User getUserSelected() {
return userSelected;
}
public void setUserSelected(User userSelected) {
this.userSelected = userSelected;
}
}

ApplicationScoped Bean is null on rich:tab's actionListener-method

I'm using JSF 2.0 and Richfaces 3.3.2.
I'm having an issue on one of my pages.
First of all I have a main page which contains a rich:tabPanel with several rich:tabs, no problem there switching between them.
On the first tab of my page I have another tabPanel with some other tabs.
They all have an actionListener which will call the ViewScoped ManagedBean to edit some Data, which will be displayed on the clicked tab. The method to edit the data calls a method on an ApplicationScoped Bean which is correctly injected (It works in other tabs). When switching a tab on the second layer and the action-method is called, the ApplicationScoped Bean is null.
This only happens when I switch tabs (so it does not happen on the first tab, which is displayed by default) so I think it's related to the actionListener, but i can't figure out why. Unfortunately I can't provide the actual code but this is the rough structure of my page.
mainPage.xhtml
...
<rich:tabPanel>
<rich:tab>
<ui:include src="tabs/tab1.xhtml" />
</rich:tab>
otherTabs
</rich:tabPanel>
...
tab1.xhtml
...
<rich:tabPanel>
<rich:tab actionListener="#{viewScopedBean.method}">
<ui:include src="subtabs/subtab1.xhtml" />
</rich:tab>
<rich:tab actionListener="#{viewScopedBean.method2}">
<ui:include src="subtabs/subtab2.xhtml" />
</rich:tab>
</rich:tabPanel>
ViewScopedBean.java
#ManagedBean
#ViewScoped
public class ViewScopedBean {
#ManagedProperty(value="#{applicationBean}")
private ApplicationBean applicationBean;
private Data data;
public void init() {
...
data = applicationBean.retrieveData();
...
}
public void method(ActionEvent e) {
...
data = applicationBean.retrieveData();
...
}
public void method2(ActionEvent e) {
...
data = applicationBean.retrieveData();
...
}
// getters/setters
}
ApplicationBean.java
#ManagedBean
#ApplicationScoped
public class applicationBean {
public Data retrieveData() {
...
}
}
When clicking subtab2 I get a NullPointerException at the line data = applicationBean.getData(), so the applicationBean is null. This happens everytime on every tab I'm switching to, but never in the init() method, so the applicationBean should not be null.
I could not find any solution or hints on this problem and hope someone has an idea.
Thanks in advance
regards

Netbeans tells "Unknown property" on <p:poll listener>

I havent worked out how to call/invoke a method dynamically without using the #PostContruct method and initialising # the page creation.
At the moment I am simply trying to get the primeface p:poll example working. I have placed the method in its own class for now to keep it clean and simple & looks like so:
#ManagedBean(name="counterBean")
#SessionScoped
public class CounterBean implements Serializable {
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void increment(ActionEvent actionEvent) {
setCount(getCount() + 1);
}
}
And then the xhtml code:
<h:form>
<h:outputText id="txt_count" value="#{counterBean.count} " />
<p:poll interval="3" listener="#{counterBean.increment}" update="txt_count"/>
</h:form>
Intellisense within netbeans tells me that the "increment" part of #{counterBean.increment} is an "Unknown Property" i.e. it cant find the method. So how can I get JSF to recognise and invoke this method from the xhtml?
Well after a some head scratching the p:poll component started working after a slight adaptation from the primefaces demo & manual. Change the p:poll listener to actionListener:
<h:form>
<h:outputText id="txt_count" value="#{counterBean.count} " />
<p:poll interval="3" actionListener="#{counterBean.increment}" update="txt_count"/>
</h:form>
Also ensure that your html page/template is surrounded by the <f:view contentType="text/html"> tag
Hope this helps someone & thanks to BalusC for his help in debugging this.

Resources