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