Filtrando com Grails

Criar filtros em Grails, assim como a maioria das tarefas, trata-se de uma tarefa incrívelmente simples se compararmos com o modo como costumamos implementá-los ao trabalharmos diretamente com Servlets. Apesar de ser possível criar inteceptadores, estes só são eficientes quando precisamos lidar com pouquíssimos controladores (um no máximo em minha opinião). Filtros, no entanto, são criados visando atender um número maior de controladores de maneira mais eficiente.

Para demonstrar a criação de um filtro, irei usar o exemplo mais clichê que vêm à minha mente: validação de usuários. Imaginemos por exemplo como funciona o Orkut: se não estivermos logados nos serviços do Google, seremos saudados infinitamente por um formulário de login, e apenas um formulário de login veremos enquanto não fornecermos um login e uma senha válidos. Só poderemos acessar nosso perfil e demais páginas do serviço se já estivermos corretamente logados no sistema.

Sendo assim, mãos à obra: como tudo no Grails, devemos seguir algumas convenções na criação de nosso filtro. A primeira delas diz respeito ao arquivo no qual definiremos nossos filtros. Deverá ser criada uma classe Groovy cujo nome siga a seguinte convenção: [o nome que você quiser]Filters, que por sua vez deverá estar implementada em um arquivo presente no diretório /grails-app/conf, cujo nome será… [o nome que você quiser]Filters.groovy.

Em nosso exemplo, iremos portanto criar um arquivo chamado AprendendoFilters.groovy. Neste arquivo, devemos incluir um bloco chamado Filters, tal como no exemplo abaixo:

class AprendendoFilters {
def Filters = {
// aqui posso definir quantos filtros quiser, tal como o exposto abaixo:
acessoBasico(controller:'*', action:'*') {
// aqui entrará minha validação
}
outroFiltroQualquer(controller:'aquele', action:'voceSabe') {
// No bloco Filters, posso definir QUANTOS filtros quiser (tenha moderação)
}
}
}

Há dois tipos de filtros: aqueles voltados a controladores e aqueles voltados a URL’s específicas. O exemplo exposto acima pertence à primeira categoria (mais abaixo falo da outra). Destrinchando nosso bloco Filters, pode-se observar que criei dois filtros distintos: o primeiro se aplica a todos os controladores e a todas as ações referentes aos mesmos. Caso meu projeto estivesse bem padronizado, e todos os meus controladores possuíssem uma action chamada facaBobagem, poderia configurá-lo tal como no código abaixo sem problemas:

acessoBasico(controller:'*', action:'facaBobagem) {
// Gerencio permissões
}

Já o segundo exemplo listado, sabe muito melhor o que quer. Aplica-se somente ao controlador aquele e deseja interceptar apenas a action voceSabe.

Caso eu quisesse implementar um filtro relativo a URL’s (eis a segunda categoria), poderia implementá-lo tal como no exemplo abaixo:

apenasURLs(uri:'/voceSabe/**') {
// implementação
}

Já no corpo do filtro, você pode definir qual o seu tipo de atuação. Há três tipos de atuação distintos:

  • before – Executa o filtro antes da action em questão
  • after – Executa após a execução da action. Recebe como primeiro argumento o modelo aplicado à visualização
  • afterView – Executado após a view ter sido renderizada

Então, agora que sabemos as regras básicas de funcionamento de um Filtro, vamos implementar o nosso filtro de gerenciamento de acesso. Observe o código abaixo:

acessoBasico(controller:'*', action:'*') {
/*
Repare: dentro do meu bloco acessoBasico, incluo outro bloco, chamado before
*/
before = {
if (!session.usuario && !actionName.equals('login') {
redirect(controller:'entrada', action:'apresentacao')
return false
}
return true
}
}

Como pode ser visto, o filtro atua antes de qualquer action ser executada. Em seu corpo, é verificada a presença do atributo usuario na sessão e, caso o mesmo não esteja presente, e o nome da action seja diferente de login, redireciono-o para o controlador entrada acessando a action apresentacao.

Aonde uma dúvida pode surgir: o que vem a ser actionName? actionName consiste em uma das propriedades presentes em todos os filtros do Grails. Neste caso, actionName retorna o nome da ação que está sendo interceptada. Convém mencionar que propriedades presentes nas classes de controle, como session, request, response, flash, params, e outras também encontram-se presentes para os filtros.

Sendo assim, como pode ser visto, a criação de filtros em Grails é muito mais simples do que o modo com o qual estamos habituados a trabalhar quando lidamos com Servlets. Nenhum arquivo de configuração foi tocado, nossa única ação consistiu em criar um arquivo com o nome correto, no lugar correto seguindo algumas convenções. Convention over Configuration rocks!

10 thoughts on “Filtrando com Grails

  1. Kico, to fazendo tipo um filtro na minha list pra listar baseado em alguns campos.
    Adicionei o seguinte trecho no list.gsp

    Project:

    Meu controler ficou assim:
    def list = {
    params.max = Math.min(params.max ? params.max.toInteger() : 10, 100)
    if(params.projectId){
    [creditInstanceList: Credit.findAllByProject(params.projectId), creditInstanceTotal: Credit.count()]
    }
    else{
    [creditInstanceList: Credit.list(params), creditInstanceTotal: Credit.count()]
    }
    }

    Meu domain ficou assim:
    class Credit {
    Project project
    …..

    Mas dá o seguinte erro:
    Error 500: Executing action [list] of controller [com.scacp.faturaProjeto.CreditController] caused exception: groovy.lang.MissingMethodException: No signature of method: com.scacp.faturaProjeto.Credit.findAllByProject() is applicable for argument types: (java.lang.String) values: [26] Possible solutions: findAllByProject(java.util.List), findByProject(java.util.List)

    Você poderia me ajudar?

    Responda

    admin Reply:

    em findAllByProject você deve passar uma instância de Project, e não uma string.

    Responda

    valter Reply:

    Na list.gsp do Credit eu tenho o filtro

    Project:

    que é o comboBox onde eu seleciono o projeto que quero filtrar.
    Meu controler do Credit tem
    def doSearch = {
    [creditInstance:Credit.findAllByProject(“%”+params.projectId+”%”)]
    }

    Porém dá o erro que você falou pra passar uma projectInstance e não uma String. Como passa essa instância? Pra assim fazer a busca pelo id do projeto?

    Responda

    valter Reply:

    list.gsp faltou isso
    “g:select name=”projectId” from=”${com.scacp.corporativo.Project.list()}” optionKey=”id” value=”${creditInstance?.project?.id}” />”

    Responda

    admin Reply:

    Valter, será que você pode me passar estas suas dúvidas por e-mail ou pelo Grails Brasil?

    Responda

  2. Iae Kico, beleza? Cara, to com problema nos filters, to iniciando agora no Grails e estou assistindo as video aulas da devmedia feitas por você… acontece o seguinte problema quando executo:
    Redirecionamento incorreto
    O Firefox detectou que o pedido para este endereço não será concluído devido à forma que o servidor o está redirecionando.

    Não consigo de forma alguma resolver o problema, você poderia me ajudar? Segue abaixo o código do filtro:

    class AcessoFilters {

    def filters = {
    acesso(controller:’*’, action:’*’) {
    after = {
    if (!session.usuario && !actionName.equal(“login”){
    redirect(url:’/freako/’)
    }
    }

    }
    }
    }

    Responda

    admin Reply:

    Oi Andrei, eu costumo resolver estas dúvidas pelo Grails Brasil. Pode ser por lá?

    O endereço é http://www.grailsbrasil.com.br

    Responda

  3. Ps.: na parte do tipo de atuação está “after” mas ja testei com “before” e não deu certo…

    Responda

  4. Olá kiko.Estou começando agora com grails,e me deparei com um problema que estou batendo um poquinho de cabeça com ele.É que eu preciso filtrar cidades por estado numa pagina gsp.Se vc puder me ajudar,me dê uma luz de como eu poderia fazer isso.De já agradeço.

    Responda

Leave a Reply

Your email address will not be published. Required fields are marked *