I'm new to JSF and I want to spend a text when an action is executed successfully. But the output text, it is not when the action is executed successfully.
Here is the view (deactivatePerson.xhtml):
<h:outputText value="#{msg.personIsDeactivate}" rendered="#{isPersonDeactivate}" />
<h:form>
<h:commandButton action="#{controller.deactivate}" value="#{msg.deactivate}" />
</h:form>
Here is the managed bean:
#ManagedBean
#SessionScoped
public class Controller {
private boolean isPersonDeactivate = false;
public String deactivate() {
isPersonDeactivate = false; // Deactivate process...
isPersonDeactivate = true;
return "persondeactivate";
}
//Getter and Setter
}
Here is the faces-config.xml:
<navigation-rule>
<navigation-case>
<from-outcome>persondeactivate</from-outcome>
<to-view-id>/deactivatePerson.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Can someone please tell me what I do wrong here?
You forgot to reference it as a property of the #{controller} managed bean. It's unclear what your getter look like, but boolean properties should have a getter prefixed with is instead of get. The property name itself should preferably not have an is prefix. It should rather be a verb statement.
Thus, more so:
private boolean personDeactivated;
public boolean isPersonDeactivated() {
return personDeactivated;
}
Then you can reference it as follows:
<h:outputText ... rendered="#{controller.personDeactivated}" />
Unrelated to the concrete problem, navigation cases are superfluous since the new JSF 2.0 implicit navigation. Just let your action method return "deactivatePerson" and it'll go to the proper view without needing a <navigation-case>. Make sure that you're reading proper JSF 2.x targeted resources and not JSF 1.x targeted ones.
Related
Is there a way to execute a JSF managed bean action when a page is loaded?
If that's relevant, I'm currently using JSF 1.2.
JSF 1.0 / 1.1
Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.
public Bean() {
// Do your stuff here.
}
JSF 1.2 / 2.x
Use #PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.
#PostConstruct
public void init() {
// Do your stuff here.
}
This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.
JSF 2.0 / 2.1
Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
JSF 2.2+
Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).
public String onload() {
// Do your stuff here.
// ...
return "some.xhtml";
}
See also:
How do I process GET query string URL parameters in backing bean on page load?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.
Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.
This is how to do it -
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
</f:metadata>
</html>
And in the myController.java
public void onPageLoad(){
// Do something
}
EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.
JSF 2.2 has a new feature which performs this task using viewAction.
<f:metadata>
<f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
#PostConstruct is run ONCE in first when Bean Created.
the solution is create a Unused property and Do your Action in Getter method of this property
and add this property to your .xhtml file like this :
<h:inputHidden value="#{loginBean.loginStatus}"/>
and in your bean code:
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public String getLoginStatus() {
// Do your stuff here.
return loginStatus;
}
Calling bean action from a <p:remoteCommand> will be a good idea, keep attribute autoRun="true"
Example below
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />
This question already has answers here:
How does the 'binding' attribute work in JSF? When and how should it be used?
(2 answers)
Closed 6 years ago.
I have some trouble dealing with PrimeFaces 5.0 and a panelGroup with "binding". I know, "binding" sucks, but I'm working with a legacy system and believe me, it's truly hard to make it the right way, without "binding".
So, when I click mi link, the getter of the "binding" property is called before the "action", then the action is called, and after all the "update". But, the component is not properly updated.
Even if I make it to run the "action" before the getter of the binding, and the getter is returning the right stuff, this particular component is not updated.
I have more components without binding which are updated properly, but not the one with "binding".
UPDATE:
Here is the rest of the code. flag starts with "false" value.
The page always print "READ ONLY".
Somepage.xhtml
<h:form id="frm">
<p:commandLink value="#{messages.Guardar}" id="bt_Guardar" action="#{myBean.flagFalse}" update="someid" />
<p:commandLink value="#{messages.Editar}" id="bt_Editar" action="#{myBean.flagTrue}" update="someid" />
<h:panelGroup id="someid" layout="block">
<h:panelGroup id="panelCamposTD" layout="block" binding="#{myBean.someStuff}" ></h:panelGroup>
</h:panelGroup>
</h:form>
And my myBean, wich is a SessionScoped bean (because it comes from a legacy system)
#ManagedBean(name="myBean")
#SessionScoped
public class MyBean implements Serializable{
private static final long serialVersionUID = 7628440827777833854L;
private boolean flag = false;
public void flagFalse(){
flag = false;
}
public void flagTrue(){
flag = true;
}
public HtmlPanelGroup getSomeStuff(){
HtmlPanelGroup pg = new HtmlPanelGroup();
HtmlOutputText t = new HtmlOutputText();
if (flag){
t.setValue("EDITED");
}else{
t.setValue("READ ONLY");
}
pg.getChildren().add(t);
return pg;
}
public void setSomeStuff(HtmlPanelGroup pg){
return;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
You should avoid bindings to managed beans with session scope. This can cause a lot of touble:
JSF 2.0 Spec
3.1.5 Component Bindings
[...]
Component bindings are often used in conjunction with JavaBeans that are dynamically instantiated via the Managed Bean Creation facility (see Section 5.8.1 “VariableResolver and the Default VariableResolver”). It is strongly recommend that application developers place managed beans that are pointed at by component binding expressions in “request” scope. This is because placing it in session or application scope would require thread-safety, since UIComponent instances depends on running inside of a single thread. There are also potentially negative impacts on memory management when placing a component binding in “session” scope.
There are two solutions which could avoid the binding:
In this solution, the output text is always visible and just get a different text from the backed bean:
<h:panelGroup id="someid" layout="block">
<h:panelGroup id="panelCamposTD" layout="block">
<h:outputText value="#{myBean.flaggedText}"></h:outputText>
</h:panelGroup>
</h:panelGroup>
Add the getter to the backed bean:
public String getFlaggedText(){
if (flag){
return "EDITED";
}else{
return "READ ONLY";
};
}
The other option is to put both output texts in the front end and hide one of them:
<h:panelGroup id="someid" layout="block">
<h:panelGroup id="panelCamposTD" layout="block">
<h:outputText value="EDITED" rendered="#{myBean.flag}"></h:outputText>
<h:outputText value="READ ONLY" rendered="#{not myBean.flag}"></h:outputText>
</h:panelGroup>
</h:panelGroup>
I have a simple CDI bean. The problem is that when I invoke method removeCustomer from the JSF page, method getCustomers() is executed before removeCustomer instead the opposite way. First I thought that producer itself is the problem but I'm getting same behavior if I put the list inside the controller. When I get response page the row in the table is not removed ether it is removed from the database. When I refresh page once more I don't see the deleted row.
#Named
#RequestScoped
public class CustomersController {
#Inject
private CustomerService customerService;
#Produces()
#RequestScoped
#Named("customers")
public List<Customer> getCustomers() {
return customerService.findCustomers();
}
/**
* #param customerId
*/
public String removeCustomer(Long customerId) {
customerService.deleteCustomer(customerId);
return null;
}
}
<h:form id="customers-form">
<h:dataTable value="#{customers}" var="customer"
styleClass="table">
<h:column>
<f:facet name="header">#{msg['customer.name']}</f:facet>
#{customer.name}
</h:column>
<h:column>
<f:facet name="header">#{msg['customer.vat']}</f:facet>
#{customer.vat}
</h:column>
<h:column>
#{msg['global.edit']}
</h:column>
<h:column>
<h:commandButton styleClass="btn btn-danger"
action="#{customersController.removeCustomer(customer.id)}"
value="#{msg['global.delete']}" aria-hidden="true">
<f:ajax render="#form"></f:ajax>
</h:commandButton>
</h:column>
</h:dataTable>
I'm using JBoss WildFly beta 1 but I'm guessing that it uses stable JSF 2.x version.
Check this answer
The method getCostumers is called before because the EL expresion (#customers) is being evaluated several times while processing the request (more details in the link).
The solution is to make your getters and setters "dumb". Just make them change a variable of your class. Avoid logic with side effects (like customerService.findCustomers();). If you need initialization, you can perform it in a #PostConstruct method or in a method fired by a JSF event).
Also, take into account that with a #RequestScoped bean, a new instance of the bean will be created for every request (either to render the page, or to save changes to the values).
Actually it is pretty easy to achieve what I want.
Here is updated CDI bean.
#Named
#RequestScoped
public class CustomersController {
#Inject
private CustomerService customerService;
#Inject
private List<Customer> customers;
#Produces()
#RequestScoped
#Named("customers")
public List<Customer> getCustomers() {
return customerService.findCustomers();
}
/**
* #param customerId
*/
public void removeCustomer(Customer customer) {
customerService.deleteCustomer(customer.getId());
customers.remove(customer);
}
}
As you can see. On ajax request to remove the customer producer is invoked before method removeCustomer. Logically because in restore view phase jsf is restoring view and evaluating EL expressions and this is happening before event processing phase. So we have list of customers in request scope and we need to inject it in controller bean so we can remove from the list selected customer in the removeCustomer method. I hope I was clear enough.
I have written a piece of code to put two pairs of radio button in a *.xhtml page of a JSF project built in JSF2.0, Jboss As 7.1.1 final and JDK 6.0, PrimeFaces 3.4.2.
<h:panelGrid columns="2">
<h:selectOneRadio value="#{calendarBean.radioFirst}">
<f:selectItem id="morning" itemValue="morning" itemLabel="Morning"/>
<f:selectItem id="afternoon" itemValue="afternoon" itemLabel="Afternoon"/>
</h:selectOneRadio>
<h:selectOneRadio style="padding-left: 170px" value="#{calendarBean.radioSecond}">
<f:selectItem id="noon" itemValue="noon" itemLabel="Noon"/>
<f:selectItem id="endofday" itemValue="endofday" itemLabel="End Of Day"/>
</h:selectOneRadio>
</h:panelGrid>
The Bean is:
private String radioFirst="morning";
private String radioSecond="endofday";
public String getRadioFirst() {
return radioFirst;
}
public void setRadioFirst(String radioFirst) {
this.radioFirst = radioFirst;
}
public String getRadioSecond() {
return radioSecond;
}
public void setRadioSecond(String radioSecond) {
this.radioSecond = radioSecond;
}
I have written a method to invoke on a Action Event where I want to have the values of the radio button selected. when the method invokes I get the value of the radio buttons as "morning" and "endofday" as these two are the initial values of the bean variables.
private String radioFirst="morning";
private String radioSecond="endofday";
But if I change the radio button options, I don't get the updated values, its the same old initial values. How can I get the changed values? Please help!
Three things
Don't use the session scope for this usage scenario. This will go completely wrong when your users open the same page in more than one tab. Use request scope or view scope.
Use a regular action instead of an action listener, and don't provide the radio button values as attributes. This makes no sense. The selectOneRadio components will set the updated values on your backing bean. When your action method is invoked, you will have access to those values via the instance fields of your bean.
Leave out the window.reload. If you need a full page refresh after the action, set ajax to false on the p:commandButton or use an h:commandButton.
You should modify your action button like this :
<p:commandButton actionListener="#{userLeaveBean.addAppliedLeave}" styleClass="apply_button" value="Create Leave">
<f:attribute name="userId" value="#{employee.name}"/>
</p:commandButton>
As #MikeBraun suggested, remove the window.reload(). If you want to refresh something, you could do it by using the update attribute from the p:commandButton.
And modify your bean according to this :
#ManagedBean
#SessionScoped // Could probably be moved to #RequestScoped or #ViewScoped
public class UserLeaveBean
{
#ManagedProperty(value="#{calendarBean}")
CalendarBean calendarBean;
public void setCalendarBean(CalendarBean calendarBean)
{
this.calendarBean = calendarBean;
}
public void addAppliedLeave(ActionEvent event)
{
System.out.println("Radio 1 : " + calendarBean.getRadioFirst());
System.out.println("Radio 2 : " + calendarBean.getRadioSecond());
}
}
The ManagedProperty will get the other bean accessible for you by injecting it inside the current one. Use the proper scope, probably you are using SessionScoped because you are using window.reload().
Important : the ManagedProperty bean must be at least scoped the same length as the other bean.
Read more :
Injecting Managed Beans in JSF 2.0
PrimeFaces Showcase - commandButton
I want to store the selected value of the first attribute managedabean "refCont" in a second attribute of the managed bean and then I'll post. but the value will show that after the second selection knowing that the value displayed is the one selected for the first time. I do not know what's sake
.xhtml
<h:outputText value="* Contact" />
<h:selectOneMenu id="contact" value="#{reclamationMB.refCont}" onchange="lazyload()">
<c:set value="#{reclamationMB.refCont}" target="#{contactMB}" property="refContt" />
<f:ajax listener="#{contactMB.affichReclContact}" />
<f:selectItem itemLabel="Select One" noSelectionOption="true" itemValue="---" />
<f:selectItems value="#{contactMB.contactsClient}" noSelectionValue="" var="contact" itemValue="#{contact.refCont}" itemLabel="#{contact.nomCont}" />
<f:selectItems itemLabel="Autre" itemValue=""></f:selectItems>
</h:selectOneMenu>
first ManagedBean:
#RequestScoped
public class ReclamationMB extends AbstractMB implements Serializable {
private int refCont;//ref contact recuperé pour la creation de la reclamation
.....
//getter and setter
Second Mnaged bean
#RequestScoped
public class ContactMB extends AbstractMB implements Serializable {
#ManagedProperty("#{reclamationMB.refCont}")
private int refContt;
.....
//getter an setter
public void affichReclContact(AjaxBehaviorEvent event){
contact=service.AffichContact(refContt);
setContact(contact);
}
The problem is that JSTL's <c:set> is a view build time tag handler, and not a view render time UI component, so your problem is a classical one: when you expect it to set the value, it is no longer there in the component tree. Moreover, it has run when there was no <h:selectOneMenu> tag at all.
Of course, if <h:selectOneMenu> implemented ActionSource, just like <h:commandButton>, you could have nested JSF <f:setPropertyActionListener> for the reason of setting the bean property with the needed values, as in <f:setPropertyActionListener target="#{contactMB.refContt}" value="#{reclamationMB.refCont}">. But you can't do that.
Basically you can do two things:
Use PrimeFaces <p:remoteCommand> tag, which can hold the abovementioned action listener to set the needed value, and call it in onchange method. There are a bunch of such examples here on Stack Overflow and in excellent PrimeFaces' documentation.
Make use of bean injection, instead of just bean property injection. In the former case, the expression reclamationMB.getRefCont() will always yield the right result in the holder bean, provided that reclamationMB is the variable to hold the injected bean by #ManagedProperty.