I have an JSF 2.2 page which contain forms and a <h:commandButton> to call the method, after the submit button, the method called successfully and all instructions works fine
Problem:
After the button submit, I got an empty page and the URL in the browser is still unchanged
What I want is that after the submit, the page stays the same and shows a growl message.
managedBean.java
#ManagedBean(name="consignmentShipBean")
#ViewScoped
public class ConsignmentShipBean implements Serializable{
public void send(){
//some instructions to do
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "__") );
}
}
page.xhtml
<p:growl id="growl" globalOnly="true" autoUpdate="true"/>
<h:form>
...
<h:commandButton value="Send" actionListener="#{consignmentShipBean.send}" />
</h:form>
UPDATE
the result after the button submit:
You have to perform an Ajax request, not an usual request. Use a standard button or a PrimeFaces one for it:
<h:commandButton value="Send" actionListener="#{consignmentShipBean.send}" >
<f:ajax update="growl"/>
</h:commandButton>
Or
<p:commandButton value="Send"
actionListener="#{consignmentShipBean.send}" update="growl" />
Related
I'm using jsf and Primefaces and I need some help.
I built in my project a IdleMonitor. It will trigger after the timeout a growl and I want to build in a clickable link. But my problem is that I can't add html code into the bean and didn't find anything about actions after clicking on the growl.
public void onActive() {
String link = "http://abcd.efg.com";
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "Deine Session ist abgelaufen", link));
}
xhtml:
<h:form>
<prime:growl id="messages" showDetail="true" sticky="true" redisplay="false" escape="false"/>
<prime:idleMonitor timeout="5000">
<prime:ajax event="idle" listener="#{idleMonitorView.onActive}" update="messages" />
<prime:ajax event="active" listener="#{idleMonitorView.onActive}" update="messages"/>
</prime:idleMonitor>
</h:form>
I am seeing different behaviors of and in a page containing multiple forms.
Here is my backing bean:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class MultiFormBean
{
String inputText1 = "";
String inputText2 = "";
#PostConstruct
public void initializeBean(){
System.out.println("PostConstruct Called ------------------");
}
public String getInputText1()
{
return inputText1;
}
public void setInputText1(String inputText1)
{
this.inputText1 = inputText1;
}
public String getInputText2()
{
return inputText2;
}
public void setInputText2(String inputText2)
{
this.inputText2 = inputText2;
}
public void doSubmit1() {
inputText2 = inputText1;
}
public void doSubmit2() {
inputText1 = inputText2;
}
}
When i use the following xhtml , clicking Submit1 and Submit2 any number of times won't call #PostConstruct more than once:
<h:body>
<h:form id="firstForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget1"/>
<h:inputText id="first_input" value="#{multiFormBean.inputText1}"/>
<h:commandButton id="click1" action="#{multiFormBean.doSubmit1}" value="submit1" type="submit"
onclick="javascript:jsf.ajax.request(this, event, {execute:'firstForm', render:'renderTarget1 secondForm'}); return false;">
</h:commandButton>
</h:form>
<h:form id="secondForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget2"/>
<h:inputText id="second_input" value="#{multiFormBean.inputText2}"/>
<h:commandButton id="click2" action="#{multiFormBean.doSubmit2}" value="submit2" type="submit"
onclick="javascript:jsf.ajax.request(this, event, {execute:'secondForm', render:'renderTarget2 firstForm'}); return false;">
</h:commandButton>
</h:form>
</h:body>
But the following xhtml would call #PostConstruct more than once:
<h:body>
<h:form id="firstForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget1"/>
<h:inputText id="first_input" value="#{multiFormBean.inputText1}"/>
<a4j:commandButton id="click1" action="#{multiFormBean.doSubmit1}" value="submit1" type="submit" execute="#form" render="renderTarget1,secondForm"/>
</h:form>
<h:form id="secondForm" prependId="false">
<h:panelGroup layout="block" id="renderTarget2"/>
<h:inputText id="second_input" value="#{multiFormBean.inputText2}"/>
<a4j:commandButton id="click2" action="#{multiFormBean.doSubmit2}" value="submit2" type="submit" execute="#form" render="renderTarget2,firstForm"/>
</h:form>
</h:body>
Please can anyone help me use the <a4j:commandButton> instead of <h:commandButton>
Also i see that i cannot call the method doSubmit2() with a4j commandButton
I think that problem here is in bug inside JSF2 and Richfaces4. From 4 version Richfaces started using JSF embedded ajax capabilities. And There is a bug with using multiple forms on page with ajax requests. The problem there that richfaces renders special hidden input with the id of currently rendered view state. This id is changed when new view is rendered. And it is also submitted with every request to show that it belongs to some specific view. So when you have multiple forms on the same page after first ajax request the view state is getting the wrong place and it can be not submitted again second time. Sometimes behavior looks like very very wierd with no logical description.
PostConstruct is called twice because server thinks that two requests belong to different views(view state is not sumbitted) and as far as bean is view scoped it is created twice. After clicking aroung ajax can completelly stop working with this because server woukd not recognize the view(probably what you see when you can not click second submit button).
In the first place I recommend you to use latest available version of JSF and Richfaces. This bug (and many more) may be already fixed there.
I have a JSF composite component which includes as a root an h:form. The form has many components among of which are selectOneMenu and a h:inputFile. When I set enctype="multipart/form-data" on the form, the valuechangelistener of the selectOneMenu is invoked ONLY for two value-changing events. Later, however I interact with the menu, the value change listener is not invoked at all. However, if I remove the enctype="multipart/form-data" every thing works fine. I have to keep enctype="multipart/form-data" because I have a file upload component.
Here is my Bean :
#Model
#ViewScoped
public class TransactionBean implements Serializable {
private Part inReceiptFilePart;
/*setter and getter*/
private TransactionType transactionType;
/*setter and getter*/
private final TransactionType transTypeList[] = {
TransactionType.COMPLETE,TransactionType.TECHNICAL,TransactionType.SUBMUNICIPALITY_TECHNICAL, TransactionType.COMPLAINT, TransactionType.FOLLOWUP_COUNCIL, TransactionType.FOLLOWUP_MANAGEMENT
};
public TransactionType[] getTransTypeList() {
return transTypeList;
}
public void transactionTypeChanged(ValueChangeEvent event) {
... /// some code
}
}
And here is the JSF composite component :
<h:form id="entryForm" enctype="multipart/form-data">
<p:selectOneMenu id="transType" value="#{transactionBean.transactionType}" style="direction: ltr" valueChangeListener="#{transactionBean.transactionTypeChanged}">
<f:ajax execute="transType" render="#form" > </f:ajax>
<f:selectItems value="#{transactionBean.transTypeList}" var="tt" itemLabel="#{tt.arName}">
</f:selectItems>
</p:selectOneMenu>
<h:inputFile value="#{transactionBean.inReceiptFilePart}" > </h:inputFile>
<p:commandButton id="insertTrans" value="أدخل المعاملة" action="#{transactionBean.insertTransaction}" ajax="false">
</p:commandButton>
</h:form>
The environment is JSF 2.2, Glassfish 4.0 and primefaces 3.5.
Please help me. I am stuck for three days on this problem.
Thanks
This is very strange behavior!
Try changing valueChangeListener event to an AJAX call.
<p:selectOneMenu id="transType" value="#{transactionBean.transactionType}" style="direction: ltr" >
<p:ajax event="change" partialSubmit="true" update="#form" listener="#{transactionBean.transactionTypeChanged}"/>
<f:selectItems value="#{transactionBean.transTypeList}" var="tt" itemLabel="#{tt.arName}" />
</p:selectOneMenu>
Primefaces's AJAX component is behavior component that extends JSF AJAX.
It adds and manages new events (e.g. valueChange); it also reattach javascript events to DOM element automatically.
Your case is that jsf's ajax does not rebind the valueChange Listener to "transType" selectOneMenu when the form is mutipart! (It's very strange, because the behavior should be the same of those ajax event, weather the form is mutipart or www-form-encoded!
Im implementing a login in a JSF application and have a problem with the redirection.
I want to make available the login form in every xhtml in the app, but after the login success or fail I want to keep the user in the same page they were when clicked on login.
I have tried to return null in the managedBean methong but that doesnt work because it not refreshes the webPage, I need the page to be refreshed for the view logic to work.
This is the login form:
<h:form id="loginForm" rendered="#{!loginBean.estaLogueado()}">
<p:panel header="#{msg.header_login}">
<h:outputLabel for="login" value="#{msg.login}"/>
<p:inputText id="login" value="#{loginBean.usuario}"></p:inputText><br/>
<h:outputLabel for="pwd" value="#{msg.password}"/>
<p:inputText id="pwd" type="password" value="#{loginBean.password}"></p:inputText><br/>
<p:commandButton action="#{loginBean.login()}" value="Login"/>
</p:panel>
</h:form>
<h:form id="logoutForm" rendered="#{loginBean.estaLogueado()}">
Bienvenido #{loginBean.nombreUsuario}!!<br/>
<p:commandButton action="#{loginBean.logout()}" value="Desconectar"/>
</h:form>
And this is the method in the action attribute:
public String login(){
currentUser = gu.login(usuario, password);
return null;
}
There is a way to return to the xhtml where the user loged, not being a fixed xhtml like "login.xhtml"??
Just redirect to the request URI.
public void login() throws IOException {
// ...
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(((HttpServletRequest) ec.getRequest()).getRequestURI());
}
As far as i am concern there is 2 ways for this purpose.
You should define the components which need to be updated in update attribute of caller commandButton.
You should do a real refresh by adding ?faces-redirect=true to return value of action.
First solution.
<h:form id="loginForm" rendered="#{!loginBean.estaLogueado()}">
<p:panel header="#{msg.header_login}">
<h:outputLabel for="login" value="#{msg.login}"/>
<p:inputText id="login" value="#{loginBean.usuario}"></p:inputText><br/>
<h:outputLabel for="pwd" value="#{msg.password}"/>
<p:inputText id="pwd" type="password" value="#{loginBean.password}"></p:inputText><br/>
<p:commandButton action="#{loginBean.login()}" value="Login" update=":loginForm :logoutForm"/>
</p:panel>
</h:form>
<h:form id="logoutForm" rendered="#{loginBean.estaLogueado()}">
Bienvenido #{loginBean.nombreUsuario}!!<br/>
<p:commandButton action="#{loginBean.logout()}" update=":loginForm :logoutForm" value="Desconectar"/>
</h:form>
the update attribute will update the components.
Second solution
Add ?faces-redirect=true to your return value of action method for a real refresh
public String login(){
currentUser = gu.login(usuario, password);
return "login?faces-redirect=true";
}
I have a JSF view with a Primefaces data table and a command button insite it, as fallows:
<p:messages id="statusMessages" showDetail="true" />
<h:form id="listForm">
<p:panel header="Wellsite List">
<br />
<h:outputLabel value="Welcome, #{wellsiteController.loggedUser.login}" />
<br />
<br />
<p:dataTable id="dataTable" var="wellsite" value="#{wellsiteController.wellsiteDataTableModel}"
paginator="true" rows="10" selection="#{wellsiteController.wellsite}">
<p:column selectionMode="single" style="width:18px" id="radioSelect" />
<p:column sortBy="#{wellsite.reference}" headerText="Wellsite ID">
<h:outputText value="#{wellsite.reference}" />
</p:column>
<p:column headerText="Allowed Groups">
<h:outputText value="#{wellsite.allowedGroups.toString()}" />
</p:column>
<f:facet name="footer">
<h:panelGrid columns="3">
<p:commandButton id="addWellsite" value="Add New Wellsite" icon="ui-icon-flag" ajax="false" action="#{wellsiteController.showAddWellsite}"/>
<p:commandButton id="editWellsite" value="Edit Selected Wellsite" icon="ui-icon-wrench" ajax="false" action="#{wellsiteController.showEditWellsite}"/>
<p:commandButton id="deleteWellsiteButton" value="Remove Selected Wellsite" icon="ui-icon-trash" onclick="confirmation.show()" type="button"/>
</h:panelGrid>
</f:facet>
</p:dataTable>
<p:spacer height="20" />
</p:panel>
<p:confirmDialog id="confirmDialog" message="Are you sure you want to remove the selected Wellsite along with all it's data?" header="Confirmation" severity="alert" widgetVar="confirmation">
<p:commandButton id="confirm" value="Yes" ajax="false" oncomplete="confirmation.hide()" action="#{wellsiteController.deleteWellsite}" />
<p:commandButton id="decline" value="Cancel" onclick="confirmation.hide()" type="button" />
</p:confirmDialog>
</h:form>
And here's the controller:
#ManagedBean(name = "wellsiteController")
#RequestScoped
public class WellsiteController implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty("#{wellsiteDao}")
private WellsiteDao wellsiteDao;
#ManagedProperty("#{userDao}")
private UserDao userDao;
#ManagedProperty("#{groupDao}")
private GroupDao groupDao;
#ManagedProperty("#{userController.loggedUser}")
private UserEnt loggedUser;
private WellsiteEnt wellsite;
private List<WellsiteEnt> wellsiteList;
DualListModel<GroupEnt> pickGroupsModel;
public WellsiteController(){
}
#PostConstruct
public void build(){
wellsite = new WellsiteEnt();
wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
}
/*some getters & setters*/
public WellsiteDataTableModel getWellsiteDataTableModel(){
return new WellsiteDataTableModel(getWellsiteList());
}
public void setPickGroupsModel(DualListModel<GroupEnt> model){
pickGroupsModel = model;
}
public DualListModel<GroupEnt> getPickGroupsModel() {
if(pickGroupsModel == null){
List<GroupEnt> allGroups = groupDao.getAll();
List<GroupEnt> currentGroups = wellsite.getAllowedGroups();
for(GroupEnt g : currentGroups){
allGroups.remove(g);
}
pickGroupsModel = new DualListModel<GroupEnt>(allGroups, currentGroups);
}
return pickGroupsModel;
}
public String listWellsites(){
getWellsiteList();
return "listWellsites";
}
public String showAddWellsite(){
FacesContext context = FacesContext.getCurrentInstance();
setWellsite(new WellsiteEnt());
wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
pickGroupsModel = null;
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
"Fields annotated with a ' * ' are mandatory",""));
return "addWellsite";
}
public String addWellsite(){
FacesContext context = FacesContext.getCurrentInstance();
wellsite.setDate(new Date());
wellsite.setLastUpdate(wellsite.getDate());
try {
wellsiteDao.addWell(wellsite);
for(GroupEnt g : pickGroupsModel.getTarget()){
GroupEnt group = groupDao.getOne(g.getGroupId());
group.getGroupWellsites().add(wellsite);
groupDao.update(group);
}
return listWellsites();
} catch (Exception ex) {
Logger.getLogger(WellsiteController.class.getName()).log(Level.SEVERE, null, ex);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
ex.getMessage(),""));
return null;
}
}
}
This view gets rendered correctly. The datatable and buttons looks fine. The problem is that when first i click the "addWellsite" commandButton, nothing happens. The page just seems to refresh. If i click it again, as exception happens:
java.lang.NumberFormatException: For input string: "null"
Using a debugger, i found out that the "addWellsite"'s action is NOT called the first time, and so, not outcome is generated (thus, the page refresh).
The exception is probably comming from the lack of initialization in the current or the target views (since both view are displayed from action methods that were not called in the page refresh)
The question is: WHY the action method is not called the first time?
As from this answer:
Whenever an UICommand component fails to invoke the associated action, verify the following:
UICommand components must be placed inside an UIForm component (e.g. h:form).
I do have a h:form
You cannot nest multiple UIForm components in each other (watch out with include files!).
There's only one.
No validation/conversion error should have been occurred (use h:messages to get them all).
I have a h:messages that does not display any error.
If UICommand components are placed inside an UIData component, ensure that exactly the same DataModel (the object behind the UIData's value attribute) is preserved.
The commandButton is inside the dataTable, but the target view does not need the dataModel. As my controller code shows, the object is built as the view tries to retrive it. The next request is not using this dataTable, to i do not handle it anymore.
The rendered and disabled attributes of the component and all of the parent components should not evaluate to false during apply request values phase.
There's no rendered or disbled attributes.
Be sure that no PhaseListener or any EventListener in the request-response chain has changed the JSF lifecycle to skip the invoke action phase.
No phaseListener is defined.
Be sure that no Filter or Servlet in the same request-response chain has blocked the request fo the FacesServlet somehow.
No other Servlet is defined. I don't even know what a Filter is.
WHY the action method is not called the first time?
This can happen when a parent of this <h:form> was been rendered by an ajax request initiated by another <h:form> beforehand. The rendered/updated <h:form> would then lose its view state. This is caused by a bug in the JavaScript API as described in JSF issue 790 which is already fixed for the shortly upcoming JSF 2.2.
In the meanwhile, with JSF 2.0/2.1, you need to explicltly specify the client ID of the <h:form> in the render (or for PrimeFaces, the update) attribute of the action in the other form.
E.g.
<h:commandButton ...>
<f:ajax ... render=":listForm" />
</h:commandButton>
or
<p:commandButton ... update=":listForm" />
Or just make it a normal (non-ajax) request instead.
See also:
Communication in JSF 2 - Ajax rendering of content which contains another form