Primefaces dataTable call method multiple times when click commandButton. why? - jsf

<p:commandButton value="Get Name List" update="nameinfo"/>
<p:dataTable id="nameinfo" var="nam" value="#{namefinder.dofind}"></p:dataTable>
"namefinder" is managed bean [ #ManagedBean(name = "namefinder")]
"dofind" is the method which find the name list and it return the value as namefinder class object list
Problem is: "dofind" method is call 7 times.
why doing like this?

Because this is the way JSF is working, and this is correct according to Java Bean principles. Getter can be called multiple times, as much as the caller wishes.
The value attribute of p:dataTable expects getter method and is calling that method multiple times. You can't guarantee how many times will a getter be called. Instead, you should do no logic in getter method.
Instead, provide the method that will be called by your p:commandButton and refresh the collection there. dofind should be the field of JavaBean with the list of rows, no logic should be done there.

Related

How to execute a bean method inside foreach without button or link in jsf?

I am looping a list containing strings in foreach, so in every iteration the variable in foreach loop should be passed as a parameter to a bean method written inside the foreach loop. I searched many sites but everywhere I am finding solution that bean method cannot be executed without commandbutton or link. Is there any solution to execute bean method without any commandbutton or link.
<c:forEach var="name" items="#{bean.stringList}"
varStatus="loopCounter">
<!--I have to execute the method here passing "name" as parameter-->
</c:forEach>
Since EL 2.2 you can invoke non-getter methods with arguments. So you could use:
<c:forEach var="name" items="#{bean.stringList}"
varStatus="loopCounter">
<c:set var="dummy" value="#{bean.yourMethod(name)}" />
</c:forEach>
However, you are most likely are trying to solve something here that can be done in more elegant ways like a PhaseListener, a #PostConstruct method, a f:viewAction, etc.
See also
How to implement a PhaseListener which runs at end of lifecycle?
Why use #PostConstruct?
When to use f:viewAction / preRenderView versus PostConstruct?

Preprocess/postprocess a bean action method from p:remoteCommand inside composite

I have the following scenario:
JSF composite component with complex JavaScript, which I'd like to refresh partially by JavaScript with a new values from a backing bean (backing bean of a page which uses this composite component, not backing component #FacesComponent).
I don't want to make full update because it's complex JavaScript plugin and it will unacceptably break UX.
I get values from backing component #FacesComponent by using Primefaces's <p:remoteCommand> with callback as described here Best method for passing Data from Java/JSF2 bean to Javascript/jQuery Components
I know that it's some abuse of JSF but would like to encapsulate all the functionality in a single unit and don't mess with a JAX-RS If you can advice another nice solution how to encapsulate such complex jQuery plugin (for sake of clarity we are talking about FullCalendar, I know that Primefaces has its own implementation of this component but its functionality insufficient for my requirement so, I was need to make my own implementation) which highly related on ajax callbacks with parameters you're highly welcome to share it here.
My question is how to update values in a backing component #FacesComponent from backing bean by using JavaScript? Currently I involved in the following chain of events:
calling from Javascript <p:remoteCommand> with parameters which passed to backing component #FacesComponent to be dispatched later in AjaxBehaviorEvent
JavaScript:
refreshEvents([
{name:'start', value:start.format()},
{name:'end', value:end.format()}
]);
JSF code:
<p:remoteCommand name="refreshValues" oncomplete="loadValues()" action="#{cc.refreshLocal()}" process="#this"/>
Parameters which I passed stored in a backing component by using
getStateHelper().put(...);
jQuery event dispatched from composite component by following JavaScript code:
var hiddenField = $(document.getElementById(variables.hiddenId));
hiddenField.trigger("keypress");
In composite component's overridden method public void queueEvent(FacesEvent event) I add to this AjaxBehaviorEvent property which I stored before, in a 1st step and dispatch it forward.
Dispatched event from composite component "captured" in a page where composite component nested and performed process on this component:
<p:ajax event="refreshEvent" process="#this" listener="#{bean.refreshEvents}"/>
in #{bean.refreshEvent} method I perform request to #EJB bean and load data.
On callback from step 1 called again by loadValues()
<p:remoteCommand name="loadValues" action="#{cc.getLocalData()}" oncomplete="updateValues(xhr, status, args);"/>
In a backing component's method #{cc.getLocalData()} I add a callback parameter by using:
RequestContext.getCurrentInstance().addCallbackParam("param", ...);
function updateValues(xhr, status, args) from step 5 get in args this param's values and performs actual update.
So, my general question is it possible to simplify this process and how?
Thank you.
This is indeed a little overcomplicated. In total 3 ajax requests to just perform an action and a backing component passing data forth and back via the view state.
Your primary goal appears to be able to declare a bean action method as composite component attribute which should then be invoked by a <p:remoteCommand> inside the composite and return the desired model entity based on the passed-in parameters, preferably with some pre- and post-processing.
You can use <cc:attribute method-signature> in the composite interface to declare a method expression attribute:
<cc:interface componentType="yourComposite">
<cc:attribute name="eventListener" method-signature="com.example.Entity method(java.lang.String, java.lang.String)" required="true" />
</cc:interface>
Which can be used in the template client as below:
<my:composite ... eventListener="#{bean.eventListener}" />
public Entity eventListener(String start, String end) {
// ...
return entity;
}
The composite implementation can look like this:
<cc:implementation>
...
<p:remoteCommand name="refreshEvents"
process="#this" action="#{cc.processEventListener}"
oncomplete="updateValues(xhr, status, args)" />
...
</cc:implementation>
The #{cc.processEventListener} method can obtain the eventListener attribute as a MethodExpression and invoke it as below, along with some pre- and post-processing:
public void processEventListener() {
String start = getRequestParameter("start");
String end = getRequestParameter("end");
// ...
MethodExpression method = (MethodExpression) getAttributes().get("eventListener");
Entity entity = (Entity) eventListener.invoke(getFacesContext().getELContext(), new Object[] { start, end });
// ...
addCallbackParam("param", entityAsJSON);
}
Now it's only 1 ajax request "as usual".

Jsf ui:repeat - method that populates the value is accessed even when submiting different form

In my actual project I have noticed that the method that populates the ui:repeat tag, is being invoked when there is a post call, even though the ui:repeat is not part of the submitted form.
I have been trying to check againts the jsf documentation if that is the way it should work, with no success.
Is it supposed to work this way?
Thanks in advance.
Sample code:
When the button is clicked the method anotherBean.getCollection is being invoked:
<h:form id="firstForm">
<h:commandButton action="#{someBean.someAction}"/>
</h:form>
<h:form id="secondForm">
<ui:repeat var="product" value="#{anotherBean.populatCollection}" >
<!-- CODE -->
</ui:repeat>
</h:form>
In first place, a getter method shouldn't be populating the value at all. A getter method should, as its name says, just return the already-populated value.
You're not terribly clear on the concrete functional requirement, i.e. when exactly did you intend to populate the value, but one way would be moving the populating logic to the #PostConstruct of #{anotherBean}.
#ManagedBean
#ViewScoped
public class AnotherBean {
private List<Something> getCollection; // Terrible variable name by the way.
#PostConstruct
public void init() {
getCollection = populateItSomehow();
}
public List<Something> getGetCollection() {
return getCollection; // See, just return the property, nothing more!
}
}
See also:
Why JSF calls getters multiple times
So, it looks like ui:repeat tag is invoking the methods assigned to its value argument when a post is done, no matter if the post is done from another form.
Thanks for the help.

jsf navigation to another method

I am developing an application using jsf 2.0 and i have the following situation:
I have 2 managed beans.
On the first managed bean i have a method that process some data and then store the result in session.After the data was stored in session i need to invoke a method on the second bean that will display the information from session.
The problem is that if i return a string from the first bean method that correspond to the seconds bean method view the data is not processed, and of course not displayed.
What i need is some navigation rule that from the first bean would redirect me to the second bean method, and the second bean method would return a string with the corresponding view name.
update
maybe a
<f:event listener="#{secondBean.methodToBeInvoked}" type="preRenderView" />
would help me achieve that.
Is this the right approach ?

How to use <ui:repeat> to iterate over a nested list?

Using JSF 2.0, I need to display a table wherein each row contains a link which opens a popup. I have two models: A which has id and List<B> properties and B which has id and name properties. In my backing bean, I have a List<A> property. In my view, I am using <ui:repeat> to iterate over List<A>.
The requirement is, depending on the row that the user clicks, the corresponding List<B> of A needs to be displayed. However, the <ui:repeat> does not accept a nested list to be assigned in the var attribute. Hence, I need to do a lot of workarounds which is not efficient.
How do I efficiently solve this problem?
What you need is to nest another <ui:repeat> tag in your outer iteration:
<ui:repeat value="#{bean.listOfA}" var="a">
...
<ui:repeat value="#{a.listOfB}" var="b">
...
</ui:repeat>
</ui:repeat>
The only thing left that is worth noting is that nested <ui:repeat> tags used to have problems with state management until Mojarra 2.1.15 version (details in jsf listener not called inside nested ui:repeat and in many not so recent questions and their answers), which could result in action listeners not called, etc. but if you're currently on the latest Mojarra JSF implementation - just skip this part altogether.

Resources