retaining values across screen sin JSF2.0 - session

I am working on JSF2.0 project where I need to get value in backing bean from previous screen I have explained it below
my first screen
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="LocationID" />
<h:inputText value="#{getDetails.locationID}"/>
<h:commandButton value="Add OS" action="#{getDetails.addOSDetails}"/>
</h:form>
</h:body>
</html>
My backing bean when the commandButton is invoked
#ManagedBean(name="getDetails")
#RequestScoped
public class GetDetailsBean {
private String locationID;
public String getLocationID() {
return locationID;
}
public void setLocationID(String locationID) {
this.locationID = locationID;
}
public String addOSDetails(){
return "/app_pages/addOS";
}
}
My second screen which is addOS is
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:outputText value="Enter Value" />
<h:inputText value="#{addOS.addValue}"/>
<h:commandButton value="Add OS" action="#{addOS.save}"/>
</h:form>
</h:body>
</html>
I want the LocationID entered in the first screen to be available in this backing bean
#ManagedBean(name="addOS")
#RequestScoped
public class AddOS {
private String addValue;
public String getAddValue() {
return addValue;
}
public void setAddValue(String addValue) {
this.addValue = addValue;
}
public String save(){
return "app_pages/success";
}
}
I donot want values to be set in session.Can be used.
Thoughts and help please
Thanks.

If you really intend to do a forward, as you do in your question, the submitted on the first page data is already there when the second page is rendered: remember, the forward is done within the same HTTP request. So, what you ultimately need is to keep the value for a subsequesnt POST request. You can do it, for example, by storing the information is a hidden field on the second page:
<h:inputHidden value="#{getDetails.locationID}" />
And that's basically it.
If you intend to do a redirect, thus by appending ?faces-redirect=true to a navigation case outcome, you need to store that information in EL flash to be able to retrieve it in the recepient page: there are two requests to be done. So, change your first bean's action method to the following:
public String action() {
...
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("locationID", locationID);
return "result?faces-redirect=true";
}
This way on the recepient page it will be available in flash map, thus by
#{flash.locationID}
in EL scope and
(String)FacesContext.getCurrentInstance().getExternalContext()
.getFlash().get("locationID");
in Java code.

Related

ajax listener inside conditionally rendered element not working [duplicate]

This question already has an answer here:
h:commandButton is not working once I wrap it in a <h:panelGroup rendered>
(1 answer)
Closed 6 years ago.
Here is a test case of my problem:
TestBean:
#ManagedBean
#ViewScoped
public class TestBean implements Serializable {
private static final long serialVersionUID = -2329929006490721388L;
private List<TestObject> testObjects;
private int selectedId;
public TestBean(){
List<TestObject> to = new ArrayList<TestObject>();
for(int i=0; i<10; i++){
TestObject o = new TestObject(i, "object-"+i);
to.add(o);
}
this.setTestObjects(to);
}
public void testAjaxListener(int id){
System.out.println("testAjaxListener("+id+")");
this.setSelectedId(id);
}
//+getters/setters
}
TestObject
public class TestObject {
private int id;
private String name;
public TestObject(int id, String name){
this.setId(id);
this.setName(name);
}
//+getters/setters
}
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">
<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></h:head>
<h:body>
<h:form id="testForm">
<h:panelGroup rendered="#{param['view'] eq 'test'}">
<h2>DataTable</h2>
<h:dataTable var="o" value="#{testBean.testObjects}">
<h:column>
<h:commandLink value="#{o.name}" actionListener="#{testBean.testAjaxListener(o.id)}">
<f:ajax
render=":testForm:outputTest"
/>
</h:commandLink>
</h:column>
</h:dataTable>
<h2>output</h2>
<h:outputText id="outputTest" value="#{testBean.selectedId}" />
</h:panelGroup>
</h:form>
</h:body>
</html>
The problem is, that actionListener won't firing (i'm checking that with System.out.print as you can see). It works fine when i remove conditional render from panelGroup, so i think that is the issue - but how can i fix it?
I have readed those topics:
h:commandLink / h:commandButton is not being invoked,
f:ajax inside conditionally rendered custom tag - backing bean method not invoked
and many more, but it didn't solve my problem :(
Please help
It's because the #{param['view'] eq 'test'} didn't evaluate true while JSF is busy processing the ajax submit. It will then also consult the rendered, disabled and readonly attributes once again as safeguard against hacked requests. JSF namely doesn't include the request parameters in the <form action> URL as generated by <h:form>. This matches point 5 of commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
There are several ways to get around this.
Set it as a property of the view scoped bean via <f:viewParam>.
<f:metadata>
<f:viewParam name="view" value="#{testBean.view}" />
</f:metadata>
...
<h:panelGroup rendered="#{testBean.view eq 'test'}">
Manually retain the param via <f:param> (you need to put it in every submit action!):
<h:commandLink ...>
<f:param name="view" value="#{param.view}" />
...
</h:commandLink>
Replace <h:form> by OmniFaces <o:form> which is capable of telling JSF that it must submit the form to an URL including the request parameters:
<o:form includeRequestParams="true">
...
</o:form>
See also:
Retaining GET request query string parameters on JSF form submit

No navigation/refresh after submitting a form

Here is a very simple jsf page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form enctype="multipart/form-data">
Hello<br/>
<h:outputText value="#{backingBean.currentTime}" />
<br/>
<h:outputText id="contatoreID" value="#{backingBean.counter}" />
<br/>
<h:commandButton value="Add" action="#{backingBean.add}">
<f:ajax render="contatoreID"/>
</h:commandButton>
<br/>
<hr/>
<h:commandButton value="Reset Counter" action="#{backingBean.resetCounter}" />
</h:form>
</h:body>
</html>
The backing bean implementation is trivial.
It has a form with multipart/form-data and two buttons, one with ajax behavior which refresh only one component in the page and a 'standard' submit button.
If the Add button is pressed then Reset Counter doesn't cause the browser to refresh or navigate to a new page.
After lots of searches on internet I found this related bug report:The combination of enctype="multipart/form-data" and ajax stops navigation in some scenarios but it is not clear to me if it is recognized as a real bug or a misconfiguration issue.
I'm using latest available Mojarra release 2.2.5. I cannot seen any progress on this bug report. Can you suggest some workaround ?
Besides I recently moved a web application from Glassfish 3.1.2 to Glassfish 4.0. It worked well before while now I'm struggling with lots of problems which seem bug related, such as this on <ui:repeat>.
I'm conscious I cannot ask opinion related questions here, but I'm wondering if I'm the only person which is having a bad experience with JSF 2.2 release. Maybe I was using Jsf 2.0 in a wrong/unsafe manner...
UPDATE
I add the backing bean code
#ManagedBean
#SessionScoped
public class BackingBean {
/**
* Creates a new instance of BackingBean
*/
public BackingBean() {
}
int counter = 0;
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public void add()
{
counter++;
System.out.println("add called " + counter);
}
public void azzera()
{
counter =0;
System.out.println("Azzera ");
}
public String getOra() { return new Date().toString();}
}

h:form inside ui:repeat doesn't work as expected

For a huge project, I need to build multiple forms on a web page. Can't go into details, but assume to have the requested structure of a list of forms; using mojarra jsf 2.2.5
given Managed Bean:
#ManagedBean
#SessionScoped
public class Debug {
private final List<DebugBean> list;
public Debug() {
super();
this.list = new ArrayList<DebugBean>();
this.list.add(new DebugBean("label 1", "value 1"));
this.list.add(new DebugBean("label 2", "value 2"));
}
public String submit() {
LOGGER.info("list = " + this.list.toString());
return "";
}
public List<DebugBean> getList() {
return this.list;
}
}
The bean DebugBean is simple, just contains two variables label and value, both String, and its setter and getter.
Now the xhtml page:
<h:body style="height: 100%">
<ui:repeat value="#{debug.list}" var="x">
<h:form>
<h:panelGrid columns="2">
<h:outputText value="#{x.label}" />
<h:inputTextarea value="#{x.value}" />
</h:panelGrid>
<h:commandButton action="#{debug.submit}" value="ok" />
</h:form>
</ui:repeat>
</h:body>
The problem is in changing the first value. When I change the second one, the logger gives me the new value as expected. But changing the first one, the logger gives me the old list, as if I would have reloaded the complete form without any changes. What's the problem here, and more important: what can I do to make it work?
The solution is simple, but worse. I don't know why, but ui:repeat does not behave as h:dataTable does. So replacing ui:repeat by h:dataTable solves the problem, but means page layout rework (which is a bigger problem, but can be done by me).

Primefaces: Editable object in accordionPanel with Dynamic = True

I am trying to achieve functionality where I am generating the tabs in according panel dynamically according to the list.
List is of say some object e.g Person
Now attribute corresponding to each person, I am showing in each tab in a form.
Values are loaded correctly but when I edit those value I am not getting updated values at the backing bean, I am getting only old values.
Can somebody please explain why ?
Here is the code.
Person Object
public class Person {
String name;
//getter setter
#Override
public String toString() {
return name;
}
}
Backing Bean
#ManagedBean(name = "editor")
public class EditorBean {
private List<Person> persons = new ArrayList<Person>();
#PostConstruct
void init() {
persons.add(new Person("dhruv"));
persons.add(new Person("tarun"));
}
public void testAction() {
System.out.println(persons);
}
// Getter Setter*****************//
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
}
XHTML 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">
<h:head>
</h:head>
<h:body>
<h1>Hello World PrimeFaces</h1>
<h:form>
<p:accordionPanel value="#{editor.persons}" var="person" dynamic="true">
<p:tab title="#{person}">
<p:inputText value="#{person.name}"></p:inputText>
</p:tab>
</p:accordionPanel>
<p:commandButton action="#{editor.testAction()}" value="testAction"></p:commandButton>
</h:form>
</h:body>
</html>
When I run the same with with dynamic="false". This works fine. But in my real scenario I have lots of data which I cannot afford to paint in one go thats why I want to use dynamic = true.
Can somebody explain how to achieve this if not by dynamic = true ??
The reason you're having stale values in your accordion is that dynamic accordions default to cache="true". This attribute causes the accordion to not reload new/updated values. To cause an ajax refresh on tab open, set cache="false" on your accordion

Primefaces commandButton calls action method on page refresh

Completely edited:
Maybe I was mixing problems and misinterpreted. After simplifying my code the question simplifies to: How can I prevent the <p:commandButton> from executing it's action method on page refresh (like when you hit F5 inside browser window)?
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">
<h:body>
<h:form>
<h:outputText value="#{bugBean.number}" />
<h:outputText value="#{bugBean.isComplete()}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form" oncomplete="#{bugBean.complete()}"/>
</h:form>
</h:body>
</html>
backing bean code:
package huhu.main.managebean;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class BugBean implements Serializable {
private static final long serialVersionUID = 1L;
private int number;
private boolean isComplete = false;
public void increase(){
number++;
}
public void complete(){
isComplete = true;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean isComplete) {
this.isComplete = isComplete;
}
}
Update:
Even if I remove the oncomplete stuff like this an click the <p:commandButton> just once, the counter goes up on every page refresh.
<h:form>
<h:outputText value="#{bugBean.number}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form"/>
</h:form>
The construct was lacking Ajax-support due to a missing head definition as it seems. In this case I just added <h:head/> right above the <h:body>-tag and everything worked fine.
Thanks to all contributors!
I think that the action method increase() is not called on each page refresh, but it's called the complete() method instead, and this is probably making you think that the action method has been called.
The oncomplete attribute inside the p:commandButton indicates a client side action, and so a JS method, and not a server action: the EL executes #{bugBean.complete()} when parses it on each page refresh.

Resources