I have developed a simple login form to be used in my JSF + PrimeFaces page:
<form action="j_security_check" method="post">
<p:dialog modal="true" header="Login" widgetVar="loginDlg">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="j_username">Username:</h:outputLabel>
<h:inputText id="j_username" required="true" />
<h:message for="j_username" />
<h:outputLabel for="j_password">Password:</h:outputLabel>
<h:inputSecret id="j_password" required="true" />
<h:message for="j_password" />
<br />
<h:commandButton value="Login" />
</h:panelGrid>
</p:dialog>
</form>
Tried with an empty password, but the missing password (that is required) is not caught by h:message
component. I have also switched to a p:commandButton
thinking that the problem could have been in the Ajax behaviour of the button, but the page is not rendered because PrimeFaces complains about the CommandButton not being inside a form element. The exception thrown by the container is:
com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Access denied on empty password for user pippo
To summarize, I have 2 questions:
- Why the missing password doesn't produce a message before the form is submitted?
- How can I catch a LoginException and display the error message inside the dialog?
The
j_security_check
request is handled by the web container, not by JSF. That explains that therequired="true"
won't work. It works only when you use JSF<h:form>
and programmatic login byHttpServletRequest#login()
in the action method associated with the command button.Best what you can do is to confiure a
<form-error-page>
inweb.xml
pointing to the very same URL as the<form-login-page>
. You could then check if the request has been forwarded byj_security_check
itself, which would mean that a login error has occurred.Use this instead of the
<h:message>
.As to why
<p:commandButton>
complains that there's no form is simply because you didn't use<h:form>
.Unrelated to the concrete problem, that
<form>
(or<h:form>
whenever you would decide to switch to programmatic login) can better be placed in the body of<p:dialog>
, not outside. The<p:dialog>
can by JS be relocated to end of body which would cause it not to be in a form anymore.