Suspeito fortemente que seja algum mal entendido sobre a necessidade de beginTransaction e commit por minha parte, entao acho que vocês podem me ajudar a esclarecer:
Antes, eu nao usava interceptor para garantir que minha session do hibernate fosse aberta (beginTransaction) e fechada (commit/rollback). Meu código estava espalhado de chamadas a estes métodos. Embora feio, tudo funcionava corretamente.
Optei entao por usar o Interceptor. Porém, toda vez que chamo meu formulario de EDICAO (que recebe o id da minha entidade e executa um session.load para obter seus dados), estou recebendo um delicioso LazyInitializationException do hibernate. Nas outras chamadas como list, save, etc nao tenho nenhum problema. Estaria eu fazendo alguma bobagem? Devo considerar no Interceptor que nao é necessário um beginTransaction/commit/rollback neste caso?
Aqui vao minhas classes de exemplo:
Entidade
@Entity
public class Grupo {
@Id
@GeneratedValue
private Long idGrupo;
private String codigo;
private String descricao;
private Date criacao;
private Date modificacao;
public String getCodigo() {
return codigo;
}
public Date getCriacao() {
return criacao;
}
public String getDescricao() {
return descricao;
}
public Long getIdGrupo() {
return idGrupo;
}
public Date getModificacao() {
return modificacao;
}
public void setCodigo(String codigo) {
this.codigo = codigo;
}
public void setCriacao(Date criacao) {
this.criacao = criacao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public void setIdGrupo(Long idGrupo) {
this.idGrupo = idGrupo;
}
public void setModificacao(Date modificacao) {
this.modificacao = modificacao;
}
}
DaoFactory
@Resource
public class DaoFactory {
private final Session session;
private Transaction transaction;
public DaoFactory() {
session = HibernateUtil.getSession();
}
public void beginTransaction() {
this.transaction = this.session.beginTransaction();
}
public void close() {
this.session.close();
}
public void commit() {
this.transaction.commit();
this.transaction = null;
}
public Dao<Grupo> getGrupoDao() {
return new Dao<Grupo>(this.session, Grupo.class);
}
public boolean hasTransaction() {
return this.transaction != null;
}
public void rollback() {
this.transaction.rollback();
this.transaction = null;
}
//...
}
Controller
@Resource
public class GrupoController {
private final DaoFactory daoFactory;
private final Result result;
private Validator validator;
public GrupoController(DaoFactory daoFactory, Result result,
Validator validator) {
super();
this.daoFactory = daoFactory;
this.result = result;
this.validator = validator;
}
public Collection<Grupo> list() {
return this.daoFactory.getGrupoDao().listaTudo();
}
public void delete(Grupo grupo) {
this.daoFactory.getGrupoDao().remove(grupo);
result.use(Results.logic()).redirectTo(GrupoController.class).list();
}
public void edit(Grupo grupo) {
if (grupo.getCodigo().isEmpty()) {
validator.add(new ValidationMessage("Código não pode ser vazio!",
"codigoInvalido"));
}
validator.onErrorUse(Results.page()).of(GrupoController.class)
.formularioGrupo("add", grupo);
this.daoFactory.getGrupoDao().atualiza(grupo);
result.use(Results.logic()).redirectTo(GrupoController.class).list();
}
public void editar(Grupo grupo) {
grupo = this.daoFactory.getGrupoDao().procura(grupo.getIdGrupo());
result.use(Results.logic()).redirectTo(GrupoController.class)
.formularioGrupo("edit", grupo);
}
public void adicionar() {
result.use(Results.logic()).redirectTo(GrupoController.class)
.formularioGrupo("add", null);
}
public void add(final Grupo grupo) {
if (grupo.getCodigo().isEmpty()) {
validator.add(new ValidationMessage("Código não pode ser vazio!",
"codigoInvalido"));
}
validator.onErrorUse(Results.page()).of(GrupoController.class)
.formularioGrupo("add", grupo);
this.daoFactory.getGrupoDao().adiciona(grupo);
result.use(Results.logic()).redirectTo(GrupoController.class).list();
}
public void formularioGrupo(String action, Grupo grupo) {
result.include("formAction", action);
result.include("grupo", grupo);
}
}
Interceptor
@RequestScoped
@Intercepts
public class DaoFactoryInterceptor implements Interceptor {
private final DaoFactory daoFactory;
public DaoFactoryInterceptor(DaoFactory daoFactory) {
super();
this.daoFactory = daoFactory;
}
@Override
public boolean accepts(ResourceMethod arg0) {
return true;
}
@Override
public void intercept(InterceptorStack stack, ResourceMethod method,
Object instance) throws InterceptionException {
System.out.println("################### Interceptando DAO para "
+ method.getResource().getType());
try {
daoFactory.beginTransaction();
stack.next(method, instance);
daoFactory.commit();
} finally {
if (daoFactory.hasTransaction()) {
daoFactory.rollback();
}
daoFactory.close();
}
}
}
O problema somente ocorre quando o controller vai renderizar o form editar(). Este é meu Dao, que chama o session.load:
public class Dao<T> {
private final Session session;
@SuppressWarnings("unchecked")
private final Class classe;
@SuppressWarnings("unchecked")
Dao(Session session, Class classe) {
this.session = session;
this.classe = classe;
}
@SuppressWarnings("unchecked")
public T procura(Long id) {
return (T) this.session.load(this.classe, id);
}
// ...
}
Meu gerador de sessions.
public class HibernateUtil {
private static SessionFactory factory;
static {
Configuration conf = new AnnotationConfiguration();
conf.configure();
factory = conf.buildSessionFactory();
}
public static Session getSession() {
return factory.openSession();
}
}
e esta é a exception
17/09/2009 23:13:23 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at net.danieljurado.discadorweb.modelo.Rota_$$_javassist_22.toString(Rota_$$_javassist_22.java)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at java.util.AbstractCollection.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:89)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:54)
at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:51)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:58)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at net.danieljurado.discadorweb.interceptors.DaoFactoryInterceptor.intercept(DaoFactoryInterceptor.java:33)
at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:51)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:58)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at br.com.caelum.vraptor.core.URLParameterExtractorInterceptor.intercept(URLParameterExtractorInterceptor.java:45)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:70)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:71)
at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:99)
at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:37)
at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:97)
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:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Unknown Source)
Segundo dizia a documentação, a idéia era ‘fugir’ dos LazyInitializationException, acabei dando de cara com eles 
