JBean File Storage
Agosto 20, 2008
Após um bomtempo sem publicar devido a minha dedicação ao projeto “Easy Accept Web” (mas isso fica para outro post), anuncio um novo componente para auxílio a manipulação e associação de caminhos de arquivos/diretórios com POJOS. Muito útil quando sua aplicação trabalha em conjunto com framework ORM (Hibernate like), onde se deseja por exemplo associar uma entidade com um determinado diretório de arquivos (para upload/download por exemplo), seu nome por enquanto é :
JBean File Storage
O componente ainda apesar de implementado ainda não está disponibilizado publicamente pois ainda necessita de revisão, documentação e algumas possíveis melhorias embora esta versão esteja presente em 2 projetos já em produção.
A idéia chave foi associar um caminho a um tipo java, eu mentiria se dissesse que a idéia foi completamente minha pois me baseei numa solução proposta por Luciano Logrado ao trabalharmos juntos em um outro projeto, digamos que eu incrementei a idéia para suportar polimorfismo e com isto será possível:
- Associar um caminho a uma tipo (classe ou interface) e seus subtipos também estarão associados
- Usar uma Expression Language (semelhante a do JSP 2.0) mínima para usar caminhos dinâmicos
- Herdar um caminho dum outro POJO
- Manter na hierarquia de diretórios a hierarquia nas associações dos POJOS
Estes dois últimos são importantes caso por exemplo existam dois POJO’s com relacionamento de pai/filho e ao excluir o pai os filhos devem ser excluídos:
Cliente ->* Conta
Desta forma o caminho de arquivos do cliente poderia ser:
$/Cliente_99
/Conta_33
MeuExtrato1.txt
/Conta_34
Extrato2008.txt
Com uma operação de exclusão do diretório do cliente haverá propagação no sistema de arquivo para os subdiretórios, ou seja, as contas. Além de manter a organização dos arquivos numa hierarquia de pastas de fácil entendimento visual e manipulação.
Veja detalhes do uso:
BugBuster 1.0 – Hibernate Exception: Illegally attempted to associate a proxy with two open Sessions
Abril 19, 2008
O referido erro também ocorre com mesagem semelhante:
Illegal attempt to associate a collection with two open sessions
Causa:
O erro é provocado quando um hiberObject associado a uma sessão tenta ser alterado por outra sessão do hibernate.
Solução:
Esqueça os métodos session.get/load/update você pode conseguir o mesmo efeito com session.refresh/merge.
Contexto do Problema:
Isso acontece devido a associação de um objeto gerenciado pelo hibernate (hiberOjbect) com a sessão que o carrega. Tecnicamente se um objeto foi carregado por uma sessão, até que o objeto seja desconectado (passando para o estado Detached) ele permanece associado a ela. O que pode ser feito invocando os métodos:
//Apenas se os relacionamentos do hiberOject //que possuem cascade="evict" eles serão também desconectados session.evict(hiberObject); session.clear(); session.close();
Se outra sessão tentar alterá-lo sem ele estar destacado da última sessão, o erro será lançado.
Problemas Típicos:
1. 0 Quando se deseja usar um objeto em outra sessão sem fechar a primeira use o evict, lembrando que se os relacionamentos não possuirem cascade=”evict” o efeito do método não servirá para eles e provavelmente o mesmo erro ocorrerá para o “proxy” dos relcionamentos (que podem ser coleções causando Illegal attempt to associate a collection with two open sessions) .
2.0 Em Aplicações WEB Java tipicamente carregamos um hiberObject e o setamos em alguma variável do contexto web (request, session, sevletContext), após algum uso pela camada de apresentação fazemos outra chamada a camada do hibernate usando esse mesmo hiberObject onde ocorre falha com o dito erro. Neste caso temos dois pontos:
- Se a sessão que o carregou anterior ainda estava aberta você recai no erro 1.0
- Caso a velha sessão já tenha morrido, o seu hiberObject não está mais conectado a mesma, porém os seus relacionamentos ainda podem ter algum “proxy” para a velha sessão. Nesse caso é mais simples usar um dos metódos:
//Caso queira reconectar e recarregar //no seu objeto os dados do banco session.refresh(detachedHiberObject); //Caso queira reconectar o objeto fazer um update no banco //de dados com as novas informações setadas no objeto connectedHiberObject = session.merge(detachedHiberObject);
O merge/refresh tem funções diferentes, mas ambos reconectam o objeto a uma sessão, seja a mesma ou não, sem provocar erro.