Definitely a very interesting approach; one problem is that it'll
validate too much. For example, it'll validate beans that aren't
even used on the current page. It'll also validate beans that
aren't yet valid because they're being created and populated
over multiple pages, and beans that weren't set on this request
because they're in a different form (or subform) than the one
that was submitted.
The interesting question is how to tie an annotation
driven approach like this - which I really like - to all of
the information resident in the UIComponent tree.
-- Adam
On 3/13/06, Barry Kaplan <[EMAIL PROTECTED]> wrote:
> A few days there was a thread on using Hibernate Validator. Here is a
> quick prototype. I've only played with a tiny bit, so I'm sure there are
> issues:
>
> -barry
>
> ----
>
> package org.opentrader.infra.jsf.validation;
>
> import java.util.Collection;
> import java.util.Map;
>
> import javax.faces.application.FacesMessage;
> import javax.faces.context.ExternalContext;
> import javax.faces.context.FacesContext;
> import javax.faces.event.PhaseEvent;
> import javax.faces.event.PhaseId;
> import javax.faces.event.PhaseListener;
>
> import org.hibernate.validator.InvalidValue;
> import org.opentrader.infra.validation.BeanValidator;
> import org.opentrader.infra.validation.ValidatedBean;
> import org.springframework.context.ApplicationContext;
> import org.springframework.web.jsf.WebApplicationContextVariableResolver;
>
> // TODO Test and harden this spike.
> public class HibernateValidatorPhaseListener implements PhaseListener {
>
> private BeanValidator beanValidator;
>
> public PhaseId getPhaseId() {
> return PhaseId.PROCESS_VALIDATIONS;
> }
>
> public void beforePhase(PhaseEvent arg0) {
> //empty
> }
>
> public void afterPhase(PhaseEvent event) {
> FacesContext facesContext = event.getFacesContext();
> ExternalContext externalContext = facesContext.getExternalContext();
> BeanValidator validator = getValidator(externalContext);
> processValidators(externalContext.getRequestMap(), facesContext,
> validator);
> processValidators(externalContext.getSessionMap(), facesContext,
> validator);
> }
>
> @SuppressWarnings("unchecked")
> private BeanValidator getValidator(ExternalContext externalContext) {
> if (beanValidator == null) {
> ApplicationContext context = (ApplicationContext)
> externalContext.getApplicationMap().get(
>
> WebApplicationContextVariableResolver.WEB_APPLICATION_CONTEXT_VARIABLE_NAME);
> Map<String, BeanValidator> beans =
> context.getBeansOfType(BeanValidator.class);
> if (beans.size() == 0) {
> throw new IllegalStateException("Bean of class
> BeanValidator not found in application-context");
> }
> if (beans.size() == 0) {
> throw new IllegalStateException("More than one bean of
> class BeanValidator found in application-context: beans=" + beans.keySet());
> }
> beanValidator = beans.values().iterator().next();
> }
> return beanValidator;
> }
>
> private void processValidators(Map scope, FacesContext facesContext,
> BeanValidator validator) {
> Collection collection = scope.values();
> for (Object object : collection) {
> if
> (object.getClass().isAnnotationPresent(ValidatedBean.class)) {
> InvalidValue[] invalidValues =
> validator.validateBean(object);
> if (invalidValues.length > 0) {
> addFacesMessages(invalidValues, facesContext);
> }
> }
> }
> }
>
> private void addFacesMessages(InvalidValue[] invalidValues,
> FacesContext facesContext) {
> for (InvalidValue invalidValue : invalidValues) {
> FacesMessage message = new FacesMessage();
> message.setSeverity(FacesMessage.SEVERITY_ERROR);
> message.setSummary(invalidValue.toString());
> message.setDetail(invalidValue.toString());
> facesContext.addMessage(null, message);
> }
> }
>
> }
>
>
>