0
votes

I'm using p:button with onclick action. (I can't move to p:commandButton, because of legacy outcome navigation in faces-config.xml and custom navigation history in db):

<p:remoteCommand name="unlock_tt" actionListener="#{ttEntityMBean.unlock()}"/>
<p:button value="#{msgs['button.ok']}" outcome="#{ttEntityMBean.navigationMenuItemToRedirect.navigationRule}" onclick="unlock_tt()"/>

Generated by primefaces javascript looks like

onclick="unlock_tt(); window.open(....)"

And after clicking button, unlock_tt() in browser initiated, but immediatly broken by page redirecting, so backed java method didn't execute. Should I make unlock_tt() or java call async to be sure it will be executed before browser leaves page?

Upd: I'm thinking to use p:commandButton, if it is possible to get to-view-id programically, like in this question:

Programmatically get navigation case <to-view-id> from faces-config.xml by outcome

<p:commandButton action="#{ttEntityBean.unlock()}"/>
public String unlock() {
  //some business logic
  return OutcomeResolverHelper.getRuleFor(navigationMenuItemToRedirect.navigationRule)
}

This should reduce number of requests

2

2 Answers

0
votes

I'm not sure this will work but can you try this :

Instead of :

<p:remoteCommand name="unlock_tt" actionListener="#{ttEntityMBean.unlock()}"/>
<p:button value="#{msgs['button.ok']}" outcome="#{ttEntityMBean.navigationMenuItemToRedirect.navigationRule}" onclick="unlock_tt()"/>

do:

<h:panelGroup>
<f:ajax event="click" listener="#{ttEntityMBean.unlock}"/>
<p:button value="#{msgs['button.ok']}" outcome="#{ttEntityMBean.navigationMenuItemToRedirect.navigationRule}" />
<h:panelGroup>

Don't forget to remove onclick and your remotecommand.

This should wrap a panelGroup around your button. PanelGroup implements ClientBehaviorHolder so it can get f:ajax tag in its children. Thus when you click on it it should trigger the listener.

0
votes

The easiest way was migration from p:button to p:commandButton, which allows to execute some java-code in action method before redirect. The core is programmical translation of navigation rule, defined in faces-config.xml to base url, usable in explisit jsf-2.0 style:

//receive base url from <to-view-id> tag
public static String resolveOutcomeRule(String ruleName) {
    FacesContext context = FacesContext.getCurrentInstance();
    ConfigurableNavigationHandler configNavHandler = (ConfigurableNavigationHandler)context.getApplication().getNavigationHandler();
    NavigationCase navCase = configNavHandler.getNavigationCase(context, null, ruleName);
    return navCase.getToViewId(context);
}
//decorate it with faces-redirect=true and our custom navigation
public static String resolveOutcome(NavigationMenuItem item) {
    return resolveOutcomeRule(item.getNavigationRule()) + "?faces-redirect=true&menu=" + item.getId();
}
//controller-method
public String cancelEditTT() {
    super.unlock();
    return FacesUtil.resolveOutcome(getNavigationMenuItemToRedirect());
}
//new jsf button:
<p:commandButton value="#{msgs['button.ok']}" action="#{ttEntityMBean.cancelEditTT}"/>

This solution provided 1-step redirect instead of 2-step old one.