Arquivo para a categoria ‘Grails’
Como acessar uma taglib de dentro de um service
Uma situação que acontece muito, é a reutilização das funções de taglibs dentro dos controllers de sua aplicação grails. Isso é muito fácil de se fazer, basta chamar o método usando o objeto com o nome do namespace da taglib.
Ou seja, para usar dentro do controller a função de formatação de números, definida pela função formatNumber (taglib já no core do grails), é só fazer a chamada assim:
def myAction = {
render g.formatNumber([number:5000.234, type: "number", maxFractionDigits: 2])
}
Esta função é equivalente a chamar a taglib de dentro de um gsp da seguinte maneira:
<g:formatNumber number="5000.234" type="number" maxFractionDigits="2" />
Mas quando precisamos fazer isto, por exemplo, dentro de um service, encontramos um probleminha chato, as taglibs não são injetadas automaticamente. Para contornar essa “situação“, temos que buscar a taglib manualmente, da seguinte maneira:
def myTag = grailsApplication.mainContext.
getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
def value = myTag.formatNumber([number:5000.234, type: "number", maxFractionDigits: 2])
Ahhh, para isso não se esqueca de injetar o objeto da grailsApplication da seguinte maneira
class MeuService {
def grailsApplication
(...)
}
Bin-go.
Devolvendo um texto como attachment no response
Me deparei com a seguinte situação em uma aplicação construída usando Grails.
O sistema gravaria o conteúdo de um arquivo (plain xml mesmo) dentro do banco de dados, para evitar dependências com filesystem. Mas este arquivo também precisaria ser lido posteriormente. A solução que estava disponível, era alguma coisa mais ou menos assim:
def arquivo = Arquivo.get(params.id) //recupera o arquivo da base render arquivo.texto
Legal, desta maneira (bem simples até), o conteúdo deste texto seria renderizado na página para o usuário poder salvá-la.
Imaginei que isto pudesse ser incrementado um pouco, e percebi que fazer com que o usuário tivesse que salvar a página (que continha apenas o XML) poderia se tornar um tanto chato com o passar do tempo. Resolvi alterar a action para devolver o texto em anexo ao response. Isso mesmo, com a caixinha para poder salvá-lo.
Olha que simples:
def arquivo = Arquivo.get(params.id) //recupera o arquivo da base
response.setContentType "text/xml"
response.setHeader "Content-Disposition", "attachment;filename=\"${arquivo.nome}.xml\""
response << arquivo.texto
Simples, colocando a instrução no header para que a “disposição” da resposta seja “attachment” (anexo), o browser ao invés de renderizar apenas o conteudo, retorna um arquivo com este texto.
Como definir o locale default de sua aplicação grails
Graças ao ótimo suporte de internacionalização que o grails nos proporciona, podemos alterar o idioma corrente da app passando apenas o parametro lang na URL. Com isso, o locale é definido para o usuário e se sua aplicação recupera as mensagens com o g:message ou outros recursos de i18n, usará o locale indicado.
Caso queira definir um locale default para sua app, basta sobrescrever o bean localeResolver no seu resources.groovy como abaixo:
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("pt", "BR")
java.util.Locale.setDefault(defaultLocale)
}
}
Sim, estou trazendo aos poucos tópicos que estavam em meu outro blog, blog.lucastex.com, dê uma passada por lá.
Config.groovy – Cuidado ao manipular suas configurações
Hum, reportando uma situação no mínimo inusitada que tive por aqui.
Acabei descobrindo, da maneira ruim, que no Grails, quando lêmos a configuração da aplicação (Config.groovy) através da referência grailsApplication.config estamos manipulando uma variável passível de alterações, ou seja, qualquer atributo que você recuperar de lá, e modificar, assim estará para toda a execução.
Na minha situação, eu mantinha uma lista de e-mails lá no arquivo de configuração para que quando disparado, eu pudesse enviar o e-mail a estes destinatários somados ao e-mail do usuário, que tinha acabado de ser inputado no formulário. Tinha algo assim:
contato.destinatarios = ["[email protected]", "[email protected]", "[email protected]"]
E dentro do controller, usando o mail plugin (leia este post sobre o mail plugin), executava o seguinte trecho de código:
def destinatarios = grailsApplication.config.contato?.destinatarios?.toArray()
destinatarios << params.email
sendMail {
to destinatarios
subject "Contato ..."
body "......"
}
Ou seja, quando eu pegava a referência dos destinatários do Config, eu mantinha essa referência em ‘destinatários’. Quando eu adicionava neste array o destinatário que vinha do formulários “params.email”, eu alterava a *instância* e referência da configuração da aplicação, e aquele e-mail ali ficava.
Resultado, no primeiro contato, receberam o e-mail a lista de destinatários e o [email protected], na segunda execução, todos eles da configuração, o [email protected] e também o [email protected] foram copiados.
E assim sucessivamente.
Vivendo e aprendendo, tomem cuidado com isso!
Portal imobiliário usando Groovy e Grails
Ontem (dia 09/01) fizemos o lançamento de um site que desenvolvemos usando Groovy e Grails, um desafio e tanto, pela responsabilidade de colocar o sistema no ar e pelo timing do projeto. Todo o site e a integração com o sistema legado (onde algumas informações ainda estão sendo gerenciadas), tiveram que sair do simples “create app” para produção em 2 meses. Esse é também o grande motivo para a falta de tempo de postar mais por aqui.
Trata-se dos sites http://www.imoveisnomorumbi.com.br e http://www.imoveisnopanamby.com.br, site de duas imobiliárias do mesmo grupo, que negocia imóveis de alto padrão nestes dois bairros.
Algumas informações interessantes sobre o projeto:
Tecnologia e Infraestrutura: O site antigo usava SQLServer como banco de dados e tecnologia ASP. Como usamos Groovy e Grails, por trás temos uma JVM Java em execução, e o banco de dados, o bom e velho MySQL.
Antes, para suportar o ASP, o IIS era usado como web server, e agora Um apache balanceia as requisições aos dois Tomcats. Tudo isto está deployado e rodando em um Cloud Server da Locaweb, por opção do cliente, onde já mantinha a conta antiga.
Integração com o sistema legado: Para a integração do modelo de dados antigo e o novo modelo, construímos rotinas de importação dos dados usando Groovy SQL, uma maneira fácil, muito fácil, de fazer rotinas em banco de dados.
Plugins utilizados: Ahhh, os bons e velhos plugins do Grails, não canso de dizer que esta é a melhor parte do Grails! Foram usados os plugins:
Grails-Mail, para envio dos e-mails e formas de contato do site
Grails-Acegi, para autenticação e segurança
Grails-Cookie, para manipulação dos cookies do cliente
Grails-Navigation para criação de menus/submenus da interface administrativa
Grails-RichUi para alguns componentes gráficos como auto-complete e nuvem de tags
Grails-RuntimeLogging, um ótimo plugin para moder trabalhar com o nível de log de cada artefato (controller, service, etc), da app em runtime
Grails-Settings para algumas parametrizações da aplicação.
E com certeza, se eu tivesse pesquisado com um pouco mais de tempo, teria usado outros plugins para evitar algum trabalho que tenha feito na mão. E é claro, além disso, bastante (mesmo) jquery, ajax e json.
É isso, qualquer dúvida sobre o projeto, como aconteceu, soluções e problemas, basta comentar!
Obrigado a todos!
Envio de e-mails com o Mail Plugin
Enviar e-mails a partir de uma aplicação Grails é extremamente fácil. Tudo graças ao Mail Plugin. Sou um grande fã do mecanismo de plugins do Grails não só pela facilidade de criá-los, mas principalmente pelo espírito de compartilhamento de código que isto gera nos desenvolvedores. É bem simples, por exemplo, se eu preciso de alguma coisa que envie e-mails, vou construir isto separado da minha aplicação e distribuir para todos que precisem. Fácil, muito fácil!
Enfim, o Mail Plugin é um dos plugins mais antigos do Grails (acho que usei pela primeira vez em agosto de 2008), e um dos mais simples de ser usado. O primeiro passo é instalar o plugin como qualquer outro:
grails install-plugin mail
Com isso as dependências serão baixadas e o plugin será instalado.
Após isso, você vai precisar configurar o envio de e-mail.
De forma bem intuitiva novamente, diretamente em seu Config.groovy deverá setar as propriedades:
grails {
mail {
host = "smtp.meuservidor.com.br"
port = 25
username = "[email protected]"
password = "eusoul33t"
props = ["mail.smtp.auth": "true", "mail.smtp.socketFactory.port": "587"]
}
}
Ahhh, o exemplo acima já está pronto para usar validação de usuário e senha no envio, já que hoje (99%) dos servidores assim exigem. Pronto, com isso o plugin já consegue saber como o e-mail será enviado (por trás ele usa o envio de e-mails embutido no Spring, é claro).
Agora, quando for enviar um e-mail, basta usar a closure sendMail que é automaticamente adicionada em todos os seus controllers! Segue um exemplo:
sendMail {
from "[email protected]"
to "[email protected]", "[email protected]"
cc "[email protected]"
bcc "[email protected]"
subject "Enviando e-mails com Grails"
body """
E ai pessoal,
Este e-mail foi enviado diretamente de um controller da minha
aplicação Grails usando o Mail Plugin.
Até mais."""
}
Pronto, agora é só checar as caixas de e-mail! Vale lembrar que as instruções cc e bcc não são obrigatórias!
O plugin suporta envio de anexos, conteúdo HTML e outras opções. Para mais detalhes, consulte a documentação oficial, ou deixe um comentário aqui.
Ahh, e se quiser usar uma caixa do GMail para enviar as mensagens, use a configuração abaixo.
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "[email protected]"
password = "suasenhadogmail"
props = ["mail.smtp.auth": "true",
"mail.smtp.socketFactory.port": "465",
"mail.smtp.socketFactory.class": "javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback": "false"]
}
}
Feliz 2010, ao som de “Dream Theater – Don’t look past me”.
Grails e GORM: Logando as consultas SQL no console
Uma dica pra acompanhar o uso do seu banco de dados, e saber o que o hibernate e o gorm estão fazendo por trás dos panos, é logar as queries que estão sendo feitas.
Você pode acompanhar isto detalhadamente configurando seu DataSource.groovy para fazer isso com o parâmetro loggingSql. E o mais bacana na minha opinião é poder fazer isso de forma independente para cada ambiente. Lembre-se que por default esta configuração vem desligada.
environments {
development {
dataSource {
url = "..." //banco de dev
loggingSql = true
}
}
test {
dataSource {
url = "..." //banco de testes
}
}
production {
dataSource {
url = "..." //banco de produção
}
}
}
Renderizando um XML como resposta em grails
Se em grails você precisar renderizar um XML como resposta de uma action, use o método render junto com o builder de XML que temos disponível. Muito fácil, rápido e objetivo.
No exemplo abaixo, um parâmetro nome é passado para a action, que faz uma consulta baseado neste parâmetro e nos nomes dos clientes.
def busca = {
def clientes = Cliente.findAllByNomeIlike("%${params.nome}%")
render(contentType: "text/xml") {
results() {
clientes.each {
cliente -> result() {
id(cliente.id)
nome(cliente.nome)
}
}
}
}
}
Explicando o auto-explicativo:
Linha 2: Usamos um método dinâmico do grails (não, este método não existe na classe) que permite que eu localize todos os clientes (findAll) por seus nomes (byNome) Ilike (case insensitive) usando o parâmetro nome que veio no request. Esta lista é armazenada na referência clientes.
Linha 4: Pela funcão render deixamos claro que iremos renderizar um conteúdo text/xml
Linha 5: Esta será a nossa tag root do xml: results. A closure que se abre definirá os filhos deste nó.
Linha 6: Cada cliente na lista retornada…
Linha 7: Será um novo nó result do XML de resposta
Linhas 8 e 9: Os fois filhos de result, teremos o id do cliente e seu nome, suficiente para uma combo com auto-complete!
O resultado foi como esperado, e o tempo de fazer o exemplo funcionar foi definitivamente menor que o de escrever este post!
<results>
<result>
<id>313</id>
<nome>JOSE DA SILVA</nome>
</result>
<result>
<id>817</id>
<nome>PATRICIA MARIA SILVA E SILVA</nome>
</result>
<result>
<id>91</id>
<nome>MARCOS SILVINO</nome>
</result>
</results>