JSF HtmlCommandButton programmatically - Bean method not called if ajax turned off

流过昼夜 提交于 2019-12-13 17:42:56

问题


I'm trying to create an HtmlCommandButton programmatically, following the example here

http://javaevangelist.blogspot.ch/2013/01/jsf-21-tip-of-day-programmatically.html

Everything works fine (i.e., the actionListener is called) if I add the ajax behavior, it doesn't work if ajax is turned off.

Backing bean:

@Named
@RequestScoped
public class CommandBean implements Serializable {

   public String generateUUID() {
        return java.util.UUID.randomUUID().toString();
    }
}

Solution 1 (with ajax)

private HtmlCommandButton createCommandButtonWithAjax(final FacesContext context,
        final String methodExpression, final String value) {

    Application application = context.getApplication();
    Class<?>[] clazz = new Class<?>[]{};
    HtmlCommandButton htmlCommandButton =
            (HtmlCommandButton) application.createComponent(HtmlCommandButton.COMPONENT_TYPE);
    htmlCommandButton.setValue(value);

    AjaxBehavior ajaxBehavior = (AjaxBehavior) FacesContext.getCurrentInstance().getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);
    ((UIComponentBase)htmlCommandButton).addClientBehavior("click", ajaxBehavior);

MethodExpression actionListener = application.getExpressionFactory().createMethodExpression(FacesContext.getCurrentInstance().getELContext(), action, String.class, clazz);
button.addActionListener(new MethodExpressionActionListener(actionListener));

    return htmlCommandButton;
}

Solution 2 (no ajax)

private HtmlCommandButton createCommandButton(final FacesContext context,
        final String methodExpression, final String value) {
    Application application = context.getApplication();
    Class<?>[] clazz = new Class<?>[]{};
    HtmlCommandButton htmlCommandButton =
            (HtmlCommandButton) application.createComponent(HtmlCommandButton.COMPONENT_TYPE);
    htmlCommandButton.setValue(value);
    htmlCommandButton.setActionExpression(JSFUtils.createMethodExpression(methodExpression, String.class, clazz));
    return htmlCommandButton;
}

Calling code:

createCommandButton(FacesContext.getCurrentInstance(),
                "#{commandBean.generateUUID()}", "Generate UUID");

JSFUtils:

  public static MethodExpression createMethodExpression(String methodExpression,Class<?> expectedReturnType,Class<?>[] expectedParamTypes) {
    FacesContext context = FacesContext.getCurrentInstance();
    return context.getApplication().getExpressionFactory()
            .createMethodExpression(context.getELContext(), methodExpression, expectedReturnType, expectedParamTypes);
  }

Solution 1 is working, solution 2 not: the bean method generateUUID() is not called. I have tried also with htmlCommandButton.setImmediate(true) to exclude validation errors.


回答1:


Apparently we need a Custom AjaxBehavior, as suggested here: https://forum.primefaces.org/viewtopic.php?f=3&t=5344 and here How to programmatically add an AjaxBehavior to a UIComponent with primefaces

Custom Ajax:

import java.util.HashMap;
import javax.el.ELContext;
import javax.el.MethodExpression;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.BehaviorEvent;

public class MyAjaxBehavior extends AjaxBehavior{


  @Override
  public Object saveState(FacesContext context) {
    HashMap<String, Object> map;
    map = new HashMap<String, Object>();
    map.put( "update", getUpdate() );
    map.put( "process", getProcess() );
    map.put( "oncomplete", getOncomplete() );
    map.put( "onerror", getOnerror() );
    map.put( "onsuccess", getOnsuccess() );
    map.put( "onstart", getOnstart() );
    map.put( "listener", getListener() );

    if (initialStateMarked()) return null;
    return UIComponentBase.saveAttachedState(context, map);

  }

  @SuppressWarnings("unchecked")
  @Override
  public void restoreState(FacesContext context, Object state) {
    if (state != null){
      HashMap<String, Object> map;
      map = (HashMap<String, Object>) UIComponentBase.restoreAttachedState(context, state);

      setUpdate( (String) map.get( "update" ));
      setProcess( (String) map.get( "process"));
      setOncomplete( (String) map.get( "oncomplete" ));
      setOnerror( (String) map.get( "onerror" ));
      setOnsuccess( (String) map.get( "onsuccess" ));
      setOnstart( (String) map.get( "onstart" ));
      setListener( (MethodExpression) map.get( "listener" ));
    }

  }

  @Override
  public void broadcast(BehaviorEvent event) throws AbortProcessingException {
    ELContext eLContext = FacesContext.getCurrentInstance().getELContext();

//Backward compatible implementation of listener invocation
    if(getListener() != null) {
      try {
        getListener().invoke(eLContext, new Object[]{event});
      } catch(IllegalArgumentException exception) {
        getListener().invoke(eLContext, new Object[0]);
      }
    }
  }

}

Create Button

    private HtmlCommandButton createCommandButtonWithAjax(final FacesContext context,
        final String methodExpression, final String value) {

    Application application = context.getApplication();
    Class<?>[] clazz = new Class<?>[]{};
    HtmlCommandButton htmlCommandButton =
            (HtmlCommandButton) application.createComponent(HtmlCommandButton.COMPONENT_TYPE);
    htmlCommandButton.setValue(value);

    addPrimefacesAjaxSupport(htmlCommandButton,"click", methodExpression);

    return htmlCommandButton;
}

add AjaxBehavior

  private AjaxBehavior addPrimefacesAjaxSupport(UIComponentBase comp, String event, String actionListener){

    MyAjaxBehavior ajaxBehavior = new MyAjaxBehavior();
    ajaxBehavior.setListener( JSFUtils.createMethodExpression(actionListener, void.class,new Class[]{ ActionEvent.class}) );
    ajaxBehavior.setProcess( "@this" );
    comp.addClientBehavior( event, ajaxBehavior );

    return ajaxBehavior;
  }


来源:https://stackoverflow.com/questions/47589580/jsf-htmlcommandbutton-programmatically-bean-method-not-called-if-ajax-turned-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!