dúvida sobre as transações no VRaptor 3

Boa Tarde,

Alguém poderia me explicar como funciona as transações do EntityManager(begin, commit, rollback) no Vraptor 3? Sei que por default o Vraptor tem os métodos anotados @PostConstruct e @PreDestroy. Não criei minha classe de JPAUtil onde crio os entityManager, apenas coloquei-as no web.xml, dessa forma não sei como trabalhar isso pois estou tendo problemas por não saber direito o estado no meu objeto.

web.xml

<context-param>
	    <param-name>br.com.caelum.vraptor.packages</param-name>
	    <param-value>br.com.caelum.vraptor.util.jpa</param-value>
	</context-param>

Estou tendo um erro na hora de cadastrar a Entidade Operador

javax.persistence.RollbackException: Error while committing the transaction
	org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93)
	br.com.caelum.vraptor.util.jpa.JPATransactionInterceptor.intercept(JPATransactionInterceptor.java:53)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:89)
	br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:23)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
root cause

javax.validation.ConstraintViolationException: validation failed for classes [br.org.cemaden.bean.Operador] during persist time for groups [javax.validation.groups.Default, ]
	org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:155)
	org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:94)
	org.hibernate.action.EntityInsertAction.preInsert(EntityInsertAction.java:178)
	org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:72)
	org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
	org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
	org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
	org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
	org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
	org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
	org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
	org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
	org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
	br.com.caelum.vraptor.util.jpa.JPATransactionInterceptor.intercept(JPATransactionInterceptor.java:53)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:89)
	br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:23)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)

OperadorController

@Post
	@Path("/novo")
	public void adiciona(Operador operador, String msg) throws Exception{

		carregaListaGrupo();
		
		Validacao val = new Validacao(validator);
		val.validaOperador(operador);
		validator.onErrorUsePageOf(OperadorController.class).novo();
		
	
		pdao.adiciona(operador);
		
		this.result.include("message",msg);
		result.redirectTo(this).novo();

	}

DAO.java

public class DAO<T> {

	private final Class<T> classe;
	private final EntityManager em;

	public DAO(EntityManager em, Class<T> classe) {
		this.em = em;
		this.classe = classe;
	}
	
	public void adiciona(T t) {
		this.em.persist(t);
	}
}

OperadorDAO.java


@Component
public class OperadorDAO {
	
	private DAO<Operador> dao;
	private EntityManager em;

	public OperadorDAO(EntityManager em) {
		this.em = em;
		dao = new DAO<Operador>(em,Operador.class);
	}
	
	public void adiciona(Operador t){
		dao.adiciona(t);
	}
@NamedQueries({
		@NamedQuery(name = "Operador.listaOperador", query = "SELECT o FROM Operador o ORDER BY o.idoperador"),
		@NamedQuery(name = "Operador.existeOperadorNoGrupo", query = "SELECT o FROM Operador o WHERE o.grupo.idgrupo = :id")
})

@Entity
@Table(name="operador")
public class Operador {
	
	@Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "id_operador") 
    private int idoperador;
	
	@ManyToOne
	@JoinColumn(name="id_grupo")
	private Grupo grupo;
	
	@Column(name="nome", length=60)
	@NotNull
	private String nome;
	
	@Column(name="email", length=60)
	@NotNull
	private String email;
	
	@Column(name="ramal", length=4)
	@Null
	private String ramal;
	
	@Column(name="telefone", length=14)
	@Null
	private String telefone;
	
	@Column(name="celular", length=14)
	@Null
	private String celular;
	
	@OneToMany(mappedBy="operador", fetch = FetchType.LAZY)
	@Cascade(CascadeType.ALL)
	private Collection<Gerente> gerente;
	
	public int getIdoperador() {
		return idoperador;
	}
	public void setIdoperador(int idoperador) {
		this.idoperador = idoperador;
	}
	public Grupo getGrupo() {
		return grupo;
	}
	public void setGrupo(Grupo grupo) {
		this.grupo = grupo;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getRamal() {
		return ramal;
	}
	public void setRamal(String ramal) {
		this.ramal = ramal;
	}
	public String getTelefone() {
		return telefone;
	}
	public void setTelefone(String telefone) {
		this.telefone = telefone;
	}
	public String getCelular() {
		return celular;
	}
	public void setCelular(String celular) {
		this.celular = celular;
	}
	public void setGerente(Collection<Gerente> gerente) {
		this.gerente = gerente;
	}
	public Collection<Gerente> getGerente() {
		return gerente;
	}	
}

@NamedQueries(
		@NamedQuery(name = "Grupo.listaGrupo", query = "SELECT g FROM Grupo g ORDER BY g.idgrupo")
)

@Entity
@Table(name="grupo")
public class Grupo {
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="id_grupo")
	private int idgrupo;
	
	@Column(name="nome", length=60)
	@NotNull
	private String nome;
	
	@OneToMany(mappedBy="grupo", fetch = FetchType.LAZY)
	@Cascade(CascadeType.ALL)
	private Collection<Gerente> gerente;
	
	public Collection<Gerente> getGerente() {
		return gerente;
	}
	public void setGerente(Collection<Gerente> gerente) {
		this.gerente = gerente;
	}
	public int getIdgrupo() {
		return idgrupo;
	}
	public void setIdgrupo(int idgrupo) {
		this.idgrupo = idgrupo;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}

Muito obrigado

Cara, dá uma olhada no interceptor que cuida das transações:

https://github.com/caelum/vraptor/blob/master/vraptor-core/src/main/java/br/com/caelum/vraptor/util/jpa/JPATransactionInterceptor.java

Mas acho que o problema não é com a transação.

Quando você comita, seu código parece estar violando alguma regra relacional das entidades.

Verifique se o “grupo” está presente no objeto “operador”. Veja se o id do grupo está correto etc.

bronx,

Os relacionamentos estão OK, pois eu tava fazendo usando a session do hibernate e tava funcionando certinho. Porém resolvi mudar pra usar a JPA.

o problema:
javax.validation.ConstraintViolationException: validation failed for classes [br.org.cemaden.bean.Operador] during persist time for groups [javax.validation.groups.Default, ]

deu erro de validação…

vc tá chamando o validator.validate(objeto); ??

é isso mesmo Lucas, ele tá dando erro no meu pacote “package br.org.cemaden.util;” onde está minha classe “Validator” e está mandando configurar a build path. Mas olhei e está tudo OK. Nenhuma biblioteca aparentemente está com erro, e já exclui e coloquei o jar do vraptor novamente mas nada…Será que pode ser algum outro jar que esteja conflitando com o jar do vraptor 3? Pq essa classe funcionava normal…

Segue a classe

package br.org.cemaden.util; //o erro está aqui

import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.Validations;
import br.org.cemaden.bean.Gerente;
import br.org.cemaden.bean.Grupo;
import br.org.cemaden.bean.Operador;
import br.org.cemaden.dao.DAO;

public class Validacao {

	private Validator validator;

	public Validacao(Validator validator) {
		this.validator = validator;
	}

	public Grupo validaGrupo(final Grupo grupo) {

		this.validator.checking(new Validations() {
			{
				that(!grupo.getNome().isEmpty(), "Error", "grupo.nome.invalido");
			}
		});
		return grupo;
	}

	public Operador validaOperador(final Operador operador) {

		validator.checking(new Validations() {
			{
				that(!operador.getNome().isEmpty(), "Error",
						"operador.nome.invalido");
				that(!operador.getEmail().isEmpty(), "Error",
						"operador.email.invalido");
			}
		});
		return operador;
	}

	public Gerente validaGerente(final Gerente gerente) {

		validator.checking(new Validations() {
			{
				that(!(gerente.getGrupo().getIdgrupo() == 0), "Error",
						"gerente.grupo.invalido");
				that(!gerente.getSenha().isEmpty(), "Error",
						"gerente.senha.invalido");
				// that(!gedao.existeGerente(gerente),
				// "Error","gerente.existe.invalido");
			}
		});
		return gerente;
	}

}

Consegui arrumar o lance do erro no pacote adicionando o jar hamcrest-all-1.2RC3.jar . A validação está OK.

No entanto, continua o mesmo erro…acima :frowning:

tente chamar o validator.validate passando esses objetos

Perfeito Lucas,

Qnd usei o validator.validate(objeto) ele usa a validação do Hibernate, aí pude perceber que havia anotado alguns campos com @Null, com essa anotação o campo deveria ser vazio. Foi só tirar a anotação que deu certo. Voltei até a usar a validação do VRaptor.

Muito obrigado.

Abs