Solucionado (ver solução)
Solucionado
(ver solução)
18
respostas

Dúvida no Ex. 3 da Aula 7 - Validação e integração com Bean Validation

Ao anotar o Produto com @Valid no método adiciona do ProdutoController e anotar o atributo quantidade do modelo com apenas @Min(value=0), de onde vem a mensagem?

18 respostas

Olá Josué! Toda anotação do bean validation tem uma mensagem padrão, definida em um arquivo Validations.properties do próprio jar da implementação (em nosso caso, hibernate-validator). No exercício seguinte, inclusive, você deve ter personalizado essas mensagens, para exibir em português. Tudo correu bem? Um abraço

Sim, mas eu recebi uma mensagem em português. Isso foi devido ao meu browser estar configurado para português?

Outra dúvida foi que quando eu setei o @Min(value=10) tomei uma exception do hibernate. (agora não lembro qual exatamente)

Pode me dizer mais sobre isso?

Ah, sim, exatamente! Por padrão, ele uso o Locale do seu navegador para internacionalizar as mensagens. Nas versões mais novas, já existe um arquivo de propriedades em pt_BR (bem legal, né?). Quanto ao erro do @Min, precisaria ver a mensagem mesmo, mas normalmente ele dá erro quando você anota em algum tipo não numérico (exemplo uma String). Faz sentido?

Sua explicação sobre o @Min faz sentido, porem o campo é int. A noite vou tentar simular o erro novamente e volto a postar aqui. Tudo bem?

Muito obrigado até aqui! =)

Claro! Se der erro, mande a stacktrace que com certeza acharemos uma explicação juntos. Um abraço

Rodrigo, quando anoto o atributo quantidade desta forma:

@Min(value=10, message="{produto.quantidade.negativa}")
    private Integer quantidade;

Recebo a seguinte stacktrace ao tentar restartar o server:

GRAVE: Exception starting filter vraptor
javax.validation.ConstraintViolationException: Validation failed for classes [br.com.caelum.vraptor.model.Produto] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='Não pode cadastrar um produto com quantidade negativa', propertyPath=quantidade, rootBeanClass=class br.com.caelum.vraptor.model.Produto, messageTemplate='{produto.quantidade.negativa}'}
]
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:160)
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:95)
    at org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:202)
    at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:91)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:480)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:191)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:175)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:210)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:780)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
    at br.com.caelum.vraptor.observers.InitialDataObserver.insert(InitialDataObserver.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:93)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:266)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:253)
    at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:232)
    at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:169)
    at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:165)
    at org.jboss.weld.event.ObserverNotifier.notifyObservers(ObserverNotifier.java:119)
    at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:112)
    at org.jboss.weld.event.EventImpl.fire(EventImpl.java:83)
    at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:92)
    at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:279)
    at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:260)
    at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:105)
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4573)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5192)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3746)
    at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:292)
    at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5527)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1378)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1382)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1382)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1350)
    at java.lang.Thread.run(Thread.java:745)

Josué, confere se você tem um arquivo src/main/resources/META-INF/validation.xml, e que nele tem a linha <executable-validation enabled="false"/>? Além disso, confere se no seu controller tem um validatior.onError...?

Meu validation.xml tem a tag que vc falou.

<?xml version="1.0" encoding="UTF-8"?>

<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.1.xsd"
        version="1.1">
    <executable-validation enabled="false"/>
</validation-config>

E o meu controller:

@Post
    public void adiciona(@Valid Produto produto){
        //validator.check(produto.getQuantidade() > 0, new I18nMessage("erro", "produto.quantidade.negativa"));
        validator.onErrorUsePageOf(this).formulario();

        dao.adiciona(produto);
        result.include("mensagem","Produto adicionado com sucesso!");
        result.redirectTo(this).lista();
    }

Que estranho. Qual o import da sua anotação @Min? É do javax.validation.constraints.Min mesmo?

import javax.validation.constraints.Min;

Josué, as demais anotações estão funcionando sem nenhum problema?

A @NotNull e @NotEmpty funcionam.

A @Min também funciona, porem só funciona com o "value=0".

Quando eu mudo para: @Min(value=10, message="{produto.quantidade.negativa}") private Integer quantidade;

Acontece a exception:

javax.validation.ConstraintViolationException: Validation failed for classes [br.com.caelum.vraptor.model.Produto] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='Valor do produto não pode ser negativo', propertyPath=valor, rootBeanClass=class br.com.caelum.vraptor.model.Produto, messageTemplate='{produto.valor.negativo}'}
]
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:160)
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:95)
    at org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:202)
    at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:91)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:480)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:191)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:175)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:210)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:780)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
    at br.com.caelum.vraptor.observers.InitialDataObserver.insert(InitialDataObserver.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:93)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:266)
    at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:253)
    at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:232)
    at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:169)
    at org.jboss.weld.event.ObserverNotifier.notifyObserver(ObserverNotifier.java:165)
    at org.jboss.weld.event.ObserverNotifier.notifyObservers(ObserverNotifier.java:119)
    at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:112)
    at org.jboss.weld.event.EventImpl.fire(EventImpl.java:83)
    at br.com.caelum.vraptor.VRaptor.init(VRaptor.java:92)
    at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:279)
    at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:260)
    at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:105)
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4573)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5192)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3746)
    at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:292)
    at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5527)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1378)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1382)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1382)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1350)
    at java.lang.Thread.run(Thread.java:745)

Josué, você consegue compartilhar esse código comigo (via dropbox ou algo do tipo?) Se puder, me envie por e-mail em rodrigo.turini@caelum.com.br.

Olá Rodrigo!!

Enviei como solicitado para o seu e-mail.

Grato pela ajuda!

Oi Josué! Recebi seu projeto e acabei de testar, curiosamente está funcionando:

http://pasteboard.co/pioJXfD.png

Deve ser algo relacionado ao ambiente. Qual sistema operacional você usa?

Tente dar um clean no projeto e importar para o eclipse de novo.

Rodrigo, ele funciona para valores negativos desde que a anotação esteja com o value=0.

Tente colocar o @Min(value=5) por exemplo e veja se vai compilar.

Meu sistema é Ubuntu 14. Já fiz clean no projeto e não resolveu.

solução!

Oi Josúe, entendi! Fiz um teste sem VRaptor e também deu erro, tudo indica que é um bug no hibernate validator. Vou pesquisar um pouco mais e se for o caso abrir uma issue pra eles. Enquanto isso, como workaround você pode fazer essa validação via API do VRaptor:

validator.check(quantidade < 5, umaMensagem);

Valeu Rodrigo!

Obrigado pelas dicas e pela atenção.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software