父页面支持Bean中的JSF 2.0复合组件事件

时间:2010-10-27 15:28:49

标签: events jsf notifications composite-component

我在父页面中使用JSF 2.0复合组件时有一个概念性的思维模块。我理解如何为复合组件的操作实现ActionListener(和其他),但是如何为父页面使用这些连线?例如,我希望我的登录复合组件执行身份验证,完成后,通过一个事件(ActionListener?)通知父页面的辅助bean来执行一些UI初始化工作。这里的关键是登录组件会说,“嘿,我已经完成了,用户也很好。轮到你。”

提前感谢您的帮助。

和平。

克里斯

1 个答案:

答案 0 :(得分:0)

我发现你可以实现的一种方法是使用复合组件+自定义组件类型+ ActionSource2 +系统事件

在复合集的接口中有一个组件类型(当没有定义时,实现(Mojarra或MyFaces)使用默认的组件类型。

<cc:interface componentType="example.Login">
  <cc:attribute name="text" type="java.lang.String"/>
  <cc:attribute name="actionExpression" method-signature="void method()"/>
</cc:interface>

<cc:implementation>
    <p>
      <h:outputLabel value="User"/>
      <h:inputText id="user"/>
    </p>
    <p>
      <h:outputLabel value="Password"/>
      <h:inputSecret id="password"/>
    </p>
</cc:implementation>

此组件类型是实现NamingContainer的java类(UINamingContainer是实现此接口的组件的子类)。接下来,您必须实现ActionSource2,以便在验证用户时生成操作事件。

验证必须在验证用户和密码组件之后(不是您的验证,而是JSF PROCESS VALIDATIONS)。为了知道验证何时发生,我们使用系统事件。

这是自定义组件的代码示例。该类实现ActionSource2接口的方法并覆盖广播以处理ActionEvent。我在Mojarra中使用了一些特定的类(因为ActionSource和ActionSource2之间存在遗留问题)。

 @FacesComponent("example.Login") //Component type in the composite
@ListenerFor(systemEventClass=PostValidateEvent.class) //Event to listen for user and password verification
public class LoginComponent extends UINamingContainer implements  ActionSource2{

    @Override
    public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
        if(event instanceof PostValidateEvent){
            System.out.println("post validate");
        }
        super.processEvent(event);
        String user=(String) ((HtmlInputText)findComponent("user")).getValue();
        String password=(String) ((HtmlInputSecret)findComponent("password")).getValue();
        System.out.println("user: "+user);
        System.out.println("password: "+password);
        //a simple logic for verification
        if(user != null && user.equals("victor") && password != null && password.equals(user)){
            System.out.println("user ok");
            queueEvent(new ActionEvent(this));
        }
    }


    private MethodExpression exp;

    @Override
    public MethodExpression getActionExpression() {
        return exp;
    }

    @Override
    public void setActionExpression(MethodExpression action) {
        exp=action;
    }

    @Override
    public MethodBinding getAction() {
        return exp != null ? new MethodBindingMethodExpressionAdapter(exp): null;
    }

    @Override
    public void setAction(MethodBinding action) {
        setActionExpression(new MethodExpressionMethodBindingAdapter(action));
    }

    private MethodBinding actionListener;

    @Override
    public MethodBinding getActionListener() {
        return actionListener;
    }

    @Override
    public void setActionListener(MethodBinding actionListener) {
        this.actionListener=actionListener;
    }

    private boolean i;

    @Override
    public boolean isImmediate() {
        return i;
    }

    @Override
    public void setImmediate(boolean immediate) {
        this.i=immediate;
    }

    List<ActionListener> listeners=new LinkedList<ActionListener>();

    @Override
    public void addActionListener(ActionListener listener) {
        listeners.add(listener);
    }

    @Override
    public ActionListener[] getActionListeners() {
        return listeners.toArray(new ActionListener[0]);
    }

    @Override
    public void removeActionListener(ActionListener listener) {
        listeners.remove(listener);
    }

    @Override
     public void broadcast(FacesEvent event) throws AbortProcessingException {
        super.broadcast(event);

        if (event instanceof ActionEvent) {
            FacesContext context = getFacesContext();
            MethodBinding binding = getActionListener();
            if (binding != null) {
                binding.invoke(context, new Object[] { event });
            }

            ActionListener listener = context.getApplication().getActionListener();
            if (listener != null) {
                listener.processAction((ActionEvent) event);
            }
        }
    }

}

这是使用页面中的代码:

<ez:login actionExpression="#{bean.logged}"/>