| Autor |
Mensagem |
|
|
microfilo wrote: Aí eu não tenho um mecanismo que gerencia a transação. Seria o mesmo que controlar a UserTransaction na mão. Da muito trabalho e obriga os meus objetos de dominio a lidar com transação, algo que eu não acho legal.
Exatamente, o controle é explícito programaticamente, embora a abstração da API transacional através da estratégia lhe garanta um Gateway no domínio isolado da tecnologia. Quanto ao domínio lhe dar com a transação, mesmo se você colocasse metadados nas entidades, como as annotations @Transaction, o controle continuaria no Domínio.
microfilo wrote:
Mas seria a "entity" o local mais adequado para demarcar as transações? e se eu for utilizar uma mesma "entity" em um outro contexto em que o isolamento transacional é diferente?
Transações são ações bem particulares dos casos de uso. Fatalmente, se você possui um domínio rico e ubiquitous, o comportamento da entidade reflete diretamente estas ações. Se um comportamento explícito em um ou mais métodos requer determinado tratamento, por consequência toda chamada a este método/comportamento deve ser executada de mesma forma, caso contrário é uma ação diferente.
Se isso estiver em um Service (o controle de transações), não muda nada. Services também são objetos de negócio pertencentes ao domínio, assim como Aggregates, ValueObjects, Entities, etc. Da mesma forma que você pode utilizar um Entity em lugares distintos, você também poderia utilizar um service. A questão é, se em lugares diferentes eles podem possuir comportamentos diferentes, então alguma coisa na modelagem pode não estar legal.
Claro, outra alternativa é deixar a cargo da Application Layer (Actions, Commands, ManagedBeans e afins). Em vista que a transação possa ser encarada como serviço do sistema, a própria camada de aplicação pode resolver este problema... a questão é, será que isso é interessante para todos os casos? Eu acredito que não.
microfilo wrote:
Lezinho wrote: Em caso de transações atômicas uso flushMode manual do hibernate ...
O flush em si não resolve... Mesmo que você faça o flush, se você fizer o rollback da transação, o seu update não sera refletido no banco de dados.
Isso é o que espero, note que me referi as transações atômicas e não em isolamentos.
microfilo wrote: Acho que a gente se confundiu, heheh. Para invocações client-side é bem parecido com DWR.
Pois é, hehe. Mas com o DWR eu posso invocar diretamente um EJB na página?
[]'s
|
 |
|
|
microfilo wrote: Acredito que na maioria dos demarcadores transcionais não podem ficar no repository.
Concordo. Citei um Repository como EJB3 apenas para questão do uso de injeção convencional do EntityManager.
microfilo wrote: Entendo Lezinho, mas em todo o caso, haverá momentos em que a "entity" precisara efetuar operações de update e, em alguns casos, precisara que essas operações estejam em transações isoladas. Como minha "entity" não é instanciada via spring\ejb, ela não possui demarcação de transação. E, como eu disse acima, não acho que seria correto demarcar a transação no repository, na maioria dos casos.
Em caso de transações isoladas em entidades para entidades poderia ser feito:
1) Construir uma Strategy de um objeto de transação fake (para poder mudar a implementação se necessário). Esta strategy é um atributo injetado em sua entidade (portanto controlado pelo ciclo de vida do seu framework de injeção/transação). Ele tem um atributo que inicia uma nova transação isolada e que a finaliza. Você pode chamar este atributo nos pontos necessários de sua entidade.
2) Criar uma anotação para novas transações na entidade. Funcionaria exatamente como descrevi acima, com a chamada para um objeto de transação sob o controle de seu framework, exceto pelo fato de você não ter que fazer um atributo a mais na sua entidade... mas sim anotar um método. Um "aspecto"deverá fazer a leitura para efetuar a transação.
3) Fazer todo o processo transacional por fora, em um service. É a forma mais simples e direta, porém pode compromete um pouco o modelo.
Costumo utilizar controle de transação otimista, onde ela se inicia no começo de um request e finaliza no seu fim (via filtros).
Em caso de transações atômicas uso flushMode manual do hibernate, onde os DAOs (e não repositories) possuem métodos com flush explícito. Para o Repositories isso é transparente e não vaza para o domínio. Claro que o filtro é informado quando a transação é atômica ou não (na realidade isso é feito pelo Seam).
microfilo wrote:Será que da para fazer algum transaction management diretamente na "entity" utilizando AOP? Nesse caso, a entity não ficaria muito "parruda"?
Eu acho que não fica ruim. Ela é parruda tão quanto o modelo assim o faz, eu acho justo.
microfilo wrote:
Lezinho wrote: Server-side, embora poderia ser client-side em vista que consigo invocar qualquer metodo mesmo com Javascript, bastando ele estar anotado por @WebRemote para esta ultima.
Bacana, bem parecido com DWR, não?
Na realidade bem mais transparente. Com a EL dele é possível invocar qualquer método de classes de negócio sem ter um Command por trás disso em qualquer página, e sem javaScript adicionais (é server-side). Mais se acaso vc tiver um JavaScript e precisar invocar um método de um objeto de negócio que esta em algum escopo, neste caso vc utiliza a anotação @WebRemote... somente isso.
|
 |
|
|
Entendi microfilo, mas mais uma vez o limite é tecnológico (utilizar facilidades do EJB/Spring).
Neste caso mais específico, o EJB pode ser a façade que mencionei e usar os controles transacionais necessários, ou até mesmo ser seu Repository (um EJB3 sendo a implementação de um repository não é ruim, muito pelo contrário).
De forma geral um repository pode estar dentro ou fora da entidade, conforme sua necessidade. Uma abordagem como entidade.salvar não me agrada nem um pouco, neste caso utilizo um repository fora da entidade. Porém a entidade como objeto de negócio que é, certamente irá precisar em algum momento de acesso a dados via repository, em seus próprios métodos, como o comportamento que citei em "client.latestPurchases", neste caso uso um Repository interno.
Mas sei que isso pode gerar outros problemas, como:
"Mas como vou injetar Repositories em minha entidade se ela não é gerenciada pelo meu container IoC, é instanciada via new ou por frameworks de persistência?"
... bom, se sua dúvida for essa, eu postei uma solução aqui:
http://www.guj.com.br/posts/list/70275.java
microfilo wrote:As chamadas são server-side ou client-side?
Server-side, embora poderia ser client-side em vista que consigo invocar qualquer metodo mesmo com Javascript, bastando ele estar anotado por @WebRemote para esta ultima.
|
 |
|
|
rpffoz wrote: Aproveitando, gostaria de saber se vocês tem uma referência para tratamento de exceptions, e usando AOP para as exceptions corriqueiras.
Utilize o advice "around" com o AspectJ. Com ele vc consegue contornar qualquer pointcut que desejar com try/catch.
|
 |
|
|
"Se você utiliza o repository direto na "entity", fica difícil tirar proveito dessas facilidades (eu imagino que a entity é geralmente instanciada com new e não via IoC\Lookup), ou pelo menos do tranasction management."
Não sou o Shoes mas vou opiniar Microfilo.
Quando se usa Repositories, teoricamente sua modelagem deve estar sendo criada com base em Domain-Driven Design (pelo menos tende a ser).
Portanto o design é para o negócio e não para a arquitetura na camada de aplicação. Uma Façade qualquer pode isolar seu Domínio de Negócio do Domínio da Aplicação. Hoje em dia, nem mesmo isso é necessário, eu por exemplo faço isso usando o JbossSeam:
... diretamente em meu xhtml.
Em outros pontos da aplicação eu faço:
... onde o método na entidade Client faz acesso a seu repositório buscando as ultimas compras deste cliente.
|
 |
|
|
Como mencionei, apenas usei a tag t:saveState sobre o bean que estava fazendo a conversão:
http://myfaces.apache.org/tomahawk/uiSaveState.html
|
 |
|
|
Na minha opinião, uma interface ou implementação chamada simplesmente "Pessoa" só deveria existir em um sistema, se existir uma entidade chamada ExtraTerrestre ou Animal que possa entrar em conflito de comportamento com a tal "Pessoa".
Pessoa é algo muito genérico, posso estar enganado mas fatalmente essa modelagem possa ser modelada ao ponto de ficar mais clara.
|
 |
|
|
bbviana wrote:O ideal é ter uma classe para manipular cliente: GerenciadorCliente por ex. Sua classe Cliente tem qeu ser "burra", i. e., não deve ter lógicas complexas e não deve gerenciar suas instâncias.
A classe tem que ser burra??? Coitada dela ...
Concordo que a atividade de se cadastrar um novo cliente deve estar sob uma classe "GerenciadorCliente", mas não pelo motivo da classe Cliente ter que ser "burra", mas sim pq cadastrar não é atividade de um cliente.
Cliente pode ter métodos complexos sim, desde que estes sejam frutos de um comportamento de um Cliente.
public void compraProduto(Produto produto); ... pode ser uma método interessante, por exemplo, para a classe Cliente.
|
 |
|
|
Você tem que se aprofundar no "conjunto da obra" e não apenas em uma parte dela para realmente entender como se contruir um modelo não anêmico.
Como já citado aqui, Domain Model é apenas o fragmento do sistema responsável pelas entidades de negócio e seus comportamentos.
Sua interação com o resto do sistema é apoiada em outras práticas. Seu modelo não deixa de ser rico quando vc delega para algum Gateway (PoEAA - Fowler) realizar algum serviço de infraestrutura, ou quando tal feito é realizado pela camada de aplicação (DDD - Evans) isolando seu Domain Model.
Especificamente, sobre persistência em modelos ricos, procure por "Repository" catalogado por Evans e Fowler... fonte de milhares de discussões aqui no GUJ.
Boa sorte
|
 |
|
|
Já no início, programadores ouvem que é uma boa prática desenvolverem para interfaces... "abstração" é a palavra da ordem (o sistema "pode" mudar de implementação em determinado serviço, mudar de frameworks e etc ).
O próximo passo é como abstrair: o coração disso...."Factories".
Então, com embasamento e as "motivações" propostas pelos gurus dos Design Patterns (gambiarras catalogadas para suprir deficiências semânticas ou de paradigmas), surgem os mais diversos nomes e códigos para garantir que seu sistema saia o mais burocrático, extensível e "abstrato" do mundo.
Então você vaga pela internet, encontra um Portal de malucos falando sobre Injeção de Dependência e resolve ler um pouco mais a respeito:
"Hey, mas peraê, ca-ca-ca-cadê os sssingletons nas classes de vocês? Suas AbstractFactories e seus respectivos produtos-fábricas? Onde vocês estâo gerenciando/instanciado estas interfaces? Vocês não precisam se preocupar com nada disso, tão de sacanagem comigo? E ainda por cima isso facilita o desenvolvimento seus Testes Unitários?"
É, eu acho DIP uma boa ...
|
 |
|
|
Sei sim ...
É só você "anotar" no bloco de notas um script de drop e create... hehe (brincadeira Fer, amanhã a gente conversa)
|
 |
|
|
Rodrigo Carvalho Auler wrote:
Lezinho wrote:Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
Uma pergunta: nesse caso, como vc faz a validação dos dados do objeto?
 Cria um método entidade.validar() e chama dentro do EntidadeRepository.add(entidade)?
[]'s
Rodrigo C. A.
A questão da validação é relativa a cada caso.
Se a validação é sobre invariantes simples do contrato, eu utilizo Hibernate Validator (para contratos nulos, tamanho de campos, datas futuras ou passadas, regex, etc)
Ex:
Se a validação para um contrato for quanto a permissão de papeis do usuário, eu uso o Seam com Drools :
... agora se o contrato for algo que exige mais do negócio, entao eu evito colocar validações nos clientes e implemento no próprio negócio (por exemplo, quando um Entity faz um pedido ao Repository, quem vai verificar o contrato é o Repository).
Eu tento manter o código o mais limpo possível dos contratos, mas quando não é possível não se pode fazer muita coisa.
|
 |
|
|
Domain Model com Entidades contendo save, persist, ... ?
Se você acredita que estas assinaturas de métodos faz sentido estar nas entidades, sua equipe e Expert Domain concordarem com você, tudo bem.
Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
Isso não é falácia, é ponto de vista.
|
 |
|
|
Se trabalhar com Domain Model não é pré-requisito para a modelagem, tbm não vejo problema em utilizar Active Record.
Ë puramente uma questão de escolha de design.
|
 |
|
|
emerleite wrote:
Lezinho wrote:Anotações são apenas informações jogadas ao vento, não são códigos.
No caso do JPA, sua classe continua sendo POJO se apenas for anotada, mas deixa de ser se você utilizar EntityManager dentro dela (por isso use a abstração oferecida por um Repository).
O que tem a ver ter um atributo de instância com ser um POJO ?
O termo quando foi cunhado por Fowler, tinha como objetivo dar um nome para classes Java simples, aquelas que não tinham necessidade de estender nem implementar nada de frameworks em específico que lhe rotulassem algo . Porém o termo é apenas uma referência, não é uma regra... mas isso é gosto particular. Tem gente que chama POJO de Bean e esta super bem com isso, outras pessoas acham que JavaBeans é apenas a definição de componentes para GUIs & RADs, etc.
Eu *particularmente* não chamo classes que dependem da infraestrutura de frameworks que lhe ditam como deve ser seu comportamento, de POJO.
|
 |
|
|
|
|