One p:poll stop the other? - jsf

I'm newest with primefaces. What I'm trying to do is to fill a h:outputText, but i have to use p:poll because I make a request and I have to wait for response and it can take some time until I get the answer.
<h:form id="form1">
<p:poll widgetVar="headerPoll" interval="3" listener="#{bean.refreshHeader()}" update="form1" />
</h:form>
<h:form id="bodyForm">
<p:commandButton actionListener = "#{bean.loadBody}" ajax="false" value="load body" /> <br/><br/>
<h:outputText id="bodyText" escape="false" value="#{bean.body}" />
<p:poll widgetVar="bodyPoll" interval="3" listener="#{bean.refreshBody()}" update="bodyText" />
</h:form>
The associated bean:
public void refreshHeader()
{
if(header != null)
{
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.execute("headerPoll.stop();");
}
}
public void refreshBody()
{
if(body != null)
{
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.execute("bodyPoll.stop();");
}
}
The problem is at refreshHeader() function. When headerPoll.stop() get executed it stop the first and the second poll. I need to stop only one.
How can I stop only one of these polls ?

See you have set interval=3 in both the polling that's why both the functions get called parallely. Try running polling at different time. Hope it will work :)

Related

How to keep FacesMessage displayed

I display messages in my application
However, the messages are shown brifely and I would like to keep them on screen until they are closed manually.
How can i achieve this ?
EDITED:
I invoke the run method where messages are made.
I invoke the component pbAjax which then updates the growl element
I use
<p:growl id="growl" />
<p:commandButton value="Run" actionListener="#{myBean.run}" id="btnSubmitCreation" onclick="PF('pbAjax').start();"
<p:progressBar widgetVar="pbAjax" ajax="true" value="#{progressBean.progress}" styleClass="animated" >
<p:ajax event="complete" listener="#{controleBean.onComplete}" update="growl" oncomplete="startButton2.enable()"/>
</p:progressBar>
Java code:
public void run() {
...
...
List<String> messages = expResult.getMessages();
for (String message:messages){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,message,message));
}
}
Just add sticky="true" in growl tag.

How to get the selected item from an p:orderList?

I want to get the selected item from an orderList. It seems to me that this functionality is missing. Is there a functionality in PF? Or is there a possible workaround?
I really appreciate your answer!
My technology stack:
Hibernate: 4.0.1.Final
Spring: 3.1.1.RELEASE
Primefaces: 3.5
jsf-version: 2.2.0-m08
PrimefacesMobile-version: 0.9.3
Apache Tomcat/7.0.12
I've resolved this by using a button for delete. The code snippet is below:
<p:orderList id="layersList" value="#{mappingLayerController.layers}"
converter="layerConverter" var="layer" itemValue="#{layer}"
controlsLocation="left">
<p:column>
<h:outputText value="#{layer.layerName}"/>
</p:column>
<p:column style="width: 4%">
<p:commandButton icon="ui-icon-close" actionListener="#{controller.deleteLayer()}">
<f:param name="layerName" value="#{layer.layerName}" />
</p:commandButton>
</p:column>
</p:orderList>
And in the backing bean you can get the supplied parameter via the f:param tag as:
String layerName = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("layerName");
I hope this helps.
I ran into the same issue trying to create an edit action for each item in my orderList. I tried passing my var to the action, creating an action listener in combination with an attribute, and a select listener all without success.
I ended up using a dataTable ... draggableRows="true" (see data table reorder in showcase). In the data table I could simply pass my var as a parameter to an action... So I thought. I ran into the issue that after reordering, clicking the edit button gave me the wrong item. I created a workaround being that on reorder I update the model and redraw the table. It works, but doesn't feel right.
<p:dataTable id="myTable"
value="#{myBean.myItems}"
var="item"
sortBy="#{item.orderNumber}" sortOrder="ascending"
draggableRows="true">
...
<p:column headerText="Actions">
<p:commandButton title="Edit"
action="#{myBean.edit(item)}"
process="#this">
</p:column>
<p:ajax event="rowReorder"
listener="#{myBean.onSlotContentReorder}"
update="myTable"/>
</p:dataTable>
It is possible in PrimeFaces 5 and higher. There is no out of box feature, but it can be easily achieved with additional list of selected items. See example
Java code
private List<Record> allItems; // with getter and setter
private List<Record> selectedItems; // with getter and setter
public void onSelect(SelectEvent event) {
if (null == event || null == event.getObject()) {
return;
}
if (!event.isCtrlKey()) {
setSelectedItems(new ArrayList<Record>());
}
Record item = (Record)event.getObject();
if (!getSelectedItems().contains(item)) {
getSelectedItems().add(item);
}
}
public void onUnselect(UnselectEvent event) {
if (null == event || null == event.getObject()) {
return;
}
Record item = (Record)event.getObject();
if (getSelectedItems().contains(item)) {
getSelectedItems().remove(item);
}
}
public void deleteSelected() {
if (getAllItems().isEmpty()) {
addErrorMessage("listEmpty");
return;
}
if (getSelectedItems().isEmpty()) {
addErrorMessage("noItemSelected");
return;
}
for (Record item : getSelectedItems()) {
if (getAllItems().contains(item)) {
getAllItems().remove(item);
}
}
}
XHTML
<h:panelGroup id="listGroup">
<p:orderList id="list" value="#{bean.allItems}"
var="item" itemLabel="#{item.code}" itemValue="#{item}"
converter="#{itemConverter}" controlsLocation="none">
<f:facet name="caption">#{msg.listName}</f:facet>
<p:ajax event="select" listener="#{bean.onSelect}" />
<p:ajax event="unselect" listener="#{bean.onUnselect}" />
</p:orderList>
<p:contextMenu id="listMenu" for="list">
<p:menuitem value="#{msg.delete}"
actionListener="#{bean.deleteSelected}"
update="listGroup, messages"
rendered="#{not empty bean.allItems}" />
</p:contextMenu>
</h:panelGroup>

PrimeFaces with JSF - "onerror " in the <p:commandButton> doesn't work

I am using JSF,with #ManagedBean annotation and using Primefaces, and I got the following problem.
Why the "onerror" is not triggered? The exception just appears in my console.
login.xhtml
<p:commandButton
value="teste"
action="#{loginBean.methodTest()}"
ajax="true"
immediate="false"
onerror="confirmation.show()" />
<p:dialog
appendToBody="true"
header="Atencao"
widgetVar="confirmation"
showEffect="bounce">
...
</p:dialog>
MyBean
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean {
public void methodTest() throws Exception {
System.out.println("hi");
throw new Exception("Exception Test");
}
This is the expected behavior...
onerror : Client side callback to execute when ajax request fails.
in your case there is no failure in the ajax request at all , that fact that you are throwing exception got nothing to do with ajax failure
onerror is called when jsf doesn't catch your exception, http error or so. Exception != error.
read this thread for further details Ajax Engine: onerror doesn't work (might provide you with some tips...)
See the following detailed explanation about f:ajax onerror
the onerror attribute looks for an http error status code which you need to provide yourself.
In your first example
public void methodTest() {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletResponse response = (HttpServletResponse) context.getResponse();
response.setStatus(500);
System.out.println("hi");
}
should work.
Thanks everybody,
I solved this problem with a not very good way (but it worked out !), but i think perhaps you can help me to improve this way. I would like to throw a Ajax error into my "catch", and the "onerror" (insted of oncomplete) recive it, and open the dialog.
Is there possibility ??
Example that worked out , with a poor way:
<p:panel id="PanelLogin" header="Login" >
<h:form id="FormLogin" >
<br/>
<h:panelGrid columns="2">
<h:outputLabel for="user" value="Usuario:" />
<p:inputText id="user" required="true" value=" " size="75" />
<h:outputLabel for="pin" value="Senha:" />
<p:password id="pin" required="true" value=" " size="55" />
</h:panelGrid>
<p:commandButton styleClass="botaoLogin" value="OK" action="#{loginBean.checkLogin()}" ajax="true" oncomplete="if (#{loginBean.dialog}) confirmation.show()" />
</h:form>
</p:panel>
<p:dialog id="atencaoDialog" resizable="false" appendToBody="true" header="Atencao" widgetVar="confirmation" height="85" width="300" showEffect="bounce">
<div align="center">
<p:messages id="outputTextAtencaoDialog" autoUpdate="true" redisplay="false" />
</div>
<div style="text-align: center;">
<p:commandButton id="okButtonAtencaoDialog" value="OK" onclick="confirmation.hide();" />
</div>
</p:dialog>
MyBean
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private boolean dialog;
...
public String checarAutenticacao() {
...
try {
...
return "/templantes/telaAplicacao.xhtml";
} catch (Throwable e) {
this.dialog = true;
// try to throw Ajax error instead of this below ??
FacesContext.getCurrentInstance().addMessage(null,new FacesMessage(e.getMessage()));
return null;
}
}

JSF Action Method not being called

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

Add message from method in JSF

I have request scope backing bean for login page( I am using Spring Security ). When authentication error occurs Spring put it to context and I am trying add error message to my page.
public void doLogin() throws IOException {
final FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
externalContext.dispatch("/j_spring_security_check");
if (externalContext.getRemoteUser() == null) {
Exception loginError = (Exception) externalContext.getSessionMap().get(
AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
if (loginError instanceof BadCredentialsException) {
externalContext.getSessionMap().put(
AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, null);
context.addMessage("loginBtn", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid credentials!", null));
context.responseComplete();
}
}
context.renderResponse();
}
my page:
<a4j:form prependId="false">
<h:panelGrid columns="2" cellpadding="5" >
<h:outputText value="#{msgs.login_username}"/>
<h:inputText id="j_username"/>
<h:outputText value="#{msgs.login_password}"/>
<h:inputSecret id="j_password"/>
<h:outputText value=" "/>
<f:facet name="footer">
<h:panelGroup>
<h:commandButton type="submit" id="loginBtn" action="#{guest.doLogin}" value="#{msgs.login}" />
<rich:spacer width="5" height="1"/>
<rich:message id="errorForLogin" for="loginBtn">
<f:facet name="errorMarker">
<h:graphicImage value="./resources/forbidden.gif"/>
</f:facet>
</rich:message>
</h:panelGroup>
</f:facet>
</h:panelGrid>
<br/><br/>
</a4j:form>
But it's don't works. I am trying put error displaying code to #PostConstruct method but this didn't help. This work only if I implement my PhaseListener but I think this is bad idea because it invokes on every request. What my mistake, there are some ways add error message from method, maybe in #PostConstruct method?
You can approach this from other side. As you use SpringSecurity, you can subclass AuthenticationProcessingFilter and override onUnsuccessfulAuthentication method. There you can put the code for desired behaviour. Then you just specify your custom authentication processing filter class instead of AuthenticationProcessingFilter in correspondent bean definition for Spring Security.

Resources