Grails, desenvolvimento ágil de aplicações web na plataforma Java

Tendo desenvolvido aplicações em Java por algum tempo, sei o poder da plataforma java e também da dificuldade de seu uso.

O mundo java é tão grande que a gente se perde. Desenvolver web em java é ótimo, é orientado a objetos, se você seguir uma boa arquitetura você cria uma aplicação fácil de manter e evoluir, você pode usar diversos projetos open source de qualidade para ajudar no seu trabalho, é estável, performático, etc, etc. Mas tem um lado que a gente fica se questionando às vezes: mas precisa disso tudo mesmo? Cria o POJO, adiciona atributos, getters e setters (td bem o Eclipse gera), cria JSP, cria controlador, cria classe de serviços, cria DAO, cria as interfaces de serviços e DAOs, faz a query, configura tudo nos XMLs, testa tudo, faz o WAR, faz o deploy, starta o tomcat, ufa....eu só queria mostrar um relatóriozinho na tela do browser.... é, não é mole.

Aí, a gente olha para os lados e vê, por exemplo, PHP (eu mesmo já usei e continuo usando em alguns projetos). É mais simples não é? MEsmo se você usar um framework MVC de PHP, as coisas são mais simples na minha opinião, sem falar que é só dar um refresh no browser e vc vê a mudança imediatamente. Porém, e tudo aquilo que a gente gosta de Java: Apache Commons, Log4j, Quartz, Spring, Hibernate, Lucene, entre tantos outros projetos open source que nos ajudam, sem falar em orientação a objetos sem opção, etc, etc.

Dentro deste cenário todo, eu passei a ver todo o movimento sobre o Ruby on Rails (RoR): que é isso , que é aquilo, que é ótimo, rápido de desenvolver, não precisa configurar em XML, e isso, e aquilo. Realmente o grupo do RoR criou um framework MVC para aplicações web com bancos de dados que funciona e ajuda MUITO os desenvolvedores. Foi quando eu descobri o Grails (inicialmente chamado de Groovy on Rails).

O Grails foi inspirado no RoR, seguindo o padrão de convenção ao invés de configuração (o que já nos tira um trabalho de configurar tudo). Não sou profundo conhecedor do RoR, mas sabendo que o Grails se inspirou nele, podemos ver que realmente o grupo do RoR fez um excelente trabalho. Mas excelente também é o Grails: um framework MVC para desenvolvimento ágil de aplicações web com bancos de dados, sobre a plataforma Java.

O Grails foi desenvolvido em Groovy, uma linguagem de script dinamicamente tipada, orientada a objetos, que roda sobre a JVM e se intgra nativamente com Java. Você pode dar um import de uma classe java no seu script Groovy, instanciar e usar a classe Java normalmente (perdoem se eu estiver falando besteira, não sou expert em Groovy ainda).

Por baixo dos panos...
O Grails não quis reinventar a roda, e portanto utiliza tudo que a gente gosta do mundo java: Log4j, Hibernate, Spring, SpringMVC, Sitemesh, Quartz... tudo por baixo dos panos, abstraindo todo este mundo de mais "baixo nível". A configuração do spring ele mesmo faz usando groovy ao invés de xml. A persistência ele usa Hibernate. Para templates ele usa Sitemesh. E assim vai. Mas o fato é que você não precisa conhecer cada um desses frameworks, pois o Grails abstrai isso tudo. É claro que às vezes, se você conhecer um pouco de cada, você pode ter vantagens.

Auto reloading...
Você gosta de dar um refresh e e ver as mudanças imediatamente? O Grails é assim em 99% dos casos! :-)

Convenções do Grails...
O Grails usa a codificação por convenção: estrutura de diretórios, nomenclatura de classes, URL, ...
Por exemplo:
http://locahost:8080/minhaApp/user/add = UserController + add closure
A Closure add do controlador UserController será executada.

Você pode "configurar" o framework com atributos reservados, como por exemplo, se você quiser fazer com que um closure de um controlador seja a Action default a ser executada para aquele controlador, você faz:





class BookController {
def defaultAction = "list"
def list = {
// do controller logic and create model
return model
}
}




Grails MVC...



  • M =>
    Classes do modelo seguem o padrão "Active Record"
    User u = User.get(1)
    u.delete()
  • C =>
    Grails Controllers: Classes Groovy, Não herdam ninguém, Tem classes de serviços injetados pelo Spring.
  • V =>
    GSP ou JSP (GSP = Groovy Server Pages)
    Sitemesh
    Grails Taglib: classes groovy, Não precisa de TLD.

Grails Controllers..

  • closures = actions (ações a serem executadas pelo controlador são as closures do seu controlador)
  • fazer redirect nunca foi tão fácil:
    redirect(action:list)
  • É possível fazer restrição do método Http requisitado (POST, GET)
    def allowedMethods = [action1:'POST', action3:['POST', 'DELETE']]
  • Os contextos estão disponíveis para o seu controlador: Request, Session, appContext


    class BookController {
    def find = {
    def findBy = params["findBy"] // ou params.findBy
    def appContext = servletContext["appContext"] // ou sContext.appContext
    def loggedUser = session["logged_user"] // session.logged_user
    }
    }
  • Existe o escopo Flash (variável colocada na sessão até ser usada no request seguinte):
    flash.message = ‘Operação realizada com sucesso’
    redirect(action:list)


  • Binding:
    O binding do form para os atributos do seu objeto POGO é muito simples, bastanto objeto.properties = params (onde params é um mapa disponível no seu controlador contendo os parâmetros recebidos pelo POST ou GET:


    def save = {
    def b = new Book()
    b.properties = params
    b.save()

    // Ou usando um objeto command
    def sc = new SaveCommand()
    bindData(sc, params)
    return [book:b]
    }


  • Por trás dos panos retorna ModelAndView do Spring
    Caso não declare “return”, retorna propriedades do controlador
  • Rendering: encaminha para view apropriada:
    http://localhost:8080/meuprojeto/user/add = views/user/add.gsp (ou .jsp)


    render "Hello World!
    render {
    for(b in books) {
    div(id:b.id, b.title)
    }
    }





  • Action redirection and chaining
  • Action Interceptors: é possível interceptar a chamada das actions (closures):
    . def beforeInterceptor
    . def afterInterceptor
  • File uploads: o Grails possui facilidades que ajudam no upload de arquivos.


Grails Object Relational Mapping: GORM...

O Grails criou uma nova forma de mapeamento objeto relacional. Na verdade, o Grails usa o Hibernate mas facilita o mapeamento, que ao invés de ser com XML (até pode ser se vc quiser), faz com atributos reservados na sua classe de modelo (POGO , Plain Old Groovy Object). As classes de modelo tem seus atributos mapeados como campos, e você pode especificar algum atributo como opcional ou transiente.







class Book {
static optionals = [ "releaseDate" ]
static transients = [ "digitalCopy" ]
Author author
String title
String author
Date releaseDate
File digitalCopy
}


Os relacionamentos entre as entidades são especificados com atributos reservados do Grails. São suportados relacionamentos one-to-many, many-to-one, e many-to-many.



  • One-to-many

    class Author {
    static hasMany = [ books : Book ]
    String name
    }



  • Many-to-one

    class Book {
    static belongsTo = Author
    Author author
    String title
    }



  • Many-to-many

    class Book {
    static belongsTo = Author
    static hasMany = [authors:Author]
    }
    class Author {
    static hasMany = [books:Book]
    }
    new Author(..).addBook(new Book(..)).save()


Grails Querying

  • findBy*:
    def results = Book.findByTitle("The Stand")
    results = Book .findByTitleLike("Harry Pot%")
    results = Book .findByReleaseDateBetween( firstDate, secondDate )
    results = Book .findByTitleLikeOrReleaseDateLessThan( "%Something%", someDate )
  • Creteria Builder

    def c = Book.createCriteria()
    def results = c {
    like("author.name", "Stephen%")
    between("releaseDate", firstDate, secondDate )
    }
  • Query by Example:
    def b = Book.find( new Book(title:'The Shining') )
  • HQL:
    def results = Book.find("from Book as b where b.title like 'Lord of the%'")

E o Grails ainda possui facilidades para:

  • Jobs: uso do Quartz
  • Transactions: métodos dos “services” são transacionais
  • Validation
  • Scaffolding
  • Ajax
  • Unit testing
  • Spring Integration
  • Hibernate Integration

Para finalizar....

  • a lista de usuários é bastante ativa tendo todo o apoio dos líderes do projeto;
  • a documentação já é bem razoável e melhora a cada dia;
  • o primeiro livro já foi escript e publicado;
  • não se assuste com a versão ainda em 0.3.1 nesta data. O projeto já possui muitas funcionalidades estáveis que ajudam muitos projetos web.

Boa sorte!

7 comentários:

Douglas 21 de janeiro de 2007 12:20

Estou definindo uma arquitetura para um prototipo de aplicação web em java. Estou (estava) praticamente resolvido com JSF/Facelets/Hibernate, depois de ler seus posts talvez tome outra direção...

Felipe Nascimento 22 de janeiro de 2007 12:14

Olá Douglas. É bom saber que meus comentários estão chegando até o público certo. Obrigado pelo comentário. Vale a pena sim olhar o Grails e ver como ele pode nos ajudar. Boa sorte!

Anônimo 28 de outubro de 2007 20:16

Felipe,

Tem algum material do tipo passo a passo que possa ser encontrado na web???

Dei uma olhada no site e achei a documentação meio fraquinha....

O livro oferece esse passo a passo??

Felipe Nascimento 29 de outubro de 2007 12:55

Olá,

eu acho que a documentação realmente não é a melhor (ultimamente houve bastante discussão na lista sobre documentação, e o pessoal da G2one vai investir em documentação em breve). Mas para o básico ela cobre os principais pontos.
Dê uma olhada:
http://www.grails.org/Quick+Start

Depois, leia o User Guide:
http://www.grails.org/User+Guide

Vá lendo item por item. No final você terá uma excelente noção do grails.

Além disso, há sim pequenos tutoriais na web, tem é que garimpar.

Tem uma que eu fiz há um tempo já....
se quiser olhar:
http://wiki.les.inf.puc-rio.br/uploads/4/44/GrailsFelipe.ppt

O livro é muito bom. Mas foi feito na versão 0.3.1. Muita coisa mudou desde então. Mas mesmo assim, tem bastante coisa lá.

Outra opção é um pdf gratuito, um minibook:
http://www.infoq.com/minibooks/grails
Esse é legal tbem.

Por ultimo, vale olhar o www.groovyblogs.org , que é um site que agrupa blogs sobre groovy e grails. O próprio site é feito em grails e tem seu código fonte livre para download. (http://www.bytecode.com.au/downloads/grails/groovyblogs-0.5.6.tar.gz)

Cleber 10 de novembro de 2007 17:04

Você diz que os campos podem ser "opcionais ou transientes" o que isso significa exatamente?

obrigado.

Felipe Nascimento 13 de novembro de 2007 21:24

Olá Cleber,

Atributos opcionais são aqueles que não precisam ser preenchidos, ou seja, que podem ter valor NULL no BD. Transientes são aqueles que não são persistidos, ou sejam, não existem campos na tabela para esses atributos. Normalmente são atributos de ajuda, usados em memória, mas que não são persistidos.

Grande abraço
Felipe Nascimento

Anônimo 20 de novembro de 2009 10:27

Aprendi muito