vraptor3 + DaoFactory + controle de transação

23 respostas
R

Estou com uma duvida, seguindo apostilas e forum e percebi que não estou utilizando o DaoFactory para controle de transação e esta funcionando normalmente no vraptor 3, mas na teoria eu ñ deveria ter um interceptador?

Acho q com as classes fica melhor pra entender…

@Resource
public class UsuarioController {

private final UsuarioDao dao;
private final Result result;

public UsuarioController(UsuarioDao dao, Result result) {
    this.dao = dao;
    this.result = result;
}
public void adiciona (Usuario usuario) {
	  
	  this.dao.adiciona(usuario);
	  result.use(logic()).redirectTo(UsuarioController.class).lista();
}

//@Path("/lista")
public void lista () {
	
	List<Usuario> usuarioList = this.dao.listaTudo();
	result.include("users", usuarioList);
}

public void formulario() {
}

}

@Component

public class UsuarioDao extends Dao {

public UsuarioDao(Session session) {

super(session, Usuario.class);

}

}

Não devira ter um classe assim??

@RequestScoped
@Intercepts
public class DaoInterceptor implements Interceptor {

private final DaoFactory factory;


public DaoInterceptor (DaoFactory factory){
	this.factory = factory;
}

public void intercept(InterceptorStack stack, ResourceMethod method,
        Object instance) throws InterceptionException {
	try {
		factory.beginTransaction();
		stack.next(method, instance);
		factory.commit();
	}finally {
        if (factory.hasTransaction()) {
        	factory.rollback();
        }
        factory.close();
    }
}
	
public boolean accepts(ResourceMethod method) {
    return true;
}

}

e como implementar ela no Controller?

Obrigado

23 Respostas

Lucas_Cavalcanti

como vc tá criando essa Session? vc registrou o HibernateCustomProvider? vc registrou na mão um cara chamado HibernateTransactionInterceptor no CustomProvider?

se sim, tem um cara do vraptor que controla a transação pra vc…

o que vc quer implementar no controller? controle de transações?

R

Então Lucas não sei se to juntando 2 coisas e isso ta gerando o erro… na verdade eu queria fazer exatamente o que esta nesse artigo

Alterei minha classes e deixei ativo no web.xml o HibernateCustomProvider na verdade um ta gerando conflito com outro? … segue a erro

org.hibernate.TransactionException: Transaction not successfully started

org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:131)

br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:46)

br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41)

br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)

br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)

br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)

br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)

br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)

br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)

br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)

br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)

br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)

br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)

br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)

br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)

br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)

br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

Obrigado

G

rodrigoswp, não é necessário fazer isso. O Vraptor já faz para você bastando registrar o HibernateCustomProvider ou, se você usa JPA, JPACustomProvider.

R

Obrigado Garcia, desativei e funcionou!

luis.fernandez

Fala rodrigoswp,

Tô iniciando no desenvolvimento VRaptor…
Estou tendo o mesmo problema que vc estava tendo

Não entendi o que vc desativou.
Pode me dar um help.

Abcs
Luis Fernandez

Lucas_Cavalcanti

Vc já deu uma olhada na apostila do VRaptor?
http://www.caelum.com.br/curso/fj-28-vraptor-hibernate-ajax/

lá tem isso passo a passo

luis.fernandez

Ôpa Lucas,

Estou seguindo a apostila, passo a passo. Será que pode ser alguma incompatibilidade com o JBoss 4.2.3 GA (conflito de bibliotecas)?

web.xml

<display-name>goodbuy</display-name>

	<context-param>
		<param-name>br.com.caelum.vraptor.packages</param-name>
		<param-value>br.com.caelum.goodbuy</param-value>
	</context-param>
	
	<context-param>
		<param-name>br.com.caelum.vraptor.provider</param-name>
		<param-value>br.com.caelum.vraptor.util.hibernate.HibernateCustomProvider</param-value>
	</context-param>

	<filter>
		<filter-name>vraptor</filter-name>
		<filter-class>br.com.caelum.vraptor.VRaptor</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>vraptor</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>

ProdutoDAO.java

@Component
public class ProdutoDAO {

	private Session session;

	public ProdutoDAO(Session session) {
		this.session = session;
	}

	public void salvar(Produto produto) {

		Transaction tx = session.beginTransaction();
		tx.begin();
		session.save(produto);
		tx.commit();
	}
// restante do código
}

Se eu incluo esse SessionCreator …

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.ComponentFactory;

@Component
public class CriadorDeSession implements ComponentFactory<Session>{

	@Override
	public Session getInstance() {
		AnnotationConfiguration configuration = new AnnotationConfiguration();
		configuration.configure();
		SessionFactory factory = configuration.buildSessionFactory();
		Session session = factory.openSession();
		return session;
	}
}

Acontece isso, que parece ser um conflito do SessionCreator que a apostila está indicando para incluir com algum já existente…

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hibernateTransactionInterceptor': Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.Session]: : No unique bean of type [org.hibernate.Session] is defined: expected single matching bean but found 2: [br.com.caelum.vraptor.util.hibernate.SessionCreator, br.com.caelum.goodbuy.infra.CriadorDeSession]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.Session] is defined: expected single matching bean but found 2: [br.com.caelum.vraptor.util.hibernate.SessionCreator, br.com.caelum.goodbuy.infra.CriadorDeSession]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:698)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:984)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:886)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	at org.springframework.beans.factory.support.AbstractBeanFactory$2.getObject(AbstractBeanFactory.java:328)
	at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:43)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:385)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:375)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1069)
	at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:221)
	at br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:240)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:58)
	at br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:32)
	at br.com.caelum.vraptor.util.collections.Functions$1.apply(Functions.java:30)
	at com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:431)
	at java.util.AbstractList$Itr.next(Unknown Source)
	at com.google.common.collect.Iterators$7.computeNext(Iterators.java:602)
	at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:135)
	at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:130)
	at com.google.common.collect.Lists.newArrayList(Lists.java:131)
	at com.google.common.collect.Collections2$FilteredCollection.toArray(Collections2.java:219)
	at br.com.caelum.vraptor.interceptor.DefaultInterceptorRegistry.interceptorsFor(DefaultInterceptorRegistry.java:50)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:42)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:48)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
	at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.Session] is defined: expected single matching bean but found 2: [br.com.caelum.vraptor.util.hibernate.SessionCreator, br.com.caelum.goodbuy.infra.CriadorDeSession]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:772)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:680)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:771)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:691)
	... 58 more

Já fucei tudo que podia. Estou com um pouco de dificuldade por não ter experiêcia com Hibernate.

Desde já agradeço a ajuda!

Lucas_Cavalcanti

Se você está seguindo a apostila, e usando o vraptor 3.1, você pode remover as configurações:

<context-param>
		<param-name>br.com.caelum.vraptor.packages</param-name>
		<param-value>br.com.caelum.goodbuy</param-value>
	</context-param> <!-- não precisa mais no vraptor 3.1 -->
	
	<context-param>
		<param-name>br.com.caelum.vraptor.provider</param-name>
		<param-value>br.com.caelum.vraptor.util.hibernate.HibernateCustomProvider</param-value>
	</context-param> <!-- se vc segue a apostila, as classes que estão registradas no provider acima são criadas durante o curso -->
     <!-- então ou tira essa configuração, ou remove as classes CriadorDeSession  e CriadorDeSessionFactory -->
luis.fernandez

Fiz as configurações que vc indicou e continua dando esse erro. Detalhe: o registro é inserido no banco normalmente.

org.hibernate.TransactionException: Transaction not successfully started org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:131) br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:46) br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:41) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67) br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46) br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59) br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62) br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91) br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55) br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:8

Eu mantive HibernateCustomProvider no web.xml e retirei a configuração do “br.com.caelum.vraptor.packages” e as classes CriadorDeSession e CriadorDeSessionFactory conforme sua orientação.

Vou fazer uma gambiarra pra continuar os estudos, mas se puder me ajudar a corrigir o erro eu ficaria muito grato.

Abcs.

Lucas_Cavalcanti

que banco vc tah usando?

luis.fernandez

MySQL 5.1

hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/goodbuy</property>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
		<property name="hibernate.hbm2ddl.auto">update</property>
		<property name="show_sql">false</property>
		<property name="format_sql">true</property>
		
		<mapping class="br.com.caelum.goodbuy.model.Produto" />
	</session-factory>
</hibernate-configuration>
Lucas_Cavalcanti

Existe alguma parte do seu código que está abrindo e commitando transações? Se tiver, tire

luis.fernandez

Funcionou!!!

Estava assim:

public void salvar(Produto produto) {
		Transaction tx=session.beginTransaction();
		session.saveOrUpdate(produto);
		tx.commit();	
	}

Ficou assim:

public void salvar(Produto produto) {
		session.saveOrUpdate(produto);
	}

Vlw pela ajuda abcs.
Ps. Já tô abrindo outro post.

a.moraissoares

Porque se deve tirar esse código que você tirou? Estou implementando um cadastro com o VRaptor nesse momento, não testei ainda, mas tava fazendo igualzinho vc:

public void salvar(Produto produto) { Transaction tx=session.beginTransaction(); session.saveOrUpdate(produto); tx.commit(); }

o que vai acontecer de problema?

ps: estou seguindo a apostila da Caellum, fazendo exatamente o getSession, ProdutoDAO(adaptado) e etc. Obrigado

leandronsp

Pessoal, uma dúvida quanto ao controle de transações do VRaptor3:

No caso de eu usar o Provider do JPA ou Hibernate, a declará-lo no Web.xml, me tira o trabalho de ter que ficar abrindo e fechando transações. Isso é maneiro.
Porém gostaria de saber se o Vraptor faz o “commit” a cada método que eu chamar.

Um exemplo clássico disso é uma transação bancária. Quero tirar dinheiro de uma conta e colocar em outra. E se no meio do processo de creditar a segunda conta, dá um problema no sistema, no banco, sei lá. A conta que foi debitada, está com um valor menor (pq foi comitada) e o destinatario nao tem o valor na conta.

Se eu chamar assim na minha logica:

dao.debita(conta1);
dao.credita(conta2);

O Vraptor vai comitar pra cada linha? Ou só ao final do meu método da logica?
Pq no VRaptor 2 que estou usando, o controle de transações eu nao faço no Dao, deixo pra quem tá chamando, pois assim nao corre o risco de salvar uma informação inconsistente no BD.

Obrigado a todos

G

No JTA o padrão é sempre commit, mas se for encontrado uma exception do tipo runtime é feito um rollback. Imagine o cenário ilistrativo abaixo:

try {
    // faz alguma coisa

    transaction.commit();
} catch (RuntimeException e) {
    transaction.rollback();
    throw e;
}

Eu só não sei se o vraptor faz rollback sempre ou apenas se der uma RuntimeException e filhas.

Lucas_Cavalcanti

se vc usar os providers do VRaptor, vai acontecer o seguinte:

  • começa transação
  • executa o MeuController.minhaLogica(); // o da requisição
  • commita a transação, ou dá rollback se aconteceu alguma exception

ou seja, é uma transação por requisição…

G

Lucas, mas é qualquer exception ou apenas as runtime, como é no JTA?

Lucas_Cavalcanti

qqer exception, fora a ValidationException, que o vraptor usa pra tratar erros de validação

leandronsp

Lucas Cavalcanti:
se vc usar os providers do VRaptor, vai acontecer o seguinte:

  • começa transação
  • executa o MeuController.minhaLogica(); // o da requisição
  • commita a transação, ou dá rollback se aconteceu alguma exception

ou seja, é uma transação por requisição…

Obrigado pela explicação Lucas. Só mais uma dúvida: e se por exemplo, a requisição for para uma logica que não precisa de transação (um “getPeloId” nesse caso), o vraptor tbm abre uma transação?

Lucas_Cavalcanti

sim… mesmo que a requisição não precise de transação ela será aberta… Isso pq não dá pra prever mto
qdo a transação é necessária e qdo não é…

A menos que isso se torne um problema de performance ou de recursos do seu banco, vc não deve se preocupar com isso…

G

Complementando, em ambiente EJB quando você tem um CMT todos métodos possuem transação ativa a menos que você especifique o contrário.

O único que faz ao contrário, e na minha visão é o correto, é o Spring, onde toda a transação por padrão é readonly a menos que você especifique o contrário, ou seja, que o método possui transação.

seufagner

a.moraissoares:
Porque se deve tirar esse código que você tirou? Estou implementando um cadastro com o VRaptor nesse momento, não testei ainda, mas tava fazendo igualzinho vc:

public void salvar(Produto produto) { Transaction tx=session.beginTransaction(); session.saveOrUpdate(produto); tx.commit(); }

o que vai acontecer de problema?

ps: estou seguindo a apostila da Caellum, fazendo exatamente o getSession, ProdutoDAO(adaptado) e etc. Obrigado

Porque o utilitário do VRaptor já controla a transação para você, logo você não precisa abrir/fechar manualmente.

A apostila mostra um exemplo de como fazer um cadastro da forma mais simples possível e depois vai evoluindo no decorrer da apostila.

http://vraptor.caelum.com.br/documentacao/componentes-utilitarios-opcionais/

Criado 11 de dezembro de 2009
Ultima resposta 5 de fev. de 2010
Respostas 23
Participantes 7