BeforeInsert em Domain Class
03/09/2012 11:35
0
E ai Pessoal,

Estou tentando colocar automaticamente alguns dados no Domain da seguinte forma:

def beforeInsert() {
user = session.user //AQUI DÁ ERRO
data = new Date()
}


Já tentei usar getAttribute("user"), mas também dá erro.

Sinceramente não sei onde estou errado.

Vlw a ajuda!
Tags: BeforeInsert Domain Class getAttribute()


0
Olá, Danilo.

Amigo, acredito que não se pode usar o objeto session numa classe domain. Acho que isso só pode em Controllers e Services.


2
Opa, na realidade é possível sim.

Da uma olhada neste link: http://www.intelligrape.com/blog/2009/07/16/accessing-session-map-in-the-domain-or-service-layer/

Só não sei se é uma boa. Vai depender do contexto.


0
Oi Danilo, você pode explicar melhor o que queres fazer, quem sabe o pessoal não passou pela mesma situação e pode ajudar propondo uma saída diferente, que acha ?
03/09/2012 12:18


0
Na verdade estou tentando montar uma tabela que armazene todo o histórico do sistema. Iria fazer 2 coisas:

1- Na própria tabela, colocar o usuário e a data em que o registro foi cadastrado
class Pessoa{
Integer id
String nome
String user //USUARIO QUE CADASTROU A PESSOA
Date data //DATA DO CADASTRO
}


Por isso pretendia usar o beforeInsert() na própria classe.

2- Em outra tabela, colocar um histório das alterações com seus respectivos usuários.

Para isso, tentei criar um Filter que monitorasse todos os controllers e Actions, mas também não deu certo. Peguei de um exemplo que adicionaram aqui no fórum mesmo, mas esta dando o erro: Unable to resolve class Log (na linha def l = new Log)

Segue código
def filters = {
gaia_log(controller: '*', action: '*') {

after = {

def usrLogado = session.user
String msg = ""

if (actionName.equals("save")) {
msg = "salvou um(a) novo(a) " + controllerName
} else if (actionName.equals("delete")) {
msg = "excluiu um(a) " + controllerName
} else if (actionName.equals("update")) {
msg = "atualizou um registro do tipo " + controllerName
}

if(!msg.equals("")) {
def l = new Log(usuario: "usrLogado", mensagem: "msg", data: new Date())
l.save(flush: true, validate: false, insert: true)
}
}

}
}


Estou lendo sobre o log4j para ver como funciona, mas estou engatinhando ainda...

Vlw a ajuda!

Obs: Vou testar daqui a pouco Henrique e te aviso. Vlw


1
Deu certo Henrique!!! Vlw.

Vou arrumar o projeto agora. Só o filter que falta, mas depois vou olhar com calma.

Obrigado!


2
Olá, Danilo.

Amigo, quanto ao teu modelo de "log", tenho algumas considerações pessoais (todas IMO, ok?):

Você está tratando o registro das ocorrências no clássico estilo "operação CRUD x tabela". Eu não gosto muito desse modelo e prefiro o estilo "caso de uso". Explico....

Nem sempre você mexe em apenas 1 tabela em certos casos de uso. E uma mesma tabela pode ser atualizada por várias telas diferentes e de diferentes modos. Qual o problema disso? O problema é que se você só tem o registro "operação CRUD x tabela", acaba não sabendo exatamente COMO o usuário mexeu naqueles registros. Em que tela ele estava exatamente? Não se sabe!

Assim, sempre tento fazer um "log" por "ação", ou seja, por "caso de uso". Prefiro registrar a ação, o usuário e os parâmetros (nomes e valores) enviados. Assim sei O QUÊ o usuário fez exatamente (ou seja, EM QUAL "tela" estava).

Outra vantagem desse modelo é ter uma auditoria do que é feito. Assim, até mesmo consultas (qual foi feita e o que foi consultado) ficam devidamente registradas. Muitas vezes saber o que foi "bisbilhotado" é tão importante quanto saber o que foi inserido/alterado/excluído, não concorda?


2
Ah e outra sugestão: Não considero uma boa prática armazenar o registro de usuário para fins de auditoria em outra tabela, mesmo que seja só em 1.

O Hibernate possui um mecanismo de auditoria pronto que cria tabelas de forma automática para sua auditoria estilo "operações CRUD x tabela". É o Envers (http://docs.jboss.org/hibernate/envers/3.6/reference/en-US/html_single/). Nunca tentei mas acredito que seja possível configurá-lo junto ao GORM.


0
Concordo Yoshiriro! Como eu trabalhei muito com BD e desenvolvimento mesmo fiz pouco, tento aplicar as idéias baseado nisso, mas realmente me faltou pensar no seu caso.

Nesse caso eu continuaria a usar o Filter, mas teria que ampliar a gama de opções dele para tudo, além de marcar os valores... bom, pensei no seguinte:

class Log {
//Definições dos campos
Integer id
String user
Date data
String tabela // grava a tabela que foi utilizada
String acao // grava as ações, como CRUD + Show
Integer id_registro // id do registro usado.
String campo // coluna da tabela
String valor_novo // valor do campo registrado
String valor_antigo // caso seja insert, ficará vazio
}


Pensei em usar criar essa classe, mas não si como fazer funcionar, hehe Imagino que o pior é conseguir saber a coluna da tabela...

O caminho é por aqui né?


2
Pra fazer isso que você quer, dá uma olhada no plugin Audit Logging.

http://www.grails.org/plugin/audit-logging

Mesmo se e ele não fizer do jeito que você quer, pode dar uma olhada no código dele pra ver como ele intercepta os eventos pra fazer o log.
03/09/2012 14:58


1
Sobre esta questão de auditoria, acho que a melhor maneira de ser implementada é incluir nas classes de domínio quando possível atributos que a facilitem como data de criação ou modificação e usuário.

no caso, acho interessante justamente por evitar tabelas enormes como a gerada pelo audit logging que, quando precisamos lidar com registros excluídos, nem sempre é tranquilo.

Assim o log deixa de ser algo esquecido e passa a ter função semântica.


0
Ressuscitando o post...

Eu estou tendo a mesma situação. Uso o usuário logado na sessão e tenho esses dois campos (usuário e data alteração) em todas as minhas tabelas.
Inicialmente o projeto foi feito com o “session” diretamente também. Mas criamos um serviço que trata o usuário logado, encapsulando a chamada direta a sessão.

Qual o problema?
Não quero injetar o “usuarioLogadoService” em cada classe de Domínio.
Também não acho interessante implementar no “beforeInsert” e “beforeUpdate” uma chamada semelhante a ApplicationHolder.application.mainContext.getBean(“usuarioLogadoService”) para ter o meu serviço.

Aí pensei em criar uma espécie de “DominioGeral” onde todos os domínios herdariam dele, e lá colocaria toda essa questão. Mas não me soou bem criar uma herança pra isso. Mas não tendo jeito, é menos pior como tá.

Uma solução que pensei seria usar algo com AOP para todos os domínios da aplicação.
Diante do problema e das soluções propostas, o que vocês acham?
Obrigado desde já!
19/12/2012 13:54



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto