This question already has an answer here:
How and when should I load the model from database for JSF dataTable
(1 answer)
Closed 7 years ago.
I'm using EJB and JSF. I made a jsp simple page with a button "get list". When it's clicked, a managed bean method is called that sets the list, which is then displayed in the jsp with the dataTable tag.
The question is, how can I pre load this list/dataTable on page load without having to click the button?
This is the method that's called through the button action on the jsp:
public String retrieveList() {
items = facade.getAllItem();
return "";
}
this is the part of the jsp:
<h:dataTable value="#{mybean.items}" var="sup"
binding="#{mybean.dataTable}"
rowClasses="oddRow, evenRow"
styleClass="tableStyle"
headerClass="tableHeader"
columnClasses="column1, column2, column1, column1, column1, column1">
You can add a method init with #postConstruct
#PostConstruct
public void init(){
items = facade.getAllItem();
}
This will return the items only on bean creation ,
Annotate the method with #PostConstruct and get rid of return value.
#PostConstruct
public void retrieveList() {
items = facade.getAllItem();
}
This way the method will be executed immediately after construction of the bean and injection of all #EJB dependencies. In the JSF page you just have to bind to #{bean.items} the usual way.
Related
I am trying to create a dynamic panel (panel with various items) then i want to bind it with panel component in view page, the scope of managed bean which has the panel object is #ViewScoped.
I noticed that any ajax render this panel in the view page rebuild the managed bean, Why is that ?
Here is my code :
this is the managed bean :
package test;
import org.icefaces.ace.component.panel.Panel;
#ManagedBean(name = "myBean")
#ViewScoped
public class myBean {
private Panel myPanel;
// Constructor
public myBean() {
myPanel = drawPanel(); // this function initiate and add items to the panel
}
// Setters and Getters Methods
}
and this the view page :
<h:form>
<ace:panel binding="#{myBean.myPanel}"></ace:panel>
<ace:pushButton actionListener="#{myBean.something}">
<ace:ajax render="#form" />
</ace:pushButton>
</h:form>
in every time i pressed the button, the managed bean constructor invoked , Why does that happened ?
Also i noticed that if i remove the binding attribute from the panel component or make the scope of the managed bean session or application scope, the constructor didn't invoked.
Note : I am using icefaces 3 and jsf 2.0 .
Is there any solution for this situation ?
As the ICEFaces documentation says:
The Push Button is a component that allows entry of a complete form or just itself. It has the same functionality of a regular jsf command button but without having to add extra attributes.
Because the PushButton is a command button it do navigation. If you don't use its action attribute it will apply its default value. I can't find what it is (I just suspect that it is an empty string).
The JSF navigation rules depending on the action outcome of UICommands:
null or void : reloads the current view
empty string : recreates the current view (if the view recreated, the view scoped beans do the same)
non empty string : the next view determined by the navigation handler.
If the reason is the empty string default result of the action attribute, then use it in the facet:
<ace:pushButton action="#{myBean.nextPage}" actionListener="#{myBean.something}">
And pass back a null value in its linked handler method:
public class MyBean // You use myBean here in your question improperly
{
public String nexPage()
{ return null; }
}
This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 6 years ago.
i am working on a simple project in JSF 2.2 but i have some problem navigating between some pages. In the project i have a general template and all the views are template clients of that general template.
this is the view that i have troubles with:
<h:body>
<ui:composition template="./LayoutGeneral.xhtml">
<ui:define name="content">
<p:commandButton value="Registrar Comunidad" action="#{comunidadBean.irRegisterView}"/>
</ui:define>
</ui:composition>
</h:body>
In the action of the commandButton i call a method from the managed bean (Thar managed bean have other method that i call to change the page and they work fine, but this method doesnt):
(Managed Bean)
#ManagedBean
#SessionScoped
public class ComunidadBean {
private String idComunidad;
private String idPresidente;
private String calle;
private int numero;
private int nVecinos;
#EJB
private ComunidadDAO ejb;
public String register(){
if(ejb.realizaRegistro(this)){
return "principalView";
} else{
FacesMessage fm = new FacesMessage ("No se pudo registrar");
FacesContext.getCurrentInstance().addMessage("msg", fm);
return null;
}
}
public String irRegisterView(){
return "registroCView";
}
}
So the method "register" works fine and the page change but the method "irRegisterView" doesnt navigate to "registroCView" page.
Does someone has any idea of what it is happening?
Thanks!
I can' comment, so I write this as an answer.
I see that your bean is SessionScoped. You need to implement Serializable because a SessionScoped bean is passivating after a time.
do you have a form in LayoutGeneral.xhtml? If not, this code will never works because a commandButton needs be within a form.
why you call the method as a property? In JSF 2.2 and EL 2.3, you can call methods like this: #{comunidadBean.isRegisterView()}.
Is some exception thrown when click the button? If do, paste the stack trace.
I have the simpliest version of primefaces' DataTable (without sorting, pagination etc.) and controller class which is responsible for providing data to html page. 'cars' is collection passed to p:datatable as value attribute:
<p:dataTable id="dtid" var="car" value="#{someController.cars}" />
#Named
#SessionScoped
public class SomeController {
#Inject
SomeService dataProvider;
private Collection<Car> cars;
#PostConstruct
public void init() {
cars = dataProvider.getCars();
}
public Collection<Car> getCars() {
return cars;
}
I want to ensure that collection of cars in reloaded every time i hit "refresh" button on my webpage. init() method is invoked only once, while the page is being loaded for the first time. How to achieve this in the simpliest way? To make things clear: I do not want to change scope to #RequestScope or anything else.
Thanks in advance,
P.
If you mean "F5", you could add preRenderViewEvent in f:event tag and set init method as listener? Altough i also don't understand why you use session scoped bean in first place and this is kinda hacky.
This question already has an answer here:
#ViewScoped calls #PostConstruct on every postback request
(1 answer)
Closed 6 years ago.
I have a check box in my application and I want to call selectPlan method to execute when user select the check box
But when ever I select the check box it call the #PostConstruct method before the selectPlan method.
This leads to unwanted calls to back end as I have written some functions to populate data when page load in the #PostConstruct
<td>
<h:selectBooleanCheckbox value="#{plan.checked}">
<f:ajax listener="#{planOverlay.selectPlan}" render=":overlayForm:myTable"/>
</h:selectBooleanCheckbox>
</td>
Below is the bean class
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "planOverlay")
#ViewScoped
public class PlanOverlayBean extends OverlayBean {
#PostConstruct
public void init() {
super.init();
loadPlansFrom_DB();
}
public void selectPlan(AjaxBehaviorEvent event) throws Exception {
getOverlay().getService().setSelectedPlan(rowdata);
}
}
To avoid that case,we should check if it is postback or ajaxRequest.
If your bean is viewScoped,you can add below code to your post-construct method.
Maybe it is not the best case but it works.
Also you can use JSF 2 PreRenderViewEvent for some initialization for bean.
if (!FacesContext.getCurrentInstance().isPostback()) {
if (!FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest()) {
//Some initialization
}
}
You should make your bean session scoped, so the #PostConstruct gets called only once per session. When bean is request scoped, like yours is judging by the behavior, it is created for each request which results in init() getting called also for each request.
EDIT
The suggestion was based on the assumption that the bean is request scoped, and that init() should be called once per session/view. OP's comment proved the assumption wrong.
I have a view-scoped bean ManageFoo.java:
#ManagedBean(name = "ManageFoo")
#ViewScoped
public class ManageFoo {
#ManagedProperty(value = "#{currentRow}")
private Foo currentRowBean;
.
.
public void setCurrentRowBean(Foo foo) {...}
public Foo getCureentRowBean() {...}
public void edit(ActionEvent e) {
getCurrentRowBean();
.
.
}
}
I then have the facelets file ManageFoo.xhtml:
<h:dataTable value=#{ManageFoo.foos} var="currentRow">
<h:column>
<h:commandLink actionListener="#{ManageFoo.edit}"/>
.
.
When the 'commandLink' is clicked, however, 'getCurrentRowBean' returns null.
I have this working fine using FacesContext and a getBean("currentRow") helper method, but I'm trying to "JSF 2ify" my web application by using ManagedProperty's, ManagedBean's, etc. Am I just not implementing this properly or am I trying to use ManageProperty's in a way that doesn't make sense?
After feedback from Balus, his solution works well for my action methods, but I'm having trouble getting it to work for methods that return values (such as boolean). The following method is used in a bunch of "rendered" attributes for each row. For example, if you are editing a certain row, all of the other edit buttons on the other rows disappear and the edit button for the current row is replaced by a cancel edit button and save button. So, this method has different return results for each row:
public boolean isCurrentRowEditing() {
if(getCurrentRowDataBean().equals(getCurrentDataEditing())) {
return true;
} else {
return false;
}
}
Since I'm trying to eliminate the "getCurrentRowDataBean()" method everywhere, I need a way for this to work.
The #ManagedProperty is set directly after bean's construction. At the point the bean is been constructed, JSF is definitely not busy iterating over the datatable. Also, your bean is put in view scope, so it's been set when the view is requested for the first time, not when you submit the form to the same view. The #{currentRow} will always be null.
There are several ways to achieve this. If you're running an EL 2.2 capable container or are using JBoss EL, then you could just pass it to the action (not listener!) method:
<h:commandLink action="#{manageFoo.edit(currentRow)}"/>
(note that I fixed your managed bean name to start with lowercase, conform the coding conventions)
with
public void edit(Foo currentRow) {
// ...
}
If you aren't running an EL 2.2 capable container nor can't use JBoss EL, then you need to bind the datatable's value to DataModel and use DateModel#getRowData() inside the action(listener) method to obtain the current row.
See also:
How can I pass selected row to commandLink inside dataTable? (shows all possible ways)
Recommended JSF 2.0 CRUD frameworks (shows DataModel way)
Update backing bean in datatable from h:commandButton and JPA (shows EL 2.2 way)
Update as per your update, just compare it in EL. E.g.
rendered="#{currentRow == manageFoo.currentRow}"
and
rendered="#{currentRow != manageFoo.currentRow}"
(note that this only works if its equals() is properly implemented!)