Binding process occurs before action is taken in JSF 2 - java

I'm using PrimeFaces with JSF 2.0, I have this layout:
<h:panelGroup layout="block" id="panelGroup" binding="#{bean.boundPg}" />
<p:commandButton value="Update" action="#{bean.updateMe}" update="panelGroup" />
in which, the bean is SessionBean. By using log4j to debug I found out that the binding process called getBoundPg before executing the action updateMe. So the view is always out-of-date.
Do you know why and how to reverse that order? Thanks!
------------- Edit ---------------
I'm making a web app for a quiz game.
<h:panelGroup layout="block" id="pgContents" binding="#{bean.boundContents}" />
<p:commandButton value="Prev page" action="#{bean.prevPage}" update="pgContents" />
<p:commandButton value="Next page" action="#{bean.nextPage}" update="pgContents" />
pgContents contains many h:pannelGroups, each sub-group contains a label showing the content of a quiz, a h:inputText for the player to give their answer. Because of some reasons, I had to generate the children of pgContents programmatically.
The Prev page and Next page buttons will retrieve the prev/next group of quiz
Below is the bean (getters & setters are skipped)
#ManagedBean(name = "bean")
#SessionScoped
public class LessonHelper {
private int currentPage;
private HtmlPanelGroup boundContents;
public void prevPage() {
// decrease currentPage
// fetch contents
// add children for boundContents (label, inputText)
}
// nextPage() is similar
}
My problem is that, when I click the Prev/Next button, the getter getBoundContents is called first in binding process, and the prevPage()/nextPage() is called later, which cause the content always out-of-date.

Because this is the natural way, as you can see in this wonderful tutorial by BalusC: http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html
Tell me exactly what do you want to do, show what's inside that bean and a solution to your problem will be found!

Related

Data is not provided correctly after doing a request in JSF

In the view main_app.xhtml there are 5 different fields, each of them contains a button, when clicking in this button it has to open the view chart_xxx.xhtml, and it will show a chart with the different data related to the field
i.e.:
General Rating will show some data in the Chart
Clean Rating will show some different data in the Chart
etc
When I click the button the buildGraph() method is called several times, usually 2 or 3, and it some of those requests the parameter sent in the request is shown and in other is not, I don't know why this is happening, therefore
I decided to store that parameter sent by the request in the session but... I don't know why, if I go back to main_app.xhtml, click in a different button, the view chart_xxx.xhtml will show the data from the previous request sent,
but if I go back again to main_app.xhtml and click again in the same button, the correct data is shown.
For example:
I click on General Rating button, its data is shown on the chart.
Go back to main_app.xhtml
Click on Clean rating
Data from General Rating is shown.
Go back to main_app.xhtml
Click on Clean rating again
Data from Clean rating is shown correctly
I have read this topic Why JSF calls getters multiple times several times but I couldn't find a way to adapt it to my feature.
Furthermore, if I use #RequestScoped, the chart is shown empty the second time I click on a button to show it.
Please, omit syntactic issues, I had to change some names due to my company policies so it cannot be identified and also translate from my language so there might be some syntactic issue but only from the translation.
I also omitted Service and DAO classes because they are working fine, they return what I expect from them.
I work with Java 1.6, JSF 2.1 and Primefaces 6.0
So, I need help solving this issue or if someone knows a better approach, I am all eyes but in this case, please, try to make an extended answer because I really cannot think about any other way.
EDIT 1
I've removed Setter and Getter in order to make my code more clear for you, also removed some code assigning attributes to the Chart, but all these things are in my original code and working fine.
PollGraphicBean.java
#ManagedBean(name="pollGraphic")
#SessionScoped
public class GraficosEncuestaBean {
private LineChartModel graphicLine;
public GraficosEncuestaBean(){
if(graphicLine == null){
this.buildGraph();
}
}
public void buildGraph(){
HttpServletRequest parameterMap = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
String general = "";
String clean = "";
String date1 = "01-03-2017 00:00";
String date2 = "30-04-2017 00:00";
if(parameterMap != null){
if(general != null){
general = parameterMap.getParameter("general");
session.setAttribute("hidden", general);
}else if(clean != null){
clean = parameterMap.getParameter("clean");
session.setAttribute("hidden", clean);
}
this.buildGraphicFinal(date1,date2, (String) session.getAttribute("hidden"));
}
}
private void buildGraphicFinal(String date1, String date2, String value){
this.graphicLine = new PollGraphicService().getGraphicData(date1, date2, value);
}
}
chart_xxx.xhtml
<ui:define>
<p:panel>
<h:form>
<p:chart type="line" model="#{pollGraphic.graphicLine}" />
</h:form>
</p:panel>
</ui:define>
main_app.xhtml
<ui:define>
<p:panelGrid>
<p:column>
<p:panel>
<div>
<h:form prependId="false">
<input type="hidden" value="General Rating"
name="general" id="general"/>
<p:commandButton value="Get results"
actionListener="#{pollGraphic.buildGraph}" onstart="location.href =
'/XXX/chart/chart_xxx.xhtml'"/>
</h:form>
</div>
</p:panel>
</p:column>
<p:column>
<h:form prependId="false">
<input type="hidden" value="Clean Rating"
name="clean"/>
<p:commandButton value="Get results"
actionListener="#{pollGraphic.buildGraph}" onstart="location.href =
'/XXX/chart/chart_xxx.xhtml'"/>
</h:form>
</div>
</p:panel>
</p:column>
</p:panelGrid>
</ui:define>
Try changing #SessionScoped to #ViewScoped or even #RequestScoped

Disable a button on click and call its action [duplicate]

This is my ManagedBean:
#Named(value = "mrBean")
#RequestScoped
public class MrBean {
public void laugh() {
System.out.println("HAHAHA");
}
public void prepareToLaugh() {
System.out.println("Drink water.");
}
}
And this is the working version of my commandButton:
<p:commandButton actionListener="#{mrBean.laugh}" widgetVar="laughtButton"
value="Laugh" oncomplete="laughButton.disable();" />
When I clicked the above button, I saw HAHAHA and the button is disabled. However, when I set the laughButton's disable attribute to true, the button does not work anymore:
<p:commandButton actionListener="#{mrBean.laugh}" widgetVar="laughtButton"
value="Laugh" disabled="true" oncomplete="laughButton.disable();" />
<p:commandButton actionListener="#{mrBean.prepareToLaugh}"
value="Prepare to laugh" oncomplete="laughButton.enable();" />
When I click the 2nd button, I saw Drink water and the 1st button is enabled. However, when I click on the 1st button, nothing happens.
I'd be very grateful if someone could give me an advice on how I should tackle this problem. I'm using PrimeFaces 3.0 RC2.
Like as with rendered attribute, JSF re-evaluates the disabled attribute in the server side during processing of the form submit as part of safeguard against tampered requests and like. You're however enabling/disabling it by JS without notifying the server side of the changes.
You need to ensure that the value of the disabled attribute evaluates false during the request whenever you intend the button to be enabled during processing of the form submit. For example, bind it to a boolean property of a view scoped bean which is set by the other button.
<h:commandButton disabled="#{bean.laughDisabled}" />
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated

JSF GAE: Value Update Problem in managed bean method

I have the following piece of code with a simple h:outputText pointing to a int and a p:commandLink to set a value:
<h:form id="f1">
<h:outputText id="text" value="#{testBean.index}"/>
<p:commandLink actionListener="#{testBean.test}" update="text">
<f:setPropertyActionListener target="#{testBean.index}" value="5" />
<h:graphicImage url="/images.png"/>
</p:commandLink>
</h:form>
The managed bean looks like this:
#javax.faces.bean.ManagedBean #ViewScoped
public class TestBean implements Serializable{
private int index; // getter/setter
#PostConstruct public void init() {
index = 0;log.log(Level.WARNING, "#PostConstruct");}
public void test(ActionEvent ae){
log.log(Level.WARNING, "Index: "+index);}
}
The bean is constructed correctly, and after the first click on the image the h:ouputText is updated to 5. But in my log message I only see Index: 0 during the first click on the image.
It's something similar like Jsf updates model value with old value, but I have the JSF #ManagedBean annotation.
Action listeners are invoked in the order they're definied in the view. You want to use action instead of actionListener. Even more, the action should in first place have been used to invoke a business action.
<p:commandLink action="#{testBean.test}" update="text">
<f:setPropertyActionListener target="#{testBean.index}" value="5" />
<h:graphicImage url="/images.png"/>
</p:commandLink>
See also:
Differences between action and actionListener
What is happening is that the test ActionEvent is getting fired before the request values have been applied.
To get a better understanding of the JSF phase lifecycle and when lifecycle events and ActionEvents fire, implement the Debug PhaseListener as specified in the following blog article.
http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html
This should help you understand when request values are being applied, and when events are being fired.

JSF property transfer from backing bean A to backing bean B

I'm getting deeper into JSF 2.0 at the moment and lacking a bit of understanding about the "transport" of managed bean properties from one view to the other. I searched a bit but haven't found a really good example, so if anyone could point me to a tutorial or explain the things a little bit I'd really grateful.
So here is my scenario:
I'm developing a small playground calendar application. The first view select.xhtml contains the calendar selector, where the user can pick a specific date:
<html>
...
<h:form>
<!-- Calendar selector from primefaces -->
<p:calendar value="#{calendarSelect.date}" mode="inline" navigator="true" />
<p:commandButton value="Show entries for date" action="day" />
...
My corresponding backing bean looks like this:
#ManagedBean(name="calendarSelect")
#RequestScoped
public class CalendarSelectComponent {
private Date date = null;
... // Getters and setters
Now when I submit the form from select.xhtml I'm forwarded to day.xhtml
<html>
...
<h:form>
The current day ist:
<h:outputText value="#{calendarEdit.date}">
<f:convertDateTime pattern="dd.MM.yyyy" />
</h:outputText>
The backing bean now looks like this:
#ManagedBean(name="calendarEdit")
#ViewScoped
public class CalendarEditComponent implements Serializable {
private Date date = null;
private CalendarEntryBean currentEntry = null;
private List<CalendarEntryBean> allEntries = null;
....
I am now trying to solve the problem: How do I transfer the date parameter from the selector to the editor?
I've tried a number of options, one was this:
<p:commandButton value="Show entries for date" action="day" />
<f:setPropertyActionListener target="#{calendarEdit.date}" value="#{calendarSelect.date}" />
</p:commandButton>
A debugger shows, that indeed, the date property of the calendarEdit is populated with the value from calendarSelect, but since day.xhtml is a new view, a new CalendarEditComponent backing bean is being created and not the one I've populated with the date from the selector in the select view.
I've read that one solution would be to create a SessionScoped backing bean that does retain all it's values. But this is not the way I think it's supposed to work, because I don't really need the information in the session, I simply want it to "travel" from A to B. Another downside with the session based approach is that I can only use one selector and one editor per session - which I think isn't acceptible if you think of multi window browsing and so on.
I really don't think I'm the first one encountering such a scenario and I'm sure that JSF provides an elegant solution for this but I haven't been able to find that solution.
So once again, if anyone knows how to approach this - I'm listening! ;-)
The <f:setPropertyActionListener> is executed during invoke action phase of the form submit. So it expects that the value is still there at that point. But since your select bean is request scoped, it isn't there during form submit anymore. You want instead to pass a request parameter which get inlined in the output during render response. You can do this with <f:param>.
<p:commandButton value="Show entries for date" action="day" />
<f:param name="date" value="#{calendarSelect.dateAsString}" />
</p:commandButton>
It'll be available as request parameter (note that it only understands Strings, due to the nature of HTTP). You could let JSF set request parameters as managed properties, but since your edit bean is view scoped, this isn't possible with #ManagedProperty. You've got to gather it yourself by ExternalContext.
String dateAsString = externalContext.getRequestParameterMap().get("date");
True, that's clumsy. I would just have used the same bean and view for this and toggle visibility of select/edit forms by rendered attribute. The edit view is after all not directly openable/bookmarkable by a simple GET, isn't it? ;)

prepare a wizard flow using jsf

I am trying to creating a small wizard using jsf1.2 sun RI +richfaces.
The user sets input data in multiple pages and in the end presses finish upon which the data is inserted in database.
The info is displayed as a row in a table with edit button.
when edit is clicked the data is populated in all the pages and user can edit and save it again.
Also while navigating back and forth the data must be persisted in the forms.
Currently i have implemented this by using multiple session scope beans that access each other's data by looking its reference in session map and some are injected as dependencies.
i would like to know if there's a standard way / good pattern of doing this by avoiding multiple session scope beans and doing lookups in session map?
if someone could throw a link to any blog/tutorial with similar example that would be great
many thanks
You can just make them properties of a single session scoped bean.
public class Wizard {
private Step1 step1 = new Step1();
private Step2 step2 = new Step2();
private Step3 step3 = new Step3();
// ...
}
and use it as follows
<h:form id="step1">
<h:inputText id="input1" value="#{wizard.step1.input1}" />
<h:inputText id="input2" value="#{wizard.step1.input2}" />
</h:form>
...
<h:form id="step2">
<h:inputText id="input1" value="#{wizard.step2.input1}" />
<h:inputText id="input2" value="#{wizard.step2.input2}" />
</h:form>
...
This way you just have instant access to everything from inside the action methods.
I would recommend to you to download an open source with components for JSF like PrimeFaces. It will make it much easier for you. They also have a wizard: PrimeFaces Wizard

Categories

Resources