Событие составного компонента Sink JSF 2.0 в компоненте поддержки родительской страницы - PullRequest
0 голосов
/ 27 октября 2010

У меня есть концептуальный умственный блок вокруг использования составного компонента JSF 2.0 на родительской странице.Я понимаю, как реализовать ActionListener (и другие) для действия составного компонента, но как использовать эту привязку для родительской страницы?Например, я хочу, чтобы мой составной компонент входа в систему выполнил аутентификацию, и когда она будет завершена, сообщите компоненту поддержки родительской страницы через событие (ActionListener?), Чтобы выполнить некоторую работу по инициализации пользовательского интерфейса.Ключевым моментом здесь является то, что компонент входа в систему скажет: «Эй, я закончил, и пользователь в порядке. Ваша очередь».

Заранее благодарен за помощь.

Мир.

Крис

1 Ответ

0 голосов
/ 30 января 2011

Я обнаружил, что вы можете сделать это одним из способов, используя составной компонент + пользовательский тип компонента + 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>

Этот тип компонента является классом Java, который реализует NamingContainer (UINamingContainer является подклассом компонента, реализующего этот интерфейс). Затем вам нужно реализовать ActionSource2, чтобы вы могли генерировать событие действия при проверке пользователя.

Проверка должна быть после того, как компоненты пользователя и пароля были проверены (не ваша проверка, а JSF PROCESS VALIDATIONS). Чтобы узнать, когда произошла проверка, мы используем системные события.

Это пример кода для пользовательского компонента. Класс реализует методы интерфейса ActionSource2 и переопределяет широковещательную передачу для обработки ActionEvent. Я использую некоторые конкретные классы в Мохарре (потому что наследие между 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}"/>
...