2011-introdução ao framework grails

123
UNIVERSIDADE VEIGA DE ALMEIDA BACHARELADO EM SISTEMAS DE INFORMAÇÃO INTRODUÇÃO AO FRAMEWORK GRAILS Adriano Basto Antunes Cabo Frio 2011

Upload: profrogeriocardoso

Post on 24-Jul-2015

282 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 2011-Introdução ao Framework Grails

UNIVERSIDADE VEIGA DE ALMEIDA

BACHARELADO EM SISTEMAS DE INFORMAÇÃO

INTRODUÇÃO AO FRAMEWORK GRAILS

Adriano Basto Antunes

Cabo Frio

2011

Page 2: 2011-Introdução ao Framework Grails

ADRIANO BASTO ANTUNES

INTRODUÇÃO AO FRAMEWORK GRAILS

Trabalho desenvolvido durante a disciplina Monografia e apresentada

ao Curso de Sistemas de Informação da Universidade Veiga de

Almeida, Campus Cabo Frio, como pré-requisito para a obtenção do

título de Bacharel em Sistemas de Informação.

Orientador: Prof. Jorge Ricardo Valardan Domingos, M.Sc

Cabo Frio

Junho/2011

Page 3: 2011-Introdução ao Framework Grails

Universidade Veiga de Almeida - UVA

Faculdade de Informática

Curso de Bacharelado em Sistemas de Informação

Reitor:

Prof. Dr. Mário Veiga de Almeida Jr.

Vice-Reitor:

Prof. Tarquínio Prisco Lemos da Silva

Coordenador do Curso de Informática:

Prof. Edgar Augusto Gonçalves Gurgel do Amaral

Banca Examinadora:

_____________________________

Prof. Jorge Ricardo Vallardan Domingos (Orientador)

M.Sc em Matemática – Puc-Rio

_____________________________

Prof. Matheus Bousquet Bandini

M.Sc em Sistemas e Computação – IME/RJ

_____________________________

Prof. Douglas Ericson Marcelino de Oliveira

M.Sc em Sistemas e Computação – IME/RJ

Universidade Veiga de Almeida – Cabo Frio

Estrada das Perynas, s/n

CEP: 28901-970 - Cabo Frio – RJ

Page 4: 2011-Introdução ao Framework Grails

Dedico este trabalho a todas as pessoas que sempre me apoiaram na conquista dos

meus objetivos.

Page 5: 2011-Introdução ao Framework Grails

AGRADECIMENTOS

A minha mãe que sempre me apoiou e incentivou fervorosamente meus estudos. Aos

meus irmãos que virão em mim à chance de realizar seus sonhos. Aos meus amigos, colegas e

professores com quem dividi experiências e aprendi muito nesta longa caminhada.

Page 6: 2011-Introdução ao Framework Grails

LISTA DE FIGURAS

Figura 2.1 – A evolução do ambiente tecnológico ................................................................... 17

Figura 2.2 – O padrão MVC ..................................................................................................... 22

Figura 3.1 – Código: Comparação Simples de Java e Groovy ................................................. 31

Figura 3.2 – Código: Exemplo do uso de Meta-Objeto ............................................................ 33

Figura 3.3 – Código: Exemplo de GString ............................................................................... 34

Figura 3.4 – Código: Os métodos findAll e each. .................................................................... 35

Figura 3.5 - Código: Exemplos de Closure .............................................................................. 36

Figura 3.6 – Entendendo o SiteMesh ....................................................................................... 41

Figura 3.7 – Árvore de diretórios de uma aplicação Grails ...................................................... 45

Figura 3.8 – Código do DataSource.groovy ............................................................................. 48

Figura 3.9 – Scaffold ................................................................................................................ 51

Figura 3.10 – Exemplo de GSP ................................................................................................ 52

Figura 3.11 – Código: Incluindo template parcial .................................................................... 53

Figura 4.1 – Diagrama de Classes ............................................................................................ 60

Figura 4.2 – Classe de domínio: Cliente.groovy ...................................................................... 61

Figura 4.3 - Classes de domínio: VendasaPrazo.groovy .......................................................... 62

Figura 4.4 – Diagrama Hierárquico das Classes de Testes ...................................................... 64

Figura 4.5 – Tela Unit Test Results .......................................................................................... 65

Figura 4.6 – Tela Principal ....................................................................................................... 67

Figura 4.7 – Tela de Login ....................................................................................................... 67

Figura 4.8 – Tela Listar Clientes .............................................................................................. 68

Figura 4.9 – Tela Mostra Usuário ............................................................................................. 68

Figura 4.10 – Tela Criar Venda a Prazo ................................................................................... 69

Figura 4.11 – Tela Mostrar Resultados da busca ..................................................................... 70

Figura 4.12 – Árvore de diretórios war .................................................................................... 72

Page 7: 2011-Introdução ao Framework Grails

LISTA DE TABELAS

Tabela 3.1 – Principais diretórios de uma aplicação Grails. .................................................... 46

Tabela 4.1 – Product Backlog .................................................................................................. 57

Tabela 4.2 – Sprint Backlog ..................................................................................................... 58

Page 8: 2011-Introdução ao Framework Grails

LISTA DE ABREVIATURAS E SIGLAS

COC Convention Over Configuration (Convenção sobre Configuração)

CPD Centro de Processamento de Dados

CRUD Create – Read – Update – Delete (Criar-Ler-Editar-Excluir)

CSS Cascading Style Sheets

DI Dependency Injection (Injeção de Dependências)

DRY Don‟t Repeat Your Self (Não se repita)

GORM Grails Object Relational Mapping (Mapeamento Objeto-Relacional do Grails)

GSP Groovy Server Pages

HTML Hyper Text Markup Language (Linguagem de Marcação de Hipertexto)

HTTP Hyper Text Transfer Protocol (Protocolo de Transferência de Hipertexto)

IDE Integrated Development Environment (Ambiente Integrado de

Desenvolvimento)

IoC Inversion of Controll (Inversão de Controle)

J2EE Java 2 Platform, Enterprise Edition (Plataforma Java 2, Edição Empresarial)

JDK Java Development Kit (Kit de Desenvolvimento Java)

JEE Java Enterprise Edition (Java Edição Empresarial)

JVM Java Virtual Machine (Máquina Virtual Java)

KISS Keep It Simple and Short (Mantenha-o Simples e Curto)

MOP Meta-Object Protocol (Protocolo de Meta-Objeto)

MVC Model – View - Controller (Modelo – Visão – Controlador)

OO Orientação a Objetos

PC Personal Computer (Computador Pessoal)

PHP Hypertext Preprocessor ou Personal Home Page

RoR Ruby on Rails

SQL Struct Query Language (Linguagem de Consultas Estruturada)

TDD Test Driven Development (Desenvolvimento Direcionado a Testes)

UML Unified Modeling Language (Linguagem Unificada de Modelagem)

URL Uniform Resource Location (Localização de Recurso Uniforme)

WAR Web Archive (Arquivo Web)

XML eXtensible Markup Language (Linguagem de Marcação Estendida)

XP eXtreme Programming (Programação Extrema)

Page 9: 2011-Introdução ao Framework Grails

RESUMO

Com o apoio de um conjunto de tecnologias de sucesso no mercado de

desenvolvimento e baseado em Ruby on Rails, o framework Grails caracteriza-se como a

melhor solução no modelo de desenvolvimento ágil para a plataforma Java na web. Este

trabalho apresenta uma introdução a ferramenta, apresentando suas funcionalidades,

principais tecnologias e o desenvolvimento prático de uma aplicação que demonstrará a

utilização desses poderosos recursos.

Page 10: 2011-Introdução ao Framework Grails

ABSTRACT

With the support of a set of technologies on the successful market of software

development and based on Ruby on Rails, Grails framework is characterized as the best

solution for an agile development model for the Java platform on the web. This paper aims to

provide an introduction to the tool, showing its features, key technologies and the

development of a practical application that will demonstrate the use of these powerful

resources.

Page 11: 2011-Introdução ao Framework Grails

SUMÁRIO

1 INTRODUÇÃO .................................................................................................. 13

1.1 MOTIVAÇÃO .................................................................................................. 13

1.2 OBJETIVO ...................................................................................................... 13

1.3 JUSTIFICATIVA ............................................................................................... 14

1.4 METODOLOGIA DE PESQUISA ......................................................................... 14

1.5 ORGANIZAÇÃO DO TEXTO .............................................................................. 15

2 O UNIVERSO DE GRAILS .............................................................................. 16

2.1 HISTÓRICO DA COMPUTAÇÃO ........................................................................ 16

2.2 DESENVOLVIMENTO ÁGIL .............................................................................. 18

2.3 FRAMEWORKS ............................................................................................... 20

2.4 O PADRÃO MVC. ........................................................................................... 21

2.5 JAVA VS. RUBY ON RAILS ............................................................................. 22

3 O FRAMEWORK GRAILS .............................................................................. 26

3.1 O QUE É GRAILS? .......................................................................................... 26

3.1.1 Origem do Grails ...................................................................................... 27

3.1.2 Groovy + Ruby on Rails = Grails ............................................................ 28

3.2 GROOVY: A LINGUAGEM DO GRAILS ............................................................. 29

3.2.1 O que é Groovy? ...................................................................................... 29

3.2.2 Groovy e Java: Comparação e Integração .............................................. 30

3.2.3 Por dentro do Groovy .............................................................................. 32

3.2.4 Closures ................................................................................................... 35

3.3 GRAILS: ALGUMAS TECNOLOGIAS................................................................. 37

3.3.1 Spring ....................................................................................................... 37

3.3.2 Hibernate .................................................................................................. 38

3.3.3 SiteMesh ................................................................................................... 39

3.3.4 Outras Tecnologias .................................................................................. 42

3.4 CONHECENDO O GRAILS................................................................................ 43

3.4.1 Começando com Grails ............................................................................ 43

Page 12: 2011-Introdução ao Framework Grails

3.4.2 Estrutura de Diretórios e o Padrão MVC ................................................ 44

3.4.3 Persistência de Dados no Grails .............................................................. 47

3.4.4 Scaffold: Problema ou Solução? .............................................................. 49

3.4.5 A camada de Visualização ........................................................................ 51

3.5 CASOS DE SUCESSO ....................................................................................... 53

4 ESTUDO DE CASO ........................................................................................... 55

4.1 DESCRIÇÃO DO PROBLEMA ........................................................................... 55

4.2 O SISTEMA ..................................................................................................... 55

4.2.1 Desenvolvendo em Scrum ........................................................................ 56

4.2.2 Preparando o ambiente para o sistema................................................... 59

4.2.3 Classes de domínio e Controladores ....................................................... 59

4.2.4 Provendo Segurança do Sistema ............................................................. 62

4.2.5 Desenvolvendo direcionado a Testes ...................................................... 63

4.2.6 Conectando ao Banco de Dados ............................................................. 65

4.2.7 Visualizações da aplicação ..................................................................... 66

4.2.8 Trabalhando com plugins ........................................................................ 69

4.2.9 Implantando a aplicação ......................................................................... 70

5 CONSIDERAÇÕES FINAIS ............................................................................. 73

5.1 CONCLUSÕES ................................................................................................ 73

5.2 TRABALHOS FUTUROS ................................................................................... 74

REFERENCIAS BIBLIOGRÁFICAS......................................................................75

ANEXOS A - CÓDIGO FONTE................................................................................77

Page 13: 2011-Introdução ao Framework Grails

13

1 INTRODUÇÃO

1.1 MOTIVAÇÃO

A área de tecnologia da informação está cada dia buscando novos caminhos e formas

de tornar cada vez mais simples e ágil os processos de desenvolvimento de produtos de

software. Esta é uma necessidade exigida por um mercado cada vez mais informado e com

maior necessidade de rápidos resultados que proporcionem rápidas, porém eficientes,

decisões. A internet cada vez mais ao alcance de todos e o advento de dispositivos móveis

com acesso à mesma traz aos programadores de softwares mais oportunidades e desafios de

desenvolver para a plataforma WEB. Dentro desta premissa surge à necessidade por

ferramentas de desenvolvimento que se adequem a realidade atual.

No estudo das ferramentas de desenvolvimento de software é difícil negar a

importância da plataforma Java no mercado. Mas como acompanhar o ritmo do mercado atual

e ultrapassar os problemas apresentados pela plataforma sem abandonar seu grande poder de

produtividade?

Nessa busca por soluções, com destaque para o desenvolvimento web, criam-se

frameworks e linguagens alternativas como ferramentas que possibilitem o aproveitamento do

que já fazia sucesso acrescentando características inovadoras que podem garantir a

continuidade desse mesmo sucesso.

1.2 OBJETIVO

Objetiva-se mostrar a importância do framework Grails e da linguagem de

programação Groovy para desenvolvimento de soluções de software no atual mercado

tecnológico, visando demonstrar e comparar as novas ferramentas com as já existentes, e

trazer a imensa gama de desenvolvedores da plataforma Java soluções que permitam uma

maior capacidade competitiva.

Page 14: 2011-Introdução ao Framework Grails

14

No estudo da linguagem Groovy pretende-se conhecer suas principais características e

entender de que forma a mesma pode trazer aos atuais profissionais da área melhorias nos

projetos de desenvolvimento de software. Na análise e conhecimento do framework Grails

pretende-se entender como funcionam seus processos, estruturas e propriedades e demonstrar

o que de novo o mesmo apresenta ao mercado de desenvolvimento web através de um

desenvolvimento prático.

1.3 JUSTIFICATIVA

O avanço da Internet trouxe ao mercado de tecnologia da informação uma migração

dos sistemas desktop para os sistemas web. Nesta atual realidade justifica-se a necessidade de

novos recursos e ferramentas que permita ao mercado de software estar apto a competir num

mundo globalizado, onde a informação está cada vez mais acessível e a perca da mesma pode

levar muitos negócios à falência.

Levando em conta o citado acima, é importante levar ao conhecimento de todos as

ferramentas criadas no intuito de agilizar os processos de desenvolvimento de software, sem

causar aos atuais sistemas existentes grandes mudanças. Permitir ao desenvolvedor o

desenvolvimento ágil de aplicações de forma com que esteja preparado para acompanhar o

atual mercado e seu futuro próximo.

Justifica-se ainda o intuito de deixar conteúdo e conhecimento de soluções de

desenvolvimento ágil para web numa transição simples de uma das plataformas de

desenvolvimento de software mais comuns nos dias de hoje para o que pode vir a ser o

dominante no mercado futuro.

1.4 METODOLOGIA DE PESQUISA

A metodologia a ser utilizada nesta pesquisa caracteriza-se principalmente como

bibliográfica e dentro deste contexto têm-se como fontes de pesquisas a consulta a livros,

artigos e estudo de caso.

Serão utilizados os métodos lógicos dedutivo, hipotético-dedutivo no contexto da

análise das ferramentas de desenvolvimento de software em estudo e, para demonstrar a

Page 15: 2011-Introdução ao Framework Grails

15

evolução e o atual cenário tecnológico do desenvolvimento de software, serão utilizados os

métodos auxiliares histórico, comparativo e estatístico.

No tipo de pesquisa utilizada a bibliográfica é privilegiada por tratar-se de um estudo

sobre uma ferramenta de software. No entanto para exemplificar e auxiliar no entendimento

do assunto pretende-se utilizar estudo de caso para o desenvolvimento de uma aplicação

modelo.

1.5 ORGANIZAÇÃO DO TEXTO

O texto está organizado em 5 capítulos com a intenção de apresentar uma introdução

as principais tecnologias do framework em estudo e um apanhado histórico do universo que o

originou, além de um exemplo prático através de um estudo de caso.

O Capitulo 2 traz uma apresentação do universo que envolve o framework Grails, o

histórico da computação e das ferramentas de software, a definição de framework, o ambiente

de desenvolvimento ágil, o padrão de projeto utilizado e as inspirações e influencias de Java e

Ruby on Rails.

O Capitulo 3 abrange o ponto principal da pesquisa apresentando o framework Grails,

seu histórico, características e suas principais tecnologias e mostra um apanhado básico da

linguagem de programação Groovy que é utilizada pelo framework, salientando sua

integração com Java e fazendo comparações com a mesma.

O Capitulo 4 traz um estudo de caso com o desenvolvimento de um sistema seguindo

as diretrizes do modelo ágil e encerrando o conteúdo da pesquisa, seguido das considerações

finais no Capitulo 5.

Page 16: 2011-Introdução ao Framework Grails

16

2 O UNIVERSO DE GRAILS

2.1 HISTÓRICO DA COMPUTAÇÃO

A história da computação como conhecemos hoje teve seu início há quase meio século

atrás quando os primeiros microcomputadores PC‟s (Personal Computers) foram introduzidos

no mercado, mas a idéia da construção de uma máquina capaz de executar operações e

cálculos é bem antiga tendo seu início nos esforços de Pascal, Leibnitz e Babbage [RODR

02].

A partir da introdução dos computadores pessoais a tecnologia da informação

começou a passar por um processo de transformação cada vez mais acelerado saindo do

antigo modelo centralizado pelas Centrais de Processamento de Dados (CPD‟s) até chegar ao

atual ambiente totalmente descentralizado e cada vez mais virtual. Foi com a introdução dos

PC’s na década de 1980 que a revolução começou, com a disseminação das redes locais

utilizando alta velocidade de comunicação e conexão com outras redes locais e de longa

distância.

Com a popularização dos ambientes de redes dentro das organizações os CPD‟s

iniciaram o processo de extinção e a década de 1990 iniciou com um ambiente de

processamento de dados mais dinâmico e distribuído. Foi também na década de 1990 que a

rede mundial de computadores, criada na década de 1960 pelos militares americanos, deixou

de ser apenas de uso das universidades e instituições militares e se tornou popular entre os

usuários comuns com o uso do correio eletrônico e das home-pages.

A disseminação da Internet trouxe uma nova era tecnológica, o ambiente

computacional, que nos seus primórdios se caracterizava pelos CPD‟s, passou pelo Time

Sharing (sistemas computacionais de tempo compartilhado), pelas redes Lan’s, pela

arquitetura Cliente/Servidor e hoje com a difusão da internet vive a denominada Computação

em nuvem, onde o processamento de informações é cada vez mais virtual.

A figura 2.1 mostra os estágios de evolução do ambiente tecnológico.

Page 17: 2011-Introdução ao Framework Grails

17

Figura 2.1 – A evolução da Tecnologia da Informação

Fonte: [RODR 02]

Desde sua criação o objetivo principal de um computador é realizar o processamento

de dados, para que tal objetivo fosse satisfeito é que surgiram os programas de computador.

No entanto passar ao computador os problemas a serem resolvidos, ou seja, criar os

programas necessitava de algo que traduzisse esses problemas na linguagem do computador, a

isso se deu o nome de Linguagens de Programação.

A primeira idéia de uma linguagem de programação que expressasse instruções para o

computador veio de Ada Lovelace para o projeto de computador de Charles Babbage, o

projeto não foi concretizado e a idéia da linguagem de Ada não chegou a ser testada. Tempos

depois várias outras linguagens de programação foram surgindo, mas sem grandes impactos,

até o surgimento da primeira grande linguagem de alto nível, o Fortran em 1954. Seguiu-se

ao Fortran o surgimento do COBOL e LISP, também linguagens de alto nível que são assim

conhecidas por apresentarem uma proximidade maior a língua humana.

Foi nas décadas de 1960 e 1970 que uma grande revolução iniciou-se em meio as

linguagens de programação, surgiam as linguagens Pascal, C e Smalltalk entre tantas outras e

Page 18: 2011-Introdução ao Framework Grails

18

também na mesma época surgia um novo paradigma de programação conhecido como

Orientação a Objetos. A programação orientada a objetos trouxe grandes mudanças no

desenvolvimento de software que antes era dominado pelo paradigma estruturado das

linguagens como Pascal e C, onde era priorizada a criação de estruturas simples, usando sub-

rotinas e funções. Na programação orientada a objetos as diversas unidades de software são

chamadas de objetos, esses objetos agregam o comportamento do que representam, e o fluxo

de execução neste tipo de programa é feito através de troca de mensagens entre os objetos.

A década de 1990 foi destaque pelo grande aumento da popularidade da internet e

nessa época começou a surgir a necessidade de linguagens que criassem aplicações para o

meio virtual fazendo a história das linguagens de programação subir mais um degrau na

escala de evolução. Foi nessa época que surgiram as linguagens como Java e PHP seguidas

pelas linguagens dinâmicas, ou linguagens de script, que viriam a dominar o mercado nos

anos 2000, como Ruby, Python e Groovy.

As linguagens dinâmicas são linguagens de alto nível, com tipagem dinâmica, ou seja,

cujo tipo da variável é definido em tempo de execução. Essas linguagens, como todos os

outros tipos de linguagens de programação, apresentam suas vantagens e desvantagens

dependendo da situação em que são empregadas. O destaque desse tipo de linguagem se dá a

necessidade do mercado que atualmente exige resultados cada vez mais rápidos sem perder

eficiência. O histórico das linguagens de programação mostra que no decorrer dos anos a

tecnologia se adapta as necessidades surgidas sem necessariamente definir uma regra, mas

não se deve negar a importância do desenvolvedor conhecer mais do que uma linguagem de

programação.

O seu conhecimento das linguagens de programação é a chave

para o seu portfólio pessoal como um desenvolvedor de software.

[KÖNI 07]

2.2 DESENVOLVIMENTO ÁGIL

Desde a década de 1970 o desenvolvimento de softwares vivia uma crise no que dizia

a respeito a gestão de seus projetos. Ferramentas tradicionais de gerência de projetos não

Page 19: 2011-Introdução ao Framework Grails

19

conseguiam suprir as necessidades que os projetos de software apresentavam como prazo,

orçamento e as constantes mudanças de escopo no decorrer do desenvolvimento.

Motivados pela busca de uma solução para esses problemas, um grupo de pensadores

da área de engenharia de software se juntou no final dos anos 90 e início dos anos 2000 para

criar uma metodologia correta para lidar com os projetos de software. Do encontro em

Fevereiro de 2001 em Utah nasceu o que chamamos de Manifesto Ágil, manifesto esse que

deu origem ao segmento de Desenvolvimento Ágil.

O manifesto ágil consiste de um conjunto de valores a serem seguidos pelos

envolvidos nos processos de desenvolvimento de software, criado por 17 fundadores num

grupo formado por importantes engenheiros de software e autores de importantes publicações

da área. O manifesto consistia, basicamente, de quatro grandes premissas:

1. Indivíduos e Interações mais que processos e ferramentas.

2. Software funcionando mais que documentação abrangente.

3. Colaboração com cliente mais que negociação de contratos

4. Resposta a mudança mais que seguir um plano.

A essas premissas segue-se um conjunto de 12 princípios que aqueles que desejam

empregar o desenvolvimento ágil devem seguir. Com o surgimento do manifesto ágil o

mercado de desenvolvimento de software começou a ganhar novo impulso e, movido pelo

crescimento cada vez maior do número de usuários da internet, ferramentas que se

adequavam mais a esse novo ambiente de desenvolvimento foram surgindo.

A maioria das linguagens de programação e framework surgidos nos anos 2000 vieram

preparadas para esse novo ambiente, prontos para facilitar cada vez mais o trabalho dos

desenvolvedores. Finalmente os processos de criação de software ganharam novos olhares e a

função do programador passou a ser vista como um trabalho criativo e não mais algo

regidamente padronizado.

Com o desenvolvimento ágil surgiram metodologias como Scrum e Extreme

Programming (XP) que permitiram as equipes de desenvolvimento se focar ao que realmente

interessava. Com o cliente do lado, programadores, testadores e a equipe como um todo

passaram a saber exatamente o que deveriam fazer. O prazo pode ser estimado e o escopo não

necessitou mais ser totalmente fechado.

Page 20: 2011-Introdução ao Framework Grails

20

Hoje se observa, no entanto, que muitas organizações que dizem trabalhar com

Desenvolvimento Ágil estão na verdade empregando de maneira errada o que prega o

manifesto. “... usar as ferramentas apenas como ferramentas, não funciona se os valores não

foram entendidos” [MORE 09]. O desenvolvimento ágil não significa garantia de sucesso,

mas representa um avanço na gestão de projetos de software como nunca visto antes.

2.3 FRAMEWORKS

Os frameworks tem papel importante no atual mercado de software e há uma

imensidão deles para as mais diversas plataformas, mas muita confusão ainda existe sobre o

que realmente são. Entende-se por framework de software o conjunto de classes

implementadas em uma linguagem de programação especifica provendo uma funcionalidade

genérica que auxilia no desenvolvimento de software [DEPA 10].

Existe a confusão por parte de alguns entre framework e bibliotecas de classes. Nos

frameworks, ao contrário das bibliotecas de classes, as classes são dependentes e possui um

modelo de colaboração entre si que livra o projetista da preocupação de saber quando chamar

cada método, por exemplo. Nas bibliotecas de classes cada classe é única e não é possível o

conhecimento do domínio, sendo este feito apenas pelas próprias aplicações que criam as

colaborações entre tais classes.

Isso representa apenas uma das vantagens do uso de frameworks, possibilitando aos

desenvolvedores componentes integrados e permitindo que os mesmos gastem seu tempo

ocupando-se da lógica de negócios e não dos detalhes técnicos. Além disso, os frameworks

caracterizam-se por serem partes mais concisas de software o que possibilita uma maior

facilidade na detecção de erros.

Acima de tudo o uso de framework poupa muito o trabalho do desenvolvedor

eliminando a perca de tempo com coisas que não o interessam, mesmo sendo importantes.

Muito da configuração do projeto de software é resolvido quase que automaticamente pela

maioria dos frameworks atuais, trazendo aos projetos maior agilidade, maior lucro,

antecipação de entrega e satisfação dos clientes. Atualmente nota-se que muitos frameworks

Page 21: 2011-Introdução ao Framework Grails

21

destacaram-se de tal forma que já chegam ao patamar de plataforma de programação devido

ao grande número de funcionalidades e facilidades que eles proporcionam.

2.4 O PADRÃO MVC.

Todo processo de desenvolvimento de software segue um conjunto de regras que

visam organizar, documentar e facilitar o trabalho do desenvolvedor, dentro desta premissa é

que surgem os padrões. Um desses padrões, conhecido por MVC (Model-View-Controller)

tem destaque principalmente no desenvolvimento para Web.

O padrão MVC consiste em dividir a estrutura da aplicação em 3 (três) camadas:

Modelo, Visualização e Controlador. Essa divisão visa separar a lógica de negócio da camada

de apresentação e do fluxo da aplicação e dessa forma garantir maior “independência” do

código. Cada uma dessas camadas possui funções, objetivos e escopos diferentes e cada uma

delas pode ser alterada separadamente sem muito interferir na outra [MACO 10].

A primeira camada correspondente ao Modelo da aplicação é a responsável por

guardar as informações dos dados, os atributos e métodos de uma classe e seus respectivos

tipos.

A camada de Controle é responsável pelo fluxo da aplicação, a interação entre usuário

e sistema controlando todas as operações da aplicação.

A terceira camada é a de Visualização, responsável pela interface da aplicação.

Também conhecida como camada de apresentação a visualização determina como os dados

do modelo são mostrados ao usuário.

A interação entre as três camadas do padrão MVC pode ser melhor entendida pela

análise da Figura 2.2.

Page 22: 2011-Introdução ao Framework Grails

22

Figura 2.2 – O padrão MVC

Como demonstra a figura acima, a camada de Modelo é acessada pelas duas demais

por conter em si o modelo de dados no qual a camada de Controle e de Visualização se

baseiam para criar suas funcionalidades. O Controlador da aplicação, responsável pelas

principais funcionalidades da aplicação é a camada que controla a interação entre as demais.

O padrão MVC tem sido exigência em muitas plataformas de desenvolvimento sendo,

em algumas, imprescindível o seu conhecimento. Muitos frameworks tem sua estrutura

construída no formato do padrão separando em três camadas distintas as classes e demais

arquivos pertinentes a Modelo, Visualização e Controle.

2.5 JAVA VS. RUBY ON RAILS

Em 1991 a Sun Microsystems dava inicio a um projeto que objetivava antecipar o que

previa ser tendência no mercado tecnológico futuro. A idéia era preparar a convergência dos

computadores com os eletrodomésticos utilizados no dia-a-dia com a criação de um

dispositivo que funcionasse como um controle remoto desses equipamentos. Mais tarde

observou-se que tal projeto era muito avançado para época e a recusa do mercado fez a

empresa buscar outra utilidade para o projeto. James Gosling, um dos integrantes da equipe de

13 pessoas que trabalharam arduamente no projeto, criou uma linguagem de programação

orientada a objetos que pudesse ser executada no aparelho, essa linguagem era independente

Page 23: 2011-Introdução ao Framework Grails

23

de plataforma e fortemente inspirada na linguagem C, na época a linguagem recebera o nome

de Oak, mas logo teve que ser mudado quanto se descobriu já existir linguagem de

programação com tal nome.

Em meados da década de 1990, a internet encontrava-se em seu momento de

popularidade, estabelecendo assim uma grande rede interativa e a oportunidade ideal para Sun

Microsystems empregar todo o potencial da linguagem por traz do seu ambicioso projeto. Em

1995 nascia a nova versão do Oak, rebatizada de Java e trazia para o WWW (Word Wide

Web) uma interatividade nunca antes vista, permitindo execução de conteúdo multimídia

direto do navegador.

As vantagens do Java eram muitas, mas o destaque maior era a possibilidade de

escrever uma vez e executar em qualquer local, e por proporcionar uma maior interatividade

na web. A portabilidade que a linguagem proporcionava vinha de sua máquina virtual, a JVM

(Java Virtual Machine). Com a JVM, os programas escritos em Java podiam funcionar em

qualquer plataforma de hardware ou software que possuía uma versão da mesma instalada

tornando as aplicações independentes da plataforma onde funcionam. O sucesso do Java foi

absoluto e rapidamente cresceu o número de usuários da plataforma fazendo grandes

empresas passar a oferecer suporte ao Java [SIER 05].

Em 1999 foi criada a plataforma Java Enterprise Edition (JEE ou J2EE) visando

principalmente a internet e os softwares corporativos. O JEE, mas recentemente chamado de

J2EE consiste em um conjunto de padrões de desenvolvimento que oferecem recursos

(bibliotecas) e funcionalidades para programar software distribuído. O surgimento do J2EE

representou uma grande evolução para o Java trazendo grande produtividade a linguagem. A

introdução do desenvolvimento em camadas, que trouxe maior segurança e organização ao

código.

O sucesso da linguagem fez crescer o número de desenvolvedores Java que no início

dos anos 2000 já dominava o mercado de software. Todavia existiam na plataforma algumas

desvantagens que começavam a por em risco tal sucesso. Essas desvantagens destacavam-se

principalmente por:

Alto nível de complexidade;

Grande consumo de tempo;

Page 24: 2011-Introdução ao Framework Grails

24

Tarefas repetitivas;

E a falta de uma diretiva nítida a respeito de quais convenções seguir.

Para ajudar a resolver esses problemas vários frameworks eram criados, sendo o Struts

a melhor referência de sucesso e responsável por influenciar muitos dos frameworks que

surgiram após seu lançamento. O objetivo básico desses frameworks era facilitar o

desenvolvimento de aplicações web na plataforma Java, diminuindo sua complexidade e

aumentando significativamente sua produtividade, mas alguns problemas ainda se repetiam.

Até que o início de um movimento que revolucionaria novamente o ramo se iniciou e uma

nova plataforma de desenvolvimento para web se mostrava promissora a ser grande

concorrente da plataforma J2EE.

Na mesma época do surgimento do Java, outra linguagem era concebida no outro lado

do globo. Em 1993, no Japão, Yukihiro Matsumoto criara uma linguagem que combinava

programação funcional com programação imperativa, cujo objetivo era “ser mais poderosa

que o Perl e mais orientada a objetos que o Python”. Apresentada ao público em 1995, o Ruby

era uma linguagem dinâmica, totalmente orientada a objetos e com grande expressividade e

foi justamente sua expressividade que mais tarde levou o dinamarquês David Heinemeier

Hansson, a utilizá-la para criar um framework objetivando a agilidade e praticidade do

desenvolvimento web.

Hansson criou o Rails inicialmente para um projeto de sua empresa, a 37signals, e

passou a incentivar o uso do mesmo em comunidades da web. Em 2006, o RoR começou a se

popularizar entre os desenvolvedores, disputando com PHP, Python e Java o mercado de

desenvolvimento para web [BARR 09].

Adotando princípios ágeis como Don’t Repeat Yourself (DRY) e Convention over

Configuration (CoC) que tratam, respectivamente, sobre reaproveitamento de código e foco

na convenção com o mínimo de configuração e, utilizando a estrutura em camadas do padrão

MVC, o RoR representou uma ameaça maior ao Java principalmente pelas seguintes

características:

Stack completo: componentes pré-integrados, eliminando a necessidade de

integrar cada componente necessário a uma aplicação;

Page 25: 2011-Introdução ao Framework Grails

25

Scaffold: eliminando a repetição de tarefas, criando a base para construção da

aplicação;

Expansibilidade: permitindo criar plugins, de maneira intuitiva, para recursos que

a linguagem não oferece.

O Ruby on Rails trouxe ao mercado de desenvolvimento web a solução de uma

exigência atual, incentivada principalmente pelo Manifesto Ágil de Fevereiro de 2001: A

necessidade de criar ferramentas que permitissem o desenvolvimento de aplicações eficientes

de maneira ágil. Uma aplicação simples em Rails pode ser criada em tempo mínimo e a

imensa comunidade de desenvolvedores que a plataforma apresenta possibilita a troca de

informações que torna o RoR cada vez mais poderoso.

Dentro deste universo ágil os desenvolvedores Java começaram a procurar soluções

para manter a plataforma dentro do que o mercado exigia e assim continuar usufruindo da

enorme quantidade de bibliotecas que o Java apresentava. Surgiu então o projeto JRuby que

seria uma implementação de Ruby dentro da plataforma Java além do projeto Jython, mesma

idéia do anterior só que em Python. Os projetos não tiveram grande aceitação devido a grande

diferença no código de ambas para o que se estava acostumado no Java.

A solução seguinte veio na forma de um novo framework baseado no RoR e utilizando

uma linguagem que não era Java apenas por algumas diferenças, o Groovy, que será mostrada

mais adiante. Groovy com Rails deu origem ao Grails que veio para enfim deixar a

plataforma Java em pé de guerra com os novos modelos de desenvolvimento web.

Page 26: 2011-Introdução ao Framework Grails

26

3 O FRAMEWORK GRAILS

3.1 O QUE É GRAILS?

Grails é um framework open source para desenvolvimento de aplicações web na

plataforma Java criado com o intuito de fornecer a mesma um maior nível de abstração, com

enfoque em seguir convenções no lugar de configurar sempre e numa sintaxe mais expressiva

e limpa proporcionada pela linguagem na qual se baseia, a linguagem dinâmica Groovy.

Grails se baseia em ferramentas como Ruby on Rails, Django e TurboGears

assumindo princípios Dry (Don’t Repeat Yourself), CoC (Convention over Configuration) e

KISS (Keep It Simple and Short) que regem as principais características das ferramentas

ágeis. Características essas como:

Evitar tarefas repetitivas;

Necessidade mínima de configuração através do enfoque em seguir uma

convenção;

Proporcionar código simples, pequeno e limpo;

Desenvolvimento em camadas utilizando padrões de projeto como o MVC

(Model-View-Controller).

Grails foi desenvolvido no topo da plataforma Java o que lhe permite uma grande

integração com frameworks, bibliotecas e até uso de código Java. Apresenta um ambiente

completo de desenvolvimento sem a necessidade de preocupar-se com a configuração de

outras ferramentas como servidores de aplicação, por exemplo. Além disso, Grails tem a seu

lado os poderosos e maduros frameworks Hibernate, para mapeamento objeto-relacional

(ORM – Object Relational Mapping), e Spring, para inversão de controle (IoC – Inversion of

Controll), com os quais apresenta um enorme nível de integração. A alta produtividade e

enorme quantidade de funções e ferramentas que apresenta dão ao Grails características de

plataforma em lugar de apenas um framework. Além da compatibilidade com as duas

ferramentas já mencionadas Grails tem ainda em seu quadro outras populares tecnologias de

código aberto como:

Page 27: 2011-Introdução ao Framework Grails

27

SiteMesh para processamento de layout;

Jetty e Tomcat como servidores web;

HSQLDB para banco de dados de testes e desenvolvimento;

JUnit para testes, entre outros.

Grails é a solução ágil para plataforma Java na web mais bem sucedida trazendo a

imensa gama de desenvolvedores menos preocupação com detalhes desnecessários que

consumiam tempo do que realmente era importante preocupar-se e tornando novamente

divertido o desenvolvimento na plataforma robusta e poderosa que é o Java.

3.1.1 Origem do Grails

A busca por soluções em ferramentas para o desenvolvimento de aplicações web na

plataforma Java que proporcionasse pouca escrita de código, zero de retrabalho e rápidos

resultados levou um grupo de desenvolvedores americanos a, em 2005, iniciar o projeto de

criação de um framework baseado em Ruby on Rails e utilizando a linguagem dinâmica

Groovy. Surgia assim o Grails, cuja versão 1.0 viria a ser disponibilizada em 2006.

Graeme Rocher trabalhava com Java no desenvolvimento de sistemas de gestão de

aprendizagem quando cansado da enorme quantidade de trabalho que poderia ser evitado lhe

fez questionar se não havia soluções mais simples e rápidas para fazê-los. Mais tarde, quando

começou a trabalhar com TV Digital, Graeme conheceu o Groovy e já era bastante amigável

as poucas regras das linguagens dinâmicas e ao pouco trabalho e tempo que proporcionavam.

No entanto, até o surgimento do Groovy em 2003, nenhuma ferramenta parecia fazer bom uso

de tudo o que já proporcionava a plataforma Java. Tempos depois surgia no mercado web o

framework Ruby on Rails mostrando-se promissor a ser um grande concorrente da plataforma

Java e baseado em uma linguagem até então pouco conhecida entre a maioria dos

desenvolvedores, a linguagem Ruby.

Graeme juntou-se a Steven Devijver e Guillaume Laforge fundando o projeto que se

inspirava nos princípios de RoR e utilizava a linguagem Groovy para assim criar o framework

web Grails.

Page 28: 2011-Introdução ao Framework Grails

28

O objetivo era trazer para plataforma Java na web todas as vantagens que as

ferramentas ágeis como RoR, Django entre outras apresentavam e juntar isso ao poder do Java

com sua enorme biblioteca de classes, a enorme quantidade de tecnologias que já possuía e

toda a portabilidade proporcionada pela sua conhecida máquina virtual. Grails surgiu para se

unir ao poder do Java, trazendo soluções que outras ferramentas não conseguiram ajudando a

manter ainda por muito tempo o sucesso que a plataforma já apresentava com uma enorme

gama de desenvolvedores e empresas que não parecem dispostos a abandonar seu poderio.

Grails foi desenvolvido em código aberto, característica comum das ferramentas ágeis,

e após a disponibilização da versão 1.0, a comunidade do framework iniciou atividades e

vários desenvolvedores se juntaram ajudando na melhora do mesmo, criando plugins e

adicionando tecnologias que forneciam suporte ao desenvolvimento em Grails. Hoje vários

são os casos de sucesso que utilizaram Grails no desenvolvimento de aplicações.

Na criação do projeto em 2005, Graeme co-fundou a empresa G2One ao lado de

Guillaume Laforge e Alex Tkachman oferecendo consultoria, treinamento e suporte para as

tecnologias Groovy e Grails. Em 2008, a SpringSource adquiriu a G2One e Graeme junto dos

demais colegas juntou-se a empresa que já era responsável por outras tecnologias do mundo

Java. Grails hoje possui uma enorme quantidade de plugins e várias IDEs que facilitam o

desenvolvimento de aplicações em sua „plataforma‟ entre elas o Netbeans e o Eclipse.

3.1.2 Groovy + Ruby on Rails = Grails

Em 2005 quando iniciava o projeto de criação do Grails, Graeme e sua equipe

batizaram o projeto de Groovy on Rails, devido a forte inspiração nos conceitos e princípios

do RoR, no entanto, David Hansson, criador do Rails pediu para que o nome fosse alterado,

fazendo mudarem para o atual Grails.

Foi a capacidade do Ruby on Rails de gerar soluções rápidas e simples apenas

seguindo convenções sem a necessidade de geração de arquivos XML a todo o momento,

além de apresentar um ambiente completo de desenvolvimento, que fez Graeme se interessar

no que o framework tinha a oferecer. Além disso, RoR apresentava todo o poder e

organização do desenvolvimento em camadas através do padrão MVC, a capacidade de

Page 29: 2011-Introdução ao Framework Grails

29

transformar trabalhos repetitivos da geração de CRUD em uma única linha de comando e

possibilitar ao desenvolvedor criar suas próprias soluções quando o mesmo não as oferecia,

através da expansibilidade. Ruby on Rails parecia resolver todos os problemas que o

desenvolvimento em J2EE apresentava. Mas como fazer uso dessas soluções sem abandonar

tudo o que Java já proporcionava?

Antes do surgimento do Grails outras soluções ágeis para a plataforma Java foram

pensadas e algumas com grande sucesso. Uma dessas soluções foi implementar Ruby

(linguagem dinâmica do RoR) em Java criando o JRuby, porém a diferença da sintaxe de

Ruby para Java afastou muitos programadores devido a enorme curva de aprendizado

apresentada. O JRuby é ainda utilizado como solução para muitos casos mesmo não tendo

uma aceitação total no mundo Java.

Assim como Ruby, uma solução em linguagem Python veio através de Jython que

trazia soluções dinâmicas para plataforma Java, mas o problema continuava e os

desenvolvedores Java continuavam desanimados com o trabalho de aprender uma sintaxe

totalmente nova. Foi somente com a criação do Groovy que soluções dinâmicas começaram a

mostrar real sucesso na plataforma Java.

A enorme semelhança e integração de Groovy com Java diminuíam quase totalmente a

curva de aprendizado para os desenvolvedores da plataforma. Juntar Groovy com Rails foi a

idéia de Graeme para tirar proveito de duas das plataformas de desenvolvimento mais

poderosas da atualidade: Java e Ruby on Rails.

3.2 GROOVY: A LINGUAGEM DO GRAILS

3.2.1 O que é Groovy?

Groovy é uma linguagem de programação ágil e dinâmica para

a plataforma Java com muitas características inspiradas em linguagens

como Python, Ruby e Smalltalk, disponibilizando-as para os

desenvolvedores utilizando uma sintaxe similar a do Java [SMIT 09].

Page 30: 2011-Introdução ao Framework Grails

30

Groovy surgiu da idéia de um programador Java de trazer para a plataforma uma

sintaxe mais expressiva e comportamento dinâmico. Trabalhar dinamicamente na plataforma

Java foi o diferencial proposto por James Strachan quando criou a linguagem, desta forma

Groovy aproveitaria todo poder de uma plataforma robusta e bem aceita no mercado como o

Java e acrescentaria as vantagens das linguagens dinâmicas.

É comum muitos ainda chamarem Groovy de „apenas mais uma linguagem de script

para plataforma Java‟ e é verdade que a linguagem se sai muito bem executando scripts, mas

seu mérito maior não é esse. Ser a linguagem dinâmica mais amigável com a plataforma Java

é o que dá ao Groovy um grande potencial. Groovy é tão integrado com Java que alguns

ousam a dizer que „Groovy é Java‟. Groovy oferece uma gama de possibilidades que é um

erro afirmar que se trata de apenas uma linguagem de script.

A linguagem Groovy assim como o Java é orientada a objetos, mas também permite

que se trabalhe de forma procedural, pode ser compilada para bytecode Java, pode ser

integrada a aplicações Java sem grandes complicações e faz uso de toda a variedade de classes

que a biblioteca Java oferece, além dos frameworks. Cada tipo de Groovy é um subtipo de

java.lang.Object e cada objeto é uma instância deu um tipo na forma normal. Por exemplo,

um tipo data em Groovy é um java.util.Date [SMIT 09].

Falar da integração de Groovy com Java é pouco e pode levar a se entender que a

linguagem é apenas Java com poucas adições, já que boa parte do que Groovy faz pode ser

feito em Java. Porém a maioria do trabalho que o Java obriga ao desenvolvedor gastar tempo

se preocupando, Groovy faz nos bastidores conseguindo assim a agilidade e dinamismo que

caracterizam a linguagem.

3.2.2 Groovy e Java: Comparação e Integração

Um dos motivos do surgimento da linguagem dinâmica Groovy foi o de trazer para

plataforma Java maior agilidade com menos escrita de código. A capacidade do Groovy de se

integrar com Java, permitindo até misturar código Java na aplicação com um mínimo de

esforço, e a curta curva de aprendizado para o desenvolvedor Java faz da linguagem a solução

ágil mais próxima do sucesso dentre as opções existentes para plataforma. Uma comparação

Page 31: 2011-Introdução ao Framework Grails

31

entre as linguagens ressaltando os benefícios que o Groovy traz ao Java, e uma mostra de

como Groovy e Java trabalham lado a lado podem ser dados por simples exemplos.

Uma boa exemplificação da maneira como Groovy se assemelha ao Java é fazendo

uma pequena análise de sua sintaxe. A sintaxe de Groovy é bastante amigável ao que está

acostumado o desenvolvedor Java, com o ganho de permitir que se escreva menos código,

deixando a programação na plataforma mais limpa. O trecho de código a seguir compara a

sintaxe do Groovy com a já conhecida do Java mostrando a pouca diferença entre as duas.

Código Java Código Groovy

import Java.util.*; today = new Date()

Date today = new Date();

Figura 3.1 – Código: Comparação Simples de Java e Groovy

Fonte: [SMIT 09]

Como se observa o código de Groovy tem a mesma função que o correspondente em

Java e grande semelhança com o mesmo, porém sem a necessidade do uso de ponto-e-vírgula,

sem a importação de nenhum pacote e, com sua tipagem dinâmica, sem a necessidade de

declaração de variáveis. Essa pequena amostra serve apenas de introdução ao poder do código

de Groovy sendo eficiente e simples.

Como foi dito antes quase tudo em Groovy é Java, tipos, objetos e a maneira como

Groovy instancia seus objetos seguem a mesma linha de Java. Mas Groovy vai além e permite

que um código completo em Java rode nele sem apresentar erro.

Groovy é considerado por muitos um subconjunto de Java por apresentar grande

integração com a plataforma, porém acrescenta recursos que a plataforma não possuía. Assim

como Java, Groovy é uma linguagem que compila para forma binária (bytecode) e roda na

JVM. Compilar código Groovy para bytecode é uma das maneiras mais simples de integrar

Groovy com Java. Os arquivos .class gerados do Groovy são disponibilizados para Java que

pode fazer uso do mesmo. A Máquina Virtual Java roda Groovy como se estivesse rodando o

próprio Java, mesmo que ajam diferenças em código.

Page 32: 2011-Introdução ao Framework Grails

32

Estas aplicações podem se beneficiar da expressividade,

brevidade e dos poderosos recursos do Groovy. Em outras situações,

no entanto, Groovy pode não ser a melhor solução. Isto é

particularmente verdadeiro para aplicações que exigem alto

desempenho, dada o inevitável trade-off 1 entre agilidade e velocidade

em Groovy. [ABDU 09]

O uso do Groovy como solução colaborativa as aplicações Java, fornecendo recursos

que não estão presentes na mesma, é bem vindo, porém tiram todo o poder que a linguagem

pode oferecer a aplicação por si só.

Groovy não tem somente semelhanças e integrações com Java. Há uma gama enorme

de funcionalidades que a linguagem oferece como: blocos de códigos executáveis (closure),

fácil comunicação com base de dados, eficiência em orientação a objetos, entre outros

recursos que serão apresentados a seguir.

3.2.3 Por dentro do Groovy

Já foi descrito que Groovy é uma linguagem dinâmica, ou de script, orientada a

objetos e que também pode ser compilada para bytecode Java através da JVM. A forma como

a linguagem faz uso dessa capacidade híbrida e o poder de tal característica está em sua

sintaxe. Groovy salva a plataforma Java, mas não exclui as vantagens que a mesma já

apresenta, muito pelo contrário adiciona a ela ainda mais produtividade tornando o código

mais legível, limpo, simples e, é claro, ágil.

Em sua declaração de tipos Groovy permite trabalhar de forma dinâmica (script) ou de

forma estática, diferenciando-se de outras linguagens como Ruby e Python que só aceitam a

tipagem dinâmica, isto diminui as críticas que esse tipo de linguagem costuma receber em

relação à detecção de erros em tempo de execução.

Groovy possui a vantagem das linguagens dinâmicas de utilizar o Protocolo de Meta-

Objeto (Meta-Object Protocol ou MOP) que cria para cada objeto um meta-objeto que

1 Trade-off ou tradeoff é uma expressão que define uma situação em que há conflito de escolha. Ele se caracteriza em uma

ação econômica que visa à resolução de problema mas acarreta outro, obrigando uma escolha. Ocorre quando se abre mão de

algum bem ou serviço distinto para se obter outro bem ou serviço distinto. (Fonte: Wikipédia)

Page 33: 2011-Introdução ao Framework Grails

33

armazena os métodos separando-os, de certa forma, dos objetos em si. Isso dá ao programador

a vantagem de poder alterar o meta-objeto em tempo de execução, adicionando novas funções

ao objeto.

A função de meta-objeto também pode ser vista como o Duck Typing que é um

conceito utilizado pelas linguagens dinâmicas que traz grande flexibilidade a aplicação. Tal

nome vem da expressão que diz: “Se anda como um pato. Corre como um pato e fala como

um pato é porque é um pato”. Nesse sentido diz-se que a classe deve assumir o

comportamento que lhe for dado, adquirindo este dinamicamente.

class Pessoa {

def nome, sexo

}

Pessoa.metaClass.toString = {

return “Nome: ${nome} sexo: ${sexo}.executou

}

println new Pessoa (nome: “Adriano”, sexo: “M”).toString()

Figura 3.2 – Código: Exemplo do uso de Meta-Objeto

O código acima mostra o exemplo do uso de meta-objeto em Groovy. Em tempo de

execução, o método toString é adicionado a classe dando a aplicação um novo

comportamento. Em linguagens de tipagem forte, como o Java, por exemplo, isso não

ocorreria, pois os métodos são definidos pela classe superior do objeto e isto é fixo. Com duck

type (meta-objeto) isto depende apenas do estado corrente do objeto, em determinado

momento este pode ter 10 métodos e em outro, 15.

Muito do que Java apresenta em sua sintaxe deixa o código pesado e trabalhoso,

Groovy reduz a necessidade de escrita de código deixando opcional o uso desses recursos.

Além da declaração de tipos facilitada pela tipagem dinâmica, quando trabalha-se com

scripting, onde o tipo é opcional, em Groovy é opcional também o uso de modificadores de

acesso, ponto e vírgula e return. Algumas características básicas do Groovy são:

Page 34: 2011-Introdução ao Framework Grails

34

Por padrão tudo o que não é especificado com modificador de acesso é visto como

público;

O uso de ponto e vírgula só será necessário em caso de mais de um comando em

uma mesma linha;

A instrução return é opcional, pois se adota o retorno do último comando como

valor de retorno do método ou função;

O conceito de verdade estende o conceito do Java e diz que qualquer valor

diferente de null é verdadeiro, independente de ser do tipo boolean ou não;

Assim como em C++, podem-se subscrever os operadores como: ++, --, >, < etc.

Outro destaque importante da sintaxe do Groovy é a maneira como simplifica o uso de

beans e eleva o uso do princípio DRY (Don’t Repeat Yourself) implementado pelo modelo de

desenvolvimento ágil. Ao contrário do Java, em Groovy não é necessário a declaração dos

métodos gets e sets, isso é feito dinamicamente pela linguagem. O Groovy Beans entende que

se o escopo de uma variável é indefinido os métodos básicos da mesma devem ser criados

dinamicamente, tornando a programação mais limpa e com menos escrita de códigos.

String em Groovy é outro atrativo da linguagem que torna o código ainda mais legível.

As GString, como são denominadas, tem características da linguagem PHP e permitem o

acoplamento de String misturando o conteúdo de uma variável, uma classe Java ou o

resultado de uma expressão numa mesma saída sem a necessidade do uso do operador

mais(+). A seguinte String funciona perfeitamente no Groovy:

def x=10

println “Hoje é: ${new Java.util.Date().toString()} - ${x}”

Figura 3.3 – Código: Exemplo de GString.

Groovy possui ainda muitas funcionalidades e métodos que simplificam e muito o

trabalho do desenvolvedor. Algumas funções importantes e frequentemente utilizadas,

principalmente no framework Grails, são os métodos each e find. O uso de listas e mapas em

Groovy juntamente com esses métodos é um recurso poderoso da linguagem.

Page 35: 2011-Introdução ao Framework Grails

35

def lista = [”fornecedor”, “advogado”, “dentista”, “mecânico”]

lista.findAllbyPalavraChave {

it == “advogado”

}.each {

println it

}

Figura 3.4 – Código: Os métodos findAll e each.

O código acima exemplifica o uso dos métodos find e each em uma lista de Strings. O

método findAll procura na lista todas as ocorrências do valor informado em it, que é uma

variável usada no Groovy para implicitamente representar a variável corrente, ou no caso o

valor iterado. O método each retorna então cada (each) ocorrência e imprime na tela o valor

de it.

Groovy apresenta ainda muitas outras ferramentas e funções que melhoram a

programação na plataforma Java, entre eles os GSP (Groovy Server Pages) que serão

discutidos nos tópicos seguintes do Grails, antes, porém é preciso falar de outra grande proeza

do Groovy, o uso de Closure.

3.2.4 Closures

Closure são blocos de código executáveis. Podem ser vistas como variáveis diferentes

das demais que retornam um conjunto de instruções que é executado retornando ou iterando

dentro de variáveis locais no contexto em que está inserida [ABDU 09].

O uso de closure não é novo, mas pouco conhecido. É muito utilizado em linguagens

funcionais seu uso teve início na década de 1960 em linguagens como LISP, por exemplo. No

entanto a maneira como Groovy explora esse recurso é o que o faz surgir como um recurso

aparentemente novo.

A declaração de uma closure é feita da mesma maneira com a qual declara-se as

variáveis comuns, com a diferença de, em lugar de incluir apenas um valor, inclui-se um

Page 36: 2011-Introdução ao Framework Grails

36

bloco de código. Devido a essas e outras características é que defini-se as closure como

variáveis.

Em Groovy as closure são uma instancia da classe groovy.lang.Closure e sua

referencia, assim como a declaração é feita da mesma maneira com que referencia-se qualquer

variável convencional.

O uso de closure em Groovy é constante e sua execução dentro de uma aplicação

acontece como a execução de um método onde a única obrigatoriedade para sua execução é o

uso de parênteses. O código a seguir demonstra o uso de closure em Groovy, da declaração à

execução dentro de um contexto.

Closure

Declaração

def save = {

def usuarioInstance = new Usuario(params)

if (usuarioInstance.save(flush: true)) {

redirect(action: "show", id: usuarioInstance.id)

}

else {

render(view:"create", model:[usuarioInstance: usuarioInstance])

}

}

Referência/Execução

def aba = new Usuario(nome:"Adriano Basto", login:"aba", senha:"123456")

aba.save()

Figura 3.5 - Código: Exemplos de Closure

No código acima os itens em destaque demonstram a closure save() que recebe um

bloco de código e logo abaixo sua execução é feita com o objeto chamando-a como chama-se

um método comum.

Page 37: 2011-Introdução ao Framework Grails

37

3.3 GRAILS: ALGUMAS TECNOLOGIAS

O poder do desenvolvimento em Grails, além de possuir ao seu lado total integração

com a plataforma Java e todo o poderio da linguagem Groovy, ainda conta com o suporte das

tecnologias open-source reconhecidas e mais elogiadas do mundo Java. Tecnologias essas

como Spring, Hibernate, Sitemesh, Tomcat, entre outras que complementam o Grails e fazem

do framework a poderosa ferramenta que é.

3.3.1 Spring

Uma das tecnologias por trás do Grails é o Spring. Este é um poderoso container de

injeção de dependência que sustenta o framework livrando os programadores de uma

imensidão de trabalho. Porém, mais do que uma ferramenta integrante do Grails, Spring é um

poderoso recurso hoje utilizado por grandes empresas até mesmo pelas que não adotam

código-aberto como exigência em suas aplicações.

Podemos dizer que boa parte do que o Grails executa está ligado ao Spring e todo o

poder de injeção de dependência que o mesmo oferece. O fato de ser conhecido também como

um container de inversão de controle está no núcleo do Spring que é assim chamado. Todavia

o uso do termo pode limitar o framework a apenas essa função quando na verdade o seu foco

principal é a injeção de dependências.

Para entender o real funcionamento do Spring é preciso compreender os conceitos de

Inversão de Controle (Invertion of Control - IoC) e Injeção de dependências (Dependency

Injection – DI) mas podemos dizer que o que o Spring faz basicamente é livrar o

desenvolvedor do trabalho que se tinha, por exemplo, ao empregar o padrão de projeto

factory. O container do Spring encarrega-se de instanciar as classes e definir as dependências

entre elas, permitindo o baixo acoplamento entre classes, um problema enfrentado muitas

vezes pelo uso do factory.

O conceito de Inversão de Controle é visto por muitos como algo genérico uma vez

que consiste de uma característica comum dos frameworks onde, a sequência de chamada de

métodos é tirada das mãos dos programadores para uma infra-estrutura de software que toma

controle sobre a execução. É basicamente esta característica que também diferencia um

Page 38: 2011-Introdução ao Framework Grails

38

framework das bibliotecas de classes. Já a idéia de Injeção de Dependência, criada por Martin

Fowler, leva o IoC um pouco mais além. Ao invés de apenas tomar controle sobre os

métodos, o container ‘injeta‟ em cada classe, por exemplo, suas dependências declaradas. Um

módulo montador separado é responsável por injetar a implementação no objeto, assegurando

que qualquer usuário siga esta convenção [CARV 08].

Mas as funcionalidades do Spring vão além, com o objetivo principal de simplificar o

desenvolvimento de aplicações, o framework apresenta um conjunto de módulos que podem

ser utilizados de acordo com a necessidade do projeto. Voltados para persistência de dados,

desenvolvimento web, acesso remoto, entre outros, esses módulos dão ao framework a

possibilidade de ser um ótimo substituto para a plataforma J2EE.

O trabalho do Spring no Grails é fundamentado principalmente na injeção de

dependências, mas o framework está presente também no suporte à persistência de dados,

segurança, gerenciamento de transações do GORM, configuração em tempo de execução,

delegação de controladores, entre outras. Uma aplicação Grails é praticamente desenvolvida

em cima do Spring que viabiliza toda a gama de convenções que o framework segue e dessa

forma faz do Grails a poderosa ferramenta que é. Por isso, um conhecimento avançado do

Grails exige antes um conhecimento também do Spring.

3.3.2 Hibernate

Surgiu com o objetivo de simplificar os processos de persistência de dados para

programação orientada a objetos no modelo relacional de banco de dados. O Hibernate é um

framework feito principalmente para plataforma que integra o pacote de desenvolvimento do

Grails.

Sendo uma ferramenta de mapeamento objeto/relacional, Hibernate atua no Grails

através do GORM (Grails Object Relational Mapping), possibilitando ao desenvolvedor a

pouca escrita de código de acesso a banco de dados e de comandos SQL, acelerando a

velocidade do desenvolvimento de uma forma fantástica.

As características básicas do Hibernate são:

Page 39: 2011-Introdução ao Framework Grails

39

Permitir o desenvolvimento de persistência de dados orientada a objetos

naturalmente, incluindo herança, polimorfismo, e encapsulamento;

Não necessidade de tabelas especiais ou campos e gerando a maior parte do

SQL em tempo de inicialização do sistema, em vez de tempo de execução;

Não necessidade de interfaces ou classes base para classes persistentes,

permitindo a persistência de qualquer estrutura de classes ou de dados.

A integração de Hibernate e Grails é bem vinda principalmente porque Grails trabalha

com a maior parte da lógica de negócios na própria aplicação, dependendo pouco de funções

específicas do banco de dados. Dessa forma o framework aproveita vantagens de ambas as

partes para o mapeamento objeto/relacional.

O Hibernate possui uma poderosa linguagem de consulta que é nada mais do que um

dialeto SQL no Hibernate. O poder dessa linguagem está principalmente no fato de ser

totalmente orientada a objetos o que permite a inclusão de características próprias do

paradigma como herança, polimorfismo e encapsulamento.

Os arquivos de configuração do Hibernate são gerados na criação da aplicação em

Grails e localizam-se no diretório grails-app/conf, mas o único trabalho que um

desenvolvedor iniciante tem que ter com o mesmo fica localizado no arquivo

DataSource.groovy que será abordado em tópicos posteriores.

3.3.3 SiteMesh

Para suporte da camada de visualização do Grails a tecnologia presente é o SiteMesh,

uma ferramenta para geração e manipulação de layout de páginas web baseado no padrão

decorador (decorator). O SiteMesh foi originalmente desenvolvido como ferramenta de

código fechado para a plataforma Java passando a código aberto por volta do ano 2000 sob a

licença da OpenSymphony.

O SiteMesh funciona através de um filtro Servlet 2 que intercepta o HTML a ser

retornado para o navegador, extrai dele o conteúdo que lhe é relevante e funde o mesmo

utilizando o modelo decorador. Esse funcionamento fica mais claro quando entende-se a

2 Servlet é um componente do lado servidor que gera dados HTML e XML para a camada de apresentação de um aplicativo Web.

Page 40: 2011-Introdução ao Framework Grails

40

diferença básica do modelo que o SiteMesh adota de outro modelo comumente utilizado por

outras ferramentas.

O padrão do modelo decorador (decorator) cria um layout central com espaços vazios

onde apenas os elementos ausentes (não presentes nas visualizações) são preenchidos

deixando os demais espaços para manipulação direta das páginas de visualização. O outro

padrão, conhecido por composição (compositive), é utilizado por ferramentas como o Tiles da

Apache, por exemplo, e tem seu layout central espaços vazios que são preenchidos como um

todo por templates gerados pelas visualizações. Resumindo, pode-se dizer que o padrão do

SiteMesh faz uma fusão dos componentes do layout com os da visualização, enquanto que o

padrão composição faz a inclusão dos componentes da visualização no layout [RUDO 06].

O SiteMesh é parte integrante das ferramentas Grails e por padrão vem configurada

como o provedor de layouts do framework. Os arquivos de layout do SiteMesh são alocados

no diretório grails-app/views/layouts no ato de criação da aplicação grails.

Page 41: 2011-Introdução ao Framework Grails

41

Figura 3.6 – Entendendo o SiteMesh

A figura acima mostra de que forma o SiteMesh trabalha no Grails. O arquivo

main.gsp é um layout SiteMesh que possui em sua estrutura 3 (três) tags peculiares:

g:layoutTitle, g:layoutHead e g:layoutBody. No ato de criação da visualização no Grails,

caso um dos elementos referentes a title, head ou body não sejam preenchidos e o uso do

layout criado pelo SiteMesh estiver inserido no cabeçalho da visualização, como mostrado na

figura, os valores padrões serão mesclados aos contidos na visualização.

Page 42: 2011-Introdução ao Framework Grails

42

O uso do SiteMesh não é exclusividade do Grails e nem da plataforma Java, a

ferramenta hoje pode ser integrada também a PHP, Python, Perl, entre tantas outras

ferramentas de desenvolvimento web.

3.3.4 Outras Tecnologias

Grails possui integração ainda com muitas outras tecnologias de sucesso no mundo de

software para web, sendo muitas delas padrão do framework e integrantes de seu pacote de

instalação. Além das tecnologias já apresentadas o framework permite integração com:

Tomcat

Um servidor web sob licença livre da Apache Software Fundation que a partir da

versão 1.2 do Grails passou a vir por padrão junto ao framework. Uma ferramenta elogiada no

desenvolvimento web que provê um servidor HTTP puramente em Java. No Grails a grande

contribuição do Tomcat está na facilidade de se fazer o deploy da aplicação. Basta configurar

o arquivo config.groovy da aplicação, localizado em grails-app/conf, com as informações

pertinentes e executar o comando grails tomcat deploy que o deploy da aplicação será

realizado sem grandes problemas.

Jetty

Solução alternativa ao Tomcat como servidor web, um servidor HTTP totalmente

escrito em Java que pode ser integrado ao Grails através de plugin. As vantagens do Jetty são

a sua fácil configuração e o fato de suportar uma carga maior de usuários simultâneos sem

depender do auxilio de outras estratégias.

JUnit

O framework de testes automatizados do Java que vem por padrão entre os

componentes do framework Grails e assim como em Java, permite padronizar os testes da

aplicação. Grails segue o princípio de TDD (Test Driven Development), que em português

refere-se a desenvolvimento direcionado a testes, um princípio comum no meio de

Page 43: 2011-Introdução ao Framework Grails

43

desenvolvimento ágil. É através do JUnit que o framework realiza os testes unitários,

funcionais e de integração de toda a aplicação.

HSQLDB

É o banco de dados padrão do Grails. Vem junto ao pacote de instalação do framework

e pré-configurado no DataSource.groovy, porém tem a característica de não ser um banco de

armazenamento constantes. O HSQLD armazena os dados da aplicação Grails em memória

enquanto a mesma está sendo executada e os apaga quando a aplicação é finalizada. Possui as

características de ser bastante leve e simples de ser manuseado e por isso bastante

recomendado para execução de testes.

Quartz

É o agendador de tarefas do Grails. Implementa agendamentos para execução de

códigos em intervalos de tempo regulares. Uma ferramenta open-source que originalmente

integrava o pacote do Grails e hoje pode ser obtida através da instalação de plugin.

3.4 CONHECENDO O GRAILS

Adquirir um conhecimento avançado sobre uma ferramenta nova e com tantas

funcionalidades como o Grails exige uma grande dedicação, não apenas no aprofundamento

do framework em questão, como também das tecnologias que o sustentam, tais como: Spring,

Hibernate, Groovy, e até mesmo Java. Mas, para uma introdução do que o framework já

oferece, pouco tempo é suficiente para conhecê-lo.

3.4.1 Começando com Grails

Trabalhar com o framework Grails, apesar de exigir um conhecimento básico da

sintaxe do Groovy, mostra-se bastante simples, até mesmo nos primeiros momentos, e

principalmente aos já habituados com a plataforma Java. Desde a instalação até o

desenvolvimento através de IDE’s não há grandes dificuldades apresentadas.

Page 44: 2011-Introdução ao Framework Grails

44

Ao instalar o Grails o desenvolvedor não precisa se preocupar com nada, exceto ao

fato de ter instalado um pacote JDK 1.4, ou posterior, em sua máquina e configurar as

variáveis de ambiente necessárias. No download e instalação do Grails todas as tecnologias

integrantes como Spring e Hibernate, e até mesmo Groovy, já estão embutidas no pacote de

instalação do framework que aloca tudo em seus devidos lugares para o funcionamento da

“plataforma” de desenvolvimento. Esse procedimento não impede que outras tecnologias de

escolha do desenvolvedor sejam anexadas a plataforma, desde que haja compatibilidade com

a mesma.

Com o Grails devidamente instalado e configuradas as variáveis de ambientes

necessárias, o desenvolvedor deve apenas escolher de que forma pretende escrever seus

códigos e executar os comandos do Grails. O framework é habilitado para executar em prompt

de comando, da mesma forma que funciona perfeitamente em IDEs como NetBeans e Eclipse,

por exemplo. Essas IDEs apresentam compatibilidade com o framework e pouco trabalho de

configuração.

3.4.2 Estrutura de Diretórios e o Padrão MVC

Um conhecimento introdutório do Grails exige antes conhecer a estrutura em camadas

que o framework implementa. Já no ato de criação de uma aplicação através do comando

grails create-app, seja via linha de comando ou via IDE, Grails cria no diretório definido para

aplicação uma árvore de diretórios fundamentada no padrão em camadas MVC.

Como já visto, o padrão MVC separa os recursos principais da aplicação em 3 níveis

(camadas) Modelo – Visualização – Controle, tornando a aplicação organizada, legível e

facilitando a manipulação desses recursos separadamente sem interferir diretamente entre si.

A árvore de diretórios gerada pelo grails create-app demonstrada na Figura 3.6,

apresenta os diretórios: grais-app/domain, grails-app/view e grails-app/controllers. Esses

diretórios são responsáveis por armazenar os arquivos referentes às camadas de modelo de

dados, visualização e controle respectivamente.

Page 45: 2011-Introdução ao Framework Grails

45

Figura 3.7 – Árvore de diretórios de uma aplicação Grails

É no diretório grails-app que os recursos mais importantes da aplicação se encontram.

Além dos diretórios já apresentados, outros diretórios e subdiretórios da árvore apresentam

funções específicas dentro da aplicação. A Tabela 3.1 explica as funções básicas de alguns

deles.

Page 46: 2011-Introdução ao Framework Grails

46

Tabela 3.1 – Principais diretórios de uma aplicação Grails. Fonte: [DAVI 10]

Diretório Função

grails-app Responsável por manter em seus subdiretórios as classes principais da

aplicação.

grails-app/conf Armazena os arquivos de configuração da aplicação tais como fontes

de dados, mapeamento de URL e arquivos de configuração do Spring e

Hibernate.

grails-app/controllers Armazena as classes de controle da aplicação, o “C” do padrão MVC.

grails-app/domain Armazena as classes de modelo (domínio) da aplicação. Cada arquivo

deste diretório tem uma tabela correspondente no banco de dados.

grails-app/i18n Armazena os recursos de internacionalização da aplicação como

mensagens de erro, por exemplo.

grails-app/services Armazena os serviços da aplicação, que seriam classes que prestam

suporte a lógica de negócio, encapsulando determinados aspectos das

mesmas. Essas classes são gerenciadas pelo Spring.

grails-app/taglib Armazena tags customizadas criadas pelo Grails.

grails-app/utils Armazena arquivos utilitários do Grails tais como codecs e classes

utilizadas por plugins.

grails-app/views Armazena arquivos de visualização da aplicação, os GSP (Groovy

Server Pages). É o “V” do padrão MVC.

lib Responsável por armazenar os arquivos de bibliotecas terceirizadas

como drivers JDBC, por exemplo.

scripts Responsável por armazenar os scripts criados para facilitar o

desenvolvimento da aplicação

src Responsável por armazenar código fonte legado a ser reaproveitado

pela aplicação. Possui subdiretórios que separam código Groovy e

código Java, além de templates. Normalmente guarda código fonte que

não se encaixa facilmente na estrutura de diretórios do Grails.

test Responsável por armazenar as classes de testes unitários, funcionais e

de integração da aplicação.

web-app Responsável por armazenar todo conteúdo estático da aplicação, tais

como: CSS, imagens, ícones, arquivos html.

Grails implementa o MVC muitas vezes dinamicamente, através do comando scaffold

que, com base nos valores e atributos das classes de domínio, gera os controladores e

respectivas visualizações das classes presentes no diretório grails-app/domain. Porém o uso

do scaffold pode se apresentar arriscado dependendo do tipo de problema, como veremos

mais adiante.

Page 47: 2011-Introdução ao Framework Grails

47

3.4.3 Persistência de Dados no Grails

Banco de dados em Grails é um assunto interessante e, assim como todas as suas

demais funções, tem um procedimento de configuração mínimo. Além de possuir uma base de

dados pronta para fornecer suporte durante o desenvolvimento (HSQLDB), o framework

permite ainda o acesso a base de dados legadas e a geração automática de comandos SQL

para banco de dados externo como o MySql, por exemplo. O desenvolvedor tem contato

apenas com um arquivo, além das classes de domínio que implementa o modelo de dados e

suas respectivas validações. É neste arquivo que os dados referentes à conexão da aplicação

ao banco de dados ficam armazenados, é nele que ocorre o gerenciamento de todo o trabalho

de configuração executados por ferramentas como Hibernate através do recurso conhecido

como GORM no Grails.

A figura 3.8, apresenta o código do arquivo DataSource.groovy, localizado no

diretório grails-app/conf e responsável por guardar as informações referentes aos bancos de

dados da aplicação. Conforme se observa na figura, é comum o DataSource apresentar 3

sessões de blocos de códigos que possuem cada um uma função específica dentro deste

arquivo, são eles:

Datasource: guarda as configurações da base de dados comum aos 3 ambientes

de execução que o Grails implementa (desenvolvimento, testes e produção),

tais como driver do banco a ser utilizado, dados para acesso ao banco

(username e senha), entre outras;

Hibernate: guarda informações especificas do hibernate que normalmente

ficariam em um arquivo próprio do mesmo, como uso ou não de cachê (true ou

false), exposição ou não de comandos SQL;

Page 48: 2011-Introdução ao Framework Grails

48

Figura 3.8 – Código do DataSource.groovy

Environments: composta basicamente de três ambientes de execução guardando

as informações especificas de acesso a banco de dados para cada um deles.

Cada ambiente possui uma extensão da sessão dataSource com as

configurações especificas de: endereço do banco usado e forma de manipulação

do mesmo pela propriedade dbcreate.

Ambiente de execução é um conceito que o Grails implementa para tornar a aplicação

mais eficiente, a idéia é dividir a aplicação em ambientes voltados a cada tipo de execução,

seja ela para testes, desenvolvimento ou produção. No caso do DataSource.groovy,

especificamente, os ambientes referem-se apenas a base de dados onde se pode definir um

banco de dados para testes, um para desenvolvimento e outro para produção, principal

ambiente da aplicação.

Se um mesmo banco de dados for utilizado pelos três ambientes, ou seja, se ambos

compartilharem as mesmas informações, a solução melhor é configurar tais informações na

sessão datasource, que abrange os 3 ambientes da sessão environment.

Page 49: 2011-Introdução ao Framework Grails

49

Uma propriedade que merece destaque na sessão environment do exemplo é o recurso

dbcreate. É no dbcreate que o desenvolvedor define se a aplicação deve ou não criar

automaticamente as tabelas nos bancos correspondentes. Essa propriedade aceita quatro

valores e cada qual realiza uma função especifica na execução da aplicação, são eles:

Create: cria a estrutura SQL que gera as tabelas no banco de dados, apagando

dados quando as mesmas já existem no banco;

Creat-drop: cria as tabelas, mas apaga as mesmas no momento em que a

aplicação é finalizada;

Update: atualiza as tabelas existentes e cria novas quando essas não existem no

banco;

Validate: verifica se as classes de domínio e as tabelas nos bancos de dados

estão de acordo umas com as outras.

O uso do dbcreate pode se mostrar arriscado dependendo de qual valor é empregado a

propriedade em cada ambiente. Por exemplo, o uso do create-drop no ambiente de

desenvolvimento pode ser bem vindo, o mesmo não se recomenda ao ambiente de produção.

Na persistência de dados o trabalho do Hibernate realmente começa. O GORM

(Grails Object Relational Mapping), já no ato de criação das classes de domínio, inicia o

mapeamento das informações de cada classe, desde atributos a validações (constraints). É

através do GORM que o Hibernate cria, na execução de métodos como o dbcreate, por

exemplo, as tabelas dos bancos de dados gerando nome, tipo e tamanho dos campos de acordo

com o que está definido nas classes de domínio.

O trabalho do GORM com Hibernate na persistência de dados envolve ainda os

relacionamentos entre classes e suas correspondentes tabelas, a herança das classes entre

tantos outros recursos.

3.4.4 Scaffold: Problema ou Solução?

Um recurso poderoso implementado pelas ferramentas de desenvolvimento ágil para

web, como o Ruby on Rails, por exemplo, é o chamado scaffold. Um recurso que elimina

quase totalmente o trabalho do desenvolvedor criando dinamicamente os componentes da

Page 50: 2011-Introdução ao Framework Grails

50

camada de controle e de visualização da aplicação. Grails também possui essa função entre

suas principais funcionalidades e dessa forma permite a criação da base de uma aplicação

simples em pouco tempo. No entanto há casos em que o uso do scaffold pode ser arriscado e

tornar-se mais um problema do que uma solução [ABDU 09].

O uso do scaffold por vezes esconde do desenvolvedor os recursos referentes aos

controladores e as visualizações da aplicação, isso pode ser um problema quando há a

necessidade de se criar códigos específicos, como no caso de criar uma closure para

autenticação, por exemplo.

A utilização do scaffold no Grails é opcional, o framework possui outras

funcionalidades e comandos que geram todo o código básico de controladores e suas

respectivas visualizações. Através do comando grails generate-all, por exemplo, é gerado

para cada classe de domínio o seu correspondente na camada de controle e na camada de

visualização, além das classes de testes, porém, ao contrário do scaffold, este comando não

esconde os arquivos e códigos gerados, apenas facilita sua criação.

A utilização do scaffold é simples e basicamente o que tal função faz dentro do

controlador é gerar o CRUD (Create – Read – Update – Delete) da aplicação. O CRUD de

uma aplicação Grails é composto das propriedades básicas da aplicação, propriedades essas

chamadas em Grails por action (ação). Cada action implementa uma closure com códigos pra

realizar uma função específica de acordo com o que o usuário solicita e, em certos casos, cada

action gera um arquivo .gsp que representa uma visualização daquela ação na camada de

apresentação.

Page 51: 2011-Introdução ao Framework Grails

51

Figura 3.9 – Scaffold

A figura acima mostra o código que implementa a funcionalidade scaffold no Grails, o

único conteúdo do controlador que usa scaffold é o demonstrado, escondendo do

desenvolvedor as action que são geradas dinamicamente em tempo de execução.

3.4.5 A camada de Visualização

A segunda camada do modelo MVC é a responsável por tratar as visualizações, ou

seja, tudo o que envolve a aparência da aplicação e a interface de usuário. Grails apresenta em

suas tecnologias poderosos recursos que facilitam a geração de layout e templates, além da

geração das paginas de visualização.

Como foi dito anteriormente, é comum algumas action dos controladores gerarem uma

visualização, isso acontece dinamicamente quando a função scaffold é usada, nesse caso, para

cada classe de domínio/controle é criado um subdiretório em grails-app/views onde os

arquivos de visualização são armazenados. Em Grails os arquivos de visualização tem a

extensão .gsp de Groovy Server Pages. Os GSP contém todo o código que implementam as

interfaces da aplicação e só diferenciam dos arquivos html pela presença de tags especificas

iniciadas por <g:> que fazem valer os recursos exclusivos do Grails.

A Figura 3.10 destaca a presença das tags do grails, além das tags html convencionais,

como por exemplo a tag <g:each></g:each> que, através da função each do Groovy,

percorre uma determinada lista retornando um valor a cada iteração.

Page 52: 2011-Introdução ao Framework Grails

52

Figura 3.10 – Exemplo de GSP

A manipulação de layout no Grails é facilitada por tecnologias como o SiteMesh, por

exemplo. O framework possibilita ainda a customização de templates de maneira rápida e

intuitiva e que torna-se ainda mais poderosa se usada em conjunto com a funcionalidade

scaffold.

Grails possibilita a criação de templates parciais em que o desenvolvedor pode definir

em um arquivo .gsp a aparência e conteúdo que terão suas visualizações. Para isso basta

inserir ao início do nome do arquivo gsp o símbolo underline (_) e incluir o mesmo no

diretório grails-app/views/layouts. Após isso é preciso configurar o layout do main.gsp do

SiteMesh, conforme o exemplo do código abaixo.

Page 53: 2011-Introdução ao Framework Grails

53

<body><!-- snip -->

<g:render template="/layouts/meutemplateparcial" />

<g:layoutBody />

</body>

Figura 3.11 – Código: Incluindo template parcial

O código mostra que o grails irá renderizar o template através da tag <g:render> e

exibir seu conteúdo nas visualizações que forem criadas. É possível ainda customizar a forma

como o Grails gera as visualizações quando utilizada a função scaffold bastando configurar os

arquivos de templates que tornam-se visíveis ao desenvolvedor ao chamar o comando grails

install templates.

A camada de visualização do Grails ainda é responsável pela manipulação dos

arquivos CSS e possibilita a customização de bibliotecas de marcas (TagLibs).

3.5 CASOS DE SUCESSO

Grails tem colhido frutos dentro da comunidade de desenvolvimento ágil para web e

muitos são os casos de sucesso de aplicações desenvolvidas com o framework. A própria

história do Grails demonstra isso pelo fato de hoje ter o núcleo de gerenciamento de suas

operações de suporte e desenvolvimento de soluções junto de uma das tecnologias mais

elogiadas do mundo Java, o Spring Framework. Parte integrante da SpringSource desde 2008,

o núcleo de gerenciamento do Grails e Groovy liderados por Graeme Rocher e Guillaume

Laforge respectivamente, é dos mais ativos da empresa estando o Grails hoje a caminho da

versão 1.4 e o Groovy na versão 1.8.

Elogiado pela maneira como gerencia memória de suas aplicações, o Grails segue

desmentindo casos que sugerem o não suporte a múltiplos usuários. Segue abaixo alguns

casos de sucesso com grails no Brasil e no mundo:

Page 54: 2011-Introdução ao Framework Grails

54

Mins.ms: encurtador URL utilizando Grails no App Engine;

NoiteUniversitária.com.br: site de entretenimento brasileiro feito inicialmente

em Grails 0.4;

AndroidGateway.com: voltado para desenvolvedores de aplicativos do

Android;

ExperienceOz.com: site ecommerce para passeios turísticos na Austrália;

ImoveisnoMorumbi.com.br: site da agência imobiliária brasileira focada em

clientes de alto nível. Possui mais de 100 mil requerimentos por dia e funciona

com dois servidores Tomcat.

Page 55: 2011-Introdução ao Framework Grails

55

4 ESTUDO DE CASO

Este estudo de caso tem por objetivo apresentar uma introdução prática do uso do

framework Grails como ferramenta de desenvolvimento para aplicações Web. Para

exemplificar o funcionamento do framework uma aplicação simples foi elaborada explorando

um problema real e que demonstra parte das principais tecnologias que compõem o Grails.

Por tratar-se de uma ferramenta ágil, o processo de desenvolvimento se baseou na

metodologia Scrum, utilizando seus recursos para gerenciamento do projeto.

4.1 DESCRIÇÃO DO PROBLEMA

Para conquistar a confiança e manter o bom relacionamento com seus clientes, uma

das preocupações que as empresas devem ter diz respeito às formas de venda com as quais

trabalha. É pensando nisso que a empresa Gesso Arte de Araruama oferece a seus clientes

mais antigos e fiéis uma modalidade de venda exclusiva, as vendas a prazo.

A Gesso Arte de Araruama é uma empresa do ramo de construção civil que oferece

soluções em serviços e venda de produtos de gesso e derivados. A empresa mantém o

gerenciamento de suas informações em planilhas e fichas de papel, porém, o problema de se

controlar tais informações fez surgir a necessidade de implantar um sistema informatizado

que, de maneira rápida, resolvesse ao menos parte dos seus problemas.

4.2 O SISTEMA

O sistema proposto para resolução do problema apresentado visa gerenciar as

informações da Gesso Arte através de uma aplicação web, dividida em módulos que

corresponda a cada departamento ou operação que a empresa realiza. Por possuir sede e uma

filial em endereços distintos e pelas vantagens que o modelo web e a plataforma JVM

proporcionam é que foi sugerido o desenvolvimento desta aplicação no framework Grails.

Usando as vantagens do framework e da plataforma Java, o projeto será desenvolvido

tendo a metodologia Scrum como base, seguindo os passos do modelo ágil de

desenvolvimento sem o foco em documentação ao extremo. Os módulos nos quais o sistema

Page 56: 2011-Introdução ao Framework Grails

56

se divide, serão representados no Scrum como sprints, e para demonstração nesse estudo de

caso, apenas um sprint será desenvolvido, gerando ao seu final uma parte funcional do

sistema.

4.2.1 Desenvolvendo em Scrum

O modelo de desenvolvimento ágil oferece algumas ferramentas que visam orientar os

projetos de software de forma rápida e sem grandes complicações. Dentre estas ferramentas o

Scrum é uma das mais conhecidas e utilizadas que trabalha basicamente com 3 premissas: a

definição de papéis (ScrumMaster, dono do produto, equipe), reuniões periódicas

(planejamento, revisão, retrospectiva, reunião diária) e criação de artefatos (product backlog,

sprint backlog, burndown charts).

Um desenvolvimento baseado em Scrum não necessariamente precisa seguir

rigidamente essas regras. Pode-se adotar a inclusão de diagramas do modelo UML ou a

exclusão de alguns artefatos do Scrum de acordo com cada projeto e com o que for melhor

para a equipe desenvolvedora. No caso específico deste estudo de caso o uso de alguns dos

artefatos do Scrum é priorizado e os papéis servem apenas para identificar os envolvidos no

processo. Não há a necessidade de descrição detalhada das reuniões ou criação de muitos

diagramas para o sprint.

Começando com o planejamento do projeto o problema apresentado pela Gesso Arte

deu origem ao Product Backlog mostrado na Tabela 4.1. O Product Backlog da tabela lista

apenas algumas das estórias, ou seja, funcionalidades, que o sistema deve possuir.

O dono do produto pontua por importância (IMP) o que, a seu ver, deve ser executado

primeiro. É com base nessas informações que o primeiro sprint do projeto é criado.

Ao analisar o quadro do Product Backlog a equipe e ScrumMaster tem de pensar em

estórias que levem em consideração a pontuação do dono do produto (IMP), o tempo

estimado para cada estória (EST) e decidir quais estórias podem entrar no sprint para

proporcionar um resultado funcional ao final do mesmo, num período de pouco tempo. É

nesse momento também que se define um objetivo para o sprint. Todo sprint deve possuir um

objetivo que deve ser descrito durante a reunião de sprint, no caso deste problema o objetivo

do primeiro sprint foi o de retornar uma primeira versão funcional do sistema que realize

algumas das funcionalidades listadas no product backlog.

Page 57: 2011-Introdução ao Framework Grails

57

Tabela 4.1 – Product Backlog

ID NOME DA ESTÓRIA IMP EST COMO DEMONSTRAR

1 CADASTRO DE CLIENTES 10 1

Usuário faz login, clica em clientes, na

página clientes seleciona "criar novo",

insere os dados e clica em salvar.

2 CADASTRO DE

FUNCIONÁRIOS 5 3

Usuário faz login, clica em

funcionários, e se for autorizado de

acordo com seu papel na aplicação vai

a pagina funcionário seleciona "criar

novo", insere os dados e clica em

salvar.

7 CONTROLE DE VENDAS 10 8 Possuirá dependência direta do

controle de estoque e de caixa.

8 CONTROLE DE VENDAS

A PRAZO 10 2

Se a forma de venda for a prazo, clica-

se em Venda a prazo, clica em "Criar

nova", seleciona cliente por código e

nome, insere dados da venda e salva.

9 CONTROLE DE CAIXA 8 10 Depende do controle de vendas,

serviços, compras, despesas

15 REALIZAR VENDA 10 10

Clica em realizar venda na sessão

venda, insere os dados da venda e

imprime cupom fiscal

16 CONSULTAR VENDAS A

PRAZO 10 2

Digita um dado sobre a venda no

campo buscar da sessão vendas a

prazo e clica em buscar

17 CONSULTAR CLIENTES 10 3

Digita um dado sobre o cliente no

campo buscar da sessão clientes e

clica em buscar

18 LISTAR CLIENTES 10 1 Clica em cliente e uma lista de clientes

cadastrados é exibida

21 LISTAR VENDAS A

PRAZO 10 2

Clica em vendas a prazo e uma lista de

vendas é exibida

22 CADASTRO DE

USUÁRIOS 10 1

Usuário com permissão "cria novo

usuário" fornecendo dados de nome,

login e senha.

23 CONTROLE DE ACESSO 10 1

Verificar autenticidade do usuário, se

o mesmo se confirmar permite o

acesso, caso contrario retorna a tela

anterior.

ID = Identificador da estória - IMP = Importância - EST = Estimativa em Dias

Page 58: 2011-Introdução ao Framework Grails

58

Da análise do Product Backlog criou-se o primeiro sprint backlog, que após aprovação

do dono do produto seguiu para o desenvolvimento. A tabela 4.2 demonstra o sprint backlog.

Tabela 4.2 – Sprint Backlog

ID NOME DA ESTÓRIA IMP EST COMO DEMONSTRAR

1 CADASTRO DE CLIENTES 10 1

Usuário loga-se, clica em clientes, na

página clientes seleciona "criar novo",

insere os dados e clica em salvar.

2 CONTROLE DE VENDAS A

PRAZO 10 2

Se a forma de venda for a prazo, clica-se

em Venda a prazo, clica em "Criar

nova", seleciona cliente por código e

nome, insere dados da venda e salva.

3 CONSULTAR VENDAS A

PRAZO 10 2

Digita um dado sobre a venda no campo

buscar da sessão vendas a prazo e clica

em buscar

4 CONSULTAR CLIENTES 10 3

Digita um dado sobre o cliente no

campo buscar da sessão clientes e clica

em buscar

5 LISTAR CLIENTES 10 1 Clica em cliente e uma lista de clientes

cadastrados é exibida

6 LISTAR VENDAS A PRAZO 10 2 Clica em vendas a prazo e uma lista de

vendas é exibida

7 CADASTRO DE USUÁRIOS 10 1

Usuário com permissão "cria novo

usuário" fornecendo dados de nome,

login e senha

8 CONTROLE DE ACESSO 10 1

Verificar autenticidade do usuário, se o

mesmo se confirmar permite o acesso,

caso contrario retorna a tela anterior.

9 ...

10 ...

11 ...

Levando em conta o sprint gerado, a aplicação pode seguir o desenvolvimento. Com o

Grails como framework e as várias tecnologias que o acompanham, o primeiro módulo da

Page 59: 2011-Introdução ao Framework Grails

59

aplicação teve seu desenvolvimento inciado objetivando a implementação da parte do sistema

que faz o controle das vendas a prazo da empresa.

4.2.2 Preparando o ambiente para o sistema.

Para o desenvolvimento da aplicação em Grails algumas tecnologias e ferramentas

serão utilizadas, tais como:

o servidor HTTP Tomcat;

a IDE NetBeans;

o plugin Searchable;

o framework de testes JUnit;

o banco de dados MySql;

o gerenciador de layout SiteMesh;

o framework para modelo objeto-relacional Hibernate;

o framework para injeção de dependências Spring.

A versão do Grails utilizada nesta aplicação é a 1.2.2, estando o framework hoje em

sua versão 1.4. As demais ferramentas, com exceção do MySql, estão integradas na instalação

do framework Grails. A versão do MySql usada foi a 5.1.

Com a criação da base da aplicação e da estrutura de diretórios, o primeiro passo foi

customizar a aplicação para que ela agisse da maneira como se esperava, personalizando o

Grails para que fosse possível a implementação futura de estruturas de autenticação, por

exemplo, sem a necessidade de retrabalho. Este procedimento torna-se possível através da

instalação de templates que exibem uma lista de arquivos a serem configurados. Nesses

arquivos informa-se de que forma agirão os controladores, classes de domínio, visualizações,

testes, entre outros componentes quando usada a funcionalidade scaffold.

4.2.3 Classes de domínio e Controladores

O projeto do primeiro sprint partiu então para a criação das classes de domínio da

camada de modelo da aplicação. Nota-se pela análise das estórias do sprint a presença de

estórias com características semelhantes a outras do product backlog e que, com o recurso de

Page 60: 2011-Introdução ao Framework Grails

60

herança do modelo OO (Orientado a objetos), poupará o trabalho nos sprints posteriores. Uma

das estórias dessa questão é o “Cadastro de Clientes”, com a criação da classe Pessoa será

possível o reaproveitamento dos atributos da mesma através da herança dessa classe para a

classe de domínio Cliente e posteriormente para as classes Funcionário e Fornecedor.

Como já dito anteriormente, o modelo de desenvolvimento ágil e metodologias como

Scrum não possuem a necessidade de criação de todos os diagramas implementados pelo

modelo UML, no entanto não proíbem o seu uso. Para um melhor entendimento das classes

da aplicação solicitadas pelo dono do produto para esse primeiro sprint, torna-se importante a

criação do Diagrama de Classes apresentado na figura 4.1.

Figura 4.1 – Diagrama de Classes

Além das classes de domínio Pessoa.groovy e Cliente.groovy, tornou-se necessária a

criação da classe de domínio Usuario.groovy para possibilitar a criação do mecanismo de

acesso ao sistema. Para concluir as implementações da camada de modelo, a classe de

domínio VendasaPrazo.groovy foi criada para guardar as informações referentes a modalidade

de venda a prazo da empresa e realizar assim o objetivo do sprint de entregar algo funcional.

Page 61: 2011-Introdução ao Framework Grails

61

As figuras a seguir apresentam o código de implementação de algumas dessas classes criadas

em Grails, com seus respectivos atributos, validações e relacionamentos.

Figura 4.2 – Classe de domínio: Cliente.groovy

As figuras mostram o código com os atributos das classes conforme informado pelo

dono do produto no Diagrama de Classes, estendendo das classes pai alguns atributos e

acrescentando novos. Como se observa, mesmo na herança, a diferença para a sintaxe Java é

pouca e por isso a grande aceitação do Grails entre os desenvolvedores da plataforma.

As classes de domínio implementam ainda as validações (constraints) e o

relacionamento que as mesmas terão umas com as outras. No caso do problema deste sprint

deseja-se criar o sistema para controle de vendas a prazo, a classe Cliente exibida acima terá

relacionamento um-para-muitos com a classe VendasaPrazo, exibida na figura 4.3.

Page 62: 2011-Introdução ao Framework Grails

62

Figura 4.3 - Classes de domínio: VendasaPrazo.groovy

Algumas classes de domínio da aplicação terão seus respectivos controladores gerados

através do método scaffold do Grails, porém classes específicas com métodos próprios

evitarão este recurso por apresentar a necessidade de incluir informações além do que seria

gerado. A classe Pessoa, por exemplo, por ser usada para herança de outras classes, não

apresentou problemas no uso do scaffold.

4.2.4 Provendo Segurança do Sistema

A criação dos mecanismos de segurança do sistema começa pela classe de domínio

Usuario.groovy e seu respectivo controller. Chamam-se mecanismos de segurança nesta

aplicação as rotinas de autenticação de usuários e a codificação de senhas, além da limitação

de privilégios de acordo com o papel de cada usuário no sistema.

Grails oferece soluções prontas para autenticação de usuários, através do uso de

plugins, mas no caso deste problema a mesma se deu através de código programado

diretamente nos controladores e classes utilitárias.

Page 63: 2011-Introdução ao Framework Grails

63

Para o controle do acesso, a classe de controle Usuario recebeu a implementação das

closure login, authenticate e logout, cujos códigos possibilitam respectivamente o acesso,

autenticação e saída de sessão no sistema.

A closure login não possui código pois serve apenas para as chamadas à visualização

login.gsp que recebe os dados do usuário e realiza a autenticação conforme código da closure

authenticate. O código da closure logout realiza o encerramento da sessão do usuário.

Ainda no que diz respeito a controle de acesso, a implementação de uma classe filtro

para interceptar as tentativas de acesso e direcioná-las de acordo com a limitação do papel de

cada usuário é feita pela classe AdminFilters.groovy. Este filtro verifica se a sessão do usuário

encontra-se ativa e se o papel do usuário no sistema permite o acesso a determinada área

direcionando-o ou não a área seguinte.

Para a proteção de senhas de acesso é utilizado uma classe utilitária que codifica as

senhas geradas através do método encodeAsBase64. As senhas ficam assim protegidas sendo

gravadas nas bases de dados de modo mais seguro. Grails possibilita esses entre outros

recursos para segurança, porém por tratar-se de simples acesso a aplicação reservou-se a

implementação de mecanismos mais poderosos de segurança para os sprints posteriores do

projeto.

4.2.5 Desenvolvendo direcionado a Testes

Seguindo a „tradição‟ do modelo ágil de desenvolvimento a execução de testes

automatizados se faz necessária durante todo o processo de desenvolvimento, assim antes de

seguir para persistência de dados, foram criadas classes de testes para garantir a estabilidade

da aplicação evitando erros.

No ato de criação de classes de domínio, controle e de biblioteca de marcas, Grails

automaticamente cria uma classe teste para cada uma. Os testes implementados por essas

classes são conhecidos por testes unitários que testa partes da aplicação separadamente antes

de integrar-se a banco de dados ou servidores HTTP, por exemplo. Para realizar estes testes o

Grails utiliza o pacote de testes, que se baseia no framework de testes JUnit e, por sua vez,

cada classe de teste unitário em Grails é uma extensão de GrailsUnitTestCase, para classes de

domínio; ControllerUnitTestCase, para controladores; e TagLibUnitTestCase, para

Page 64: 2011-Introdução ao Framework Grails

64

bibliotecas de marca. A figura 4.4 ilustra a hierarquia das classes de testes do Grails incluindo

as classes de teste desta aplicação.

Figura 4.4 – Diagrama Hierárquico das Classes de Testes

Os testes necessários para essa primeira parte da aplicação objetivam-se a testar

validação das classes de domínio e o funcionamento de algumas rotinas dos controladores,

desta maneira evitando antecipadamente a presença de erros.

No decorrer dos testes unitários, por exemplo, foram notados erros nas classes de

domínio e de controle Usuário, o que permitiu a correção dos mesmos antes de prosseguir

com o restante do desenvolvimento. Isso mostra importância do uso de testes durante o

desenvolvimento e não somente após a aplicação pronta, com a realização dos chamados

testes de caixa branca. O desenvolvimento direcionado a testes é algo natural nas tecnologias

ágeis e exigência do modelo ágil de desenvolvimento, isso garante maior precisão no código e

consequentemente a diminuição do retrabalho.

Em Grails, por tratar-se de uma ferramenta em que os objetos e métodos só são

instanciados e chamados em tempo de execução, para execução de testes existe o recurso

chamado mock que simula uma aplicação em execução no próprio código, garantindo o

sucesso do teste.

Para visualizar os resultados dos testes, Grails guarda no diretório da aplicação um

arquivo HTML que mostra se o teste passou ou não, ou se apresentou algum erro que impedia

Page 65: 2011-Introdução ao Framework Grails

65

o seu sucesso. A figura 4.5 apresenta a tela do resultado dos testes da aplicação, com os

respectivos erros ou falhas.

Figura 4.5 – Tela Unit Test Results

Antes da persistência de dados, porém testes de execução da aplicação também são

necessários e um recurso que auxilia este tipo de teste populando os campos das classes para

comprovar o sucesso das rotinas de código é o BootStrap do Grails.

No BootStrap as classes podem assumir valores criando instâncias das mesmas que em

tempo de execução fazem o preenchimento dos campos permitindo-se analisar, por exemplo,

o estado das visualizações como list, show e edit; e os testes de acesso e autenticação de

usuário.

4.2.6 Conectando ao Banco de Dados

Para persistência de dados da aplicação foi escolhido o banco de dados MySql pelas

característica de ser de simples configuração e apresentar bastante compatibilidade com o

Grails. Usando os recursos da linguagem, a conexão do banco ao sistema não apresentou

grandes problemas e o trabalho de criação de estrutura SQL ficou a cargo do GORM do

Grails junto ao framework Hibernate, através do método dbcreate configurado no

DataSource.groovy.

Page 66: 2011-Introdução ao Framework Grails

66

Durante o desenvolvimento, porém o uso do BootStrap do Grails juntamente com o

banco de dados padrão do framework, o HSQLDB, foi de grande ajuda para testes das funções

implementadas até que por fim os bancos de dados foram criados no MySql.

Utilizando a divisão de ambientes do DataSource, foram criados 3 bancos de dados

para: desenvolvimento, testes e produção. O recurso foi utilizado pensando na continuidade

do sistema nos sprints posteriores.

4.2.7 Visualizações da aplicação

Para a camada de visualização da aplicação não houve exigência específica a respeito

de design. Para cada classe de domínio foi criado um diretório que continham as visualizações

básicas geradas através do comando grails generate all. Cada visualização criada no diretório

está diretamente ligada a determinadas closures da classe de controle, assim as views: list.gsp,

create.gsp, show.gsp e edit.gsp, não apresentaram grandes alterações do que foi gerado pelo

Grails, mas a inclusão de views extras foi necessária, como o caso do login.gsp.

Através do SiteMesh, que o Grails apresenta para o suporte a layout, foi possível

personalizar a aplicação criando bibliotecas de marcas e templates parciais que ofereceram

recursos para simplificar o acesso as partes do sistema. Através do SiteMesh também foi feita

a inclusão do logotipo da empresa no topo da aplicação e a página principal gerada pelo

Grails foi alterada para apresentar os recursos de forma mais organizada.

As figuras a seguir apresentam as principais telas da aplicação:

Page 67: 2011-Introdução ao Framework Grails

67

Figura 4.6 – Tela Principal

Figura 4.7 – Tela de Login

Page 68: 2011-Introdução ao Framework Grails

68

Figura 4.8 – Tela Listar Clientes

Figura 4.9 – Tela Mostra Usuário

Page 69: 2011-Introdução ao Framework Grails

69

Figura 4.10 – Tela Criar Venda a Prazo

4.2.8 Trabalhando com plugins

Durante o desenvolvimento da aplicação uma mudança no „escopo‟ do sprint foi

pedida pelo dono do produto. Ao acompanhar o desenvolvimento e observar o modelo de

consulta criado através de listagem o dono do produto pediu que fosse implementado um

mecanismo de busca rápida que retornasse as principais informações dos clientes cadastrados.

O desafio de desenvolver algo para esse pedido foi facilmente solucionado por um dos

recursos oferecidos pelo Grails. Através da instalação do plugin Searchable, foi possível criar

o mecanismo de busca solicitado.

O uso de plugins é uma característica que garante a expansibilidade e o

aproveitamento de código do Grails, duas das características básicas das ferramentas ágeis. O

plugin em questão foi então inserido ao projeto através do comando grails install plugin e

devidamente configurado para possibilitar a busca de informações de clientes. Apesar de estar

integrado ao projeto, os plugins instalados através deste comando são alocados em um

diretório diferente do diretório fonte da aplicação. Os códigos compilados pelo Grails são

Page 70: 2011-Introdução ao Framework Grails

70

alocados no diretório .grails, e neste mesmo diretório são alocados os arquivos dos plugins

instalados sendo os mesmos chamados em tempo de execução.

O trabalho por traz do plugin Searchable está na implementação de um serviço que

caracteriza-se por possibilitar lógica de negócio e comportamento a mais de uma classe de

domínio. O trabalho por traz dessa proeza fica por conta do Spring framework através da

injeção de dependência entre essas classes.

Na inserção de mais essa funcionalidade ao sistema, foi necessária ainda a criação de

uma view que apresentasse o resultado das buscas feitas pelo Searchable, bem como da

inclusão do respectivo formulário de busca. A tela da figura abaixo mostra o resultado de uma

busca simples no sistema.

Figura 4.11 – Tela Mostrar Resultados da busca

4.2.9 Implantando a aplicação

O último passo para que o resultado do primeiro sprint possa ser apresentado diz

respeito a preparar a aplicação para ser implantada. Até o momento toda a execução da

aplicação ocorreu no ambiente de desenvolvimento, através do comando grails run-app. Para

Page 71: 2011-Introdução ao Framework Grails

71

que a aplicação funcione no modo de produção em Grails, necessita ser gerado um arquivo

WAR (Web Application Archive) que prepara a aplicação com todos os componentes que a

integram deixando a pronta para a realização de deploy no Tomcat ou outro servidor utilizado.

Um detalhe importante da configuração dessa etapa é a atenção exigida com as

informações inseridas nos arquivos de configuração da aplicação, localizados no diretório

grails-app/conf. Em DataSource.groovy é preciso certificar-se de que as configurações de

conexão e acesso a bases de dados estejam corretamente implementadas.

No arquivo Config.groovy é feita então a configuração do Tomcat, ou outro servidor,

para que o mesmo realize o deploy da aplicação corretamente. Neste caso, é preciso observar

na configuração do servidor o tipo de usuário que possui permissão para realizar o deploy e

caso o mesmo não exista providenciar sua criação. No Config.groovy informa-se nome de

usuário, senha e a url da aplicação, incluindo o endereço da porta do servidor.

Com tudo devidamente conferido, o comando grails war cria o arquivo .war com o

nome e versão da aplicação contido no arquivo application.properties e que, no caso da

aplicação em estudo, gerou o arquivo: SisGesso-0.1.war. Um diretório de nome /war dentro

do diretório .grails/1.2.2/projects/SisGesso armazena todos os componentes da aplicação

desde as classes de domínio e controladores até as imagens e templates da camada de

visualização, conforme demonstra a estrutura da árvore de diretórios da figura 4.12.

Page 72: 2011-Introdução ao Framework Grails

72

Figura 4.12 – Árvore de diretórios war.

Com o arquivo .war gerado é preciso apenas instalar o mesmo no servidor de

aplicações escolhido, tendo o Grails compatibilidade com vários dos servidores da plataforma

java.

Finalizado o primeiro sprint da aplicação o sistema pode ser entregue ao cliente para

uso e retorno de informações para o prosseguimento nos sprints posteriores. O Grails permite

fácil manipulação das estruturas de códigos permitindo recuperar-se até mesmo depois de um

deploy sem sucesso através do comando undeploy no servidor de aplicações escolhido.

Page 73: 2011-Introdução ao Framework Grails

73

5 CONSIDERAÇÕES FINAIS

5.1 CONCLUSÕES

O atual do mercado de desenvolvimento de software tem exigido ferramentas que

facilitem o trabalho dos desenvolvedores proporcionando o maior aproveitamento do tempo

que dispõem e voltando o foco para a criatividade no processo de desenvolvimento. Desta

busca por soluções foi que se expandiu o uso de frameworks na intenção de livrar o

desenvolvedor de uma gama de trabalho repetitivo e detalhes técnicos.

Este trabalho fez uma introdução ao framework Grails surgindo como solução para a

plataforma Java nas novas exigências de mercado. Foram citadas as principais tecnologias e

funcionalidades do Grails e de que forma o mesmo está integrado ao Java.

Através de comparações ressaltou-se as vantagens e desvantagens da plataforma Java

perante o Ruby on Rails, plataforma de desenvolvimento web de grande crescimento nos

últimos anos, e que serviu de inspiração para o surgimento do Grails. Apresentou-se ainda a

linguagem de programação Groovy, numa rápida introdução a suas características e

funcionalidades.

O trabalho apresentou ainda um estudo de caso que demonstrou todo processo de

desenvolvimento de uma aplicação através do framework Grails. Procurou-se demonstrar de

forma prática a utilização da metodologia ágil Scrum para exemplificar todo processo de

gerenciamento de software do modelo ágil de desenvolvimento. Através do Scrum foram

listadas as funcionalidades de um problema real e criou-se um módulo de uma aplicação para

solução do mesmo.

O uso do framework Grails no desenvolvimento de aplicações web mostra-se

promissor principalmente aos desenvolvedores da plataforma Java, já acostumados as

tecnologias que o Grails incorpora. Porém, a curta curva de aprendizado faz do framework

uma ótima solução para desenvolvimento de aplicações simples e de rápido desenvolvimento.

Foi mostrado que o objetivo de ferramentas como o Grails é fazer o trabalho do

desenvolvedor ter enfoque ao que realmente se espera do mesmo: a criação de novas soluções

em softwares sem grandes preocupações com configurações o tempo todo como ocorre com

muitas plataformas. Seguindo princípios como „Convention over Configuration’ e „Don’t

Page 74: 2011-Introdução ao Framework Grails

74

Repeat Yourself’, Grails faz jus ao que prega o Manifesto Ágil de 2001 para desenvolvimento

de soluções de software.

Espera-se com isso ter conseguido produzir conhecimento introdutório que motivem

aos desenvolvedores na busca constante por atualizações e o conhecimento de novas

ferramentas para o processo de desenvolvimento de software.

5.2 TRABALHOS FUTUROS

O sistema proposto no estudo de caso apresentado mostrou a criação de apenas um

módulo do mesmo, representado através do sprint do Scrum. Para trabalhos futuros pretende-

se dar continuidade ao desenvolvimento do mesmo implementando outros módulos em

sprints posteriores.

Desta forma pretende-se ainda buscar um maior aprofundamento das funcionalidades e

recursos proporcionados pelo Grails para desenvolvimento de software para web.

Page 75: 2011-Introdução ao Framework Grails

75

REFERÊNCIAS BIBLIOGRÁFICAS

[ABDU 09] ABDUL-JAWAD, Bashar. Groovy and Grails Recipes. United States of

America: Apress, 2009.

[BARR 09] BARRETO, Juliano. Histórias do pai do Ruby on Rails. Disponível em:

<http://info.abril.com.br/professional/desenvolvimento/o-rails-e-lindo.shtml?3>. Acessado em

14/04/2011 às 18 horas e 20 minutos.

[BROW 09] BROWN, Jeff & ROCHER, Graeme. The Definitive Guide to Grails (2nd

ed.).

United States of America: Apress, 2009.

[CARV 08] CARVALHO, Marlon. Spring Framework: Introdução. Disponível em:

<http://imasters.com.br/artigo/4497/spring_framework_introducao>.

Acessado em 25/05/2011 às 16 horas e 20 minutos.

[DAVI 10] DAVIS, Scott & RUDOLPH, Jason. Getting Started with Grails – Second

Edition. United States of America: InfoQ, 2010.

[DEPA 10] Departamento de Sistemas e Computação da UFCG. O que são frameworks?

Disponível em <http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/frame/oque.htm>.

Acessado em 31/05/2010 às 15 horas.

[KÖNI 07] KÖNIG, Dierk. Groovy em Ação (Ed. Traduzida). Rio de Janeiro: Alta Books,

2007.

[MACO 10] MACORATTI, José Carlos. Padrões de Projeto: O modelo MVC – Model

View Controller. Disponível em < http://www.macoratti.net/vbn_mvc>. Acessado em

31/05/2010 às 15 horas.

[MORE 09] MOREIRA, Daniela. Desenvolvimento ágil funciona? Disponível em

<http://info.abril.com.br/noticias/ti/desenvolvimento-agil-funciona-30062009-3.shl>.

Acessado em 16/05/2010 às 23 horas e 50 minutos.

[RODR 02] RODRIGUEZ, Martius Vicente Rodriguez y. Gestão do Conhecimento nas

Empresas. Rio de Janeiro: E-papers Serviços Editoriais, 2002.

[SIER 05] SIERRA, Kathe & BATES, Bert. Use a cabeça! Java (2ª ed). Rio de Janeiro: Alta

Books, 2005.

Page 76: 2011-Introdução ao Framework Grails

76

[SMIT 09] SMITH, Glen & LEDBROOK, Peter. Grails in Action (1st ed). United States of

America: Manning Publications, 2009.

Page 77: 2011-Introdução ao Framework Grails

77

ANEXO A – CÓDIGO FONTE

// Classe de Domínio Cliente.groovy

package sisgesso

class Cliente extends Pessoa{

String email

String telCel

String outrasInf

static hasMany = [vendasaprazos: VendasaPrazo] //o método hasMany define o relacionamento

// um-para-muitos (um cliente tem muitas vendas a prazo)

static searchable = true

String toString(){"${this.nome}" - "${this.tel}"}

static constraints = {

email(email:true)

telCel()

outrasInf()

}

}

Cliente.groovy

//Classe de domínio Pessoa.groovy

package sisgesso

class Pessoa {

String nome //Tambem receberá razão social sem diferenciação especifica

String cpf //ou cnpj, caso pessoa jurídica, no mesmo campo

String rua

String numero

String bairro

String complemento

String cep

String cidade

String uf

String tel

static opcional = ["cpf","complemento", "tel"] //Campos não obrigatórios

static constraints = {

nome(maxSize:130,blank:false)

cpf(maxSize:18)

rua()

Page 78: 2011-Introdução ao Framework Grails

78

numero()

bairro()

complemento()

cidade ()

uf(inList:['AC','AL','AM','AP','BA','CE','DF','ES','GO','MA','MG','MS','MT','PA',

'PB','PE','PI','PR','RJ','RN','RO','RR','RS','SC','SE','SP','TO'],blank:false)

cep()

tel()

}

static mapping = {

sort "nome" // listar por ordem alfabética do nome

}

}

Pessoa.groovy

// Classe de domínio Usuario.groovy

package sisgesso

class Usuario {

String nome

String login

String senha

String papel = "usuario"

static transients = ['admin']

boolean isAdmin(){

return papel == "admin"

}

static constraints = {

nome()

login(blank:false, nullable:false, unique:true)

senha(blank:false, password:true)

papel(inList:["usuario","admin"])

}

String toString(){

login

}

def beforeInsert = {

senha = senha.encodeAsSHA()

}

}

Usuario.groovy

//Classe de domínio VendasaPrazo.groovy

package sisgesso

class VendasaPrazo {

Cliente cliente

int numVenda

Date dataVenda

BigDecimal valorTotal

BigDecimal valorPago = 0

BigDecimal valorReceber

Page 79: 2011-Introdução ao Framework Grails

79

Date dataPagamento = new Date()

String toString (){

"${this.numVenda}" - "${this.valorTotal}"

}

static belongsTo = [Cliente] //o método indica o relacionamento que a classe tem com Cliente

//(pertence a Cliente)

static optionals = ["valorPago", "valorReceber"]

def beforeInsert = {

valorReceber = valorTotal - valorPago

}

static constraints = {

cliente()

numVenda(blank:false,unique:true)

dataVenda(format:"dd/mm/aaaa")

valorTotal (min:0.0,scale:2)

valorPago (nullable:true)

valorReceber (nullable:true, display:false)

dataPagamento (format:"dd/mm/aaaa")

}

}

VendasaPrazo.groovy

//Classe de Controle ClienteController.groovy

package sisgesso

class ClienteController {

static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

def index = {

redirect(action: "list", params: params)

}

def search = {

flash.message = "Resultados da procura por: ${params.q}"

def resultsMap = Cliente.search(params.q, params)

render(view:'list_resultsSearch',

model:[clienteInstanceList:resultsMap.results,

clienteInstanceTotal:Cliente.countHits(params.q)]

)

}

def list = {

params.max = Math.min(params.max ? params.int('max') : 10, 100)

[clienteInstanceList: Cliente.list(params), clienteInstanceTotal: Cliente.count()]

}

def create = {

def clienteInstance = new Cliente()

clienteInstance.properties = params

return [clienteInstance: clienteInstance]

}

def save = {

def clienteInstance = new Cliente(params)

if (clienteInstance.save(flush: true)) {

Page 80: 2011-Introdução ao Framework Grails

80

flash.message = "${message(code: 'default.created.message',

args: [message(code: 'cliente.label', default: 'Cliente'), clienteInstance.id])}"

redirect(action: "show", id: clienteInstance.id)

}

else {

render(view: "create", model: [clienteInstance: clienteInstance])

}

}

def show = {

def clienteInstance = Cliente.get(params.id)

if (!clienteInstance) {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'cliente.label', default: 'Cliente'), params.id])}"

redirect(action: "list")

}

else {

[clienteInstance: clienteInstance]

}

}

def edit = {

def clienteInstance = Cliente.get(params.id)

if (!clienteInstance) {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'cliente.label', default: 'Cliente'), params.id])}"

redirect(action: "list")

}

else {

return [clienteInstance: clienteInstance]

}

}

def update = {

def clienteInstance = Cliente.get(params.id)

if (clienteInstance) {

if (params.version) {

def version = params.version.toLong()

if (clienteInstance.version > version) {

clienteInstance.errors.rejectValue("version", "default.optimistic.locking.failure",

[message(code: 'cliente.label', default: 'Cliente')] as Object[],

"Another user has updated this Cliente while you were editing")

render(view: "edit", model: [clienteInstance: clienteInstance])

return

}

}

clienteInstance.properties = params

if (!clienteInstance.hasErrors() && clienteInstance.save(flush: true)) {

flash.message = "${message(code: 'default.updated.message',

args: [message(code: 'cliente.label', default: 'Cliente'), clienteInstance.id])}"

redirect(action: "show", id: clienteInstance.id)

}

else {

render(view: "edit", model: [clienteInstance: clienteInstance])

}

}

Page 81: 2011-Introdução ao Framework Grails

81

else {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'cliente.label', default: 'Cliente'), params.id])}"

redirect(action: "list")

}

}

def delete = {

def clienteInstance = Cliente.get(params.id)

if (clienteInstance) {

try {

clienteInstance.delete(flush: true)

flash.message = "${message(code: 'default.deleted.message',

args: [message(code: 'cliente.label', default: 'Cliente'), params.id])}"

redirect(action: "list")

}

catch (org.springframework.dao.DataIntegrityViolationException e) {

flash.message = "${message(code: 'default.not.deleted.message',

args: [message(code: 'cliente.label', default: 'Cliente'), params.id])}"

redirect(action: "show", id: params.id)

}

}

else {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'cliente.label', default: 'Cliente'), params.id])}"

redirect(action: "list")

}

}

}

ClienteController.groovy

//Classe de Controle PessoaController.groovy

package sisgesso

class PessoaController {

def scaffold = true

}

PessoaController.groovy

//Classe de Controle UsuarioController.groovy

package sisgesso

class UsuarioController {

static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

def login = { }

def logout = {

flash.message = "Até breve ${session.usuario.login}"

session.usuario = null

redirect(action:"login")

}

def authenticate = {

Page 82: 2011-Introdução ao Framework Grails

82

def usuario = Usuario.findByLoginAndSenha(params.login, params.senha.encodeAsSHA())

if(usuario){

session.usuario = usuario

flash.message = "Olá ${usuario.login}!"

redirect(uri:"/")

}else{

flash.message = "Desculpe, ${params.login}. Por favor tente novamente."

redirect(action:"login")

}

}

def index = {

redirect(action: "list", params: params)

}

def list = {

params.max = Math.min(params.max ? params.int('max') : 10, 100)

[usuarioInstanceList: Usuario.list(params), usuarioInstanceTotal: Usuario.count()]

}

def create = {

def usuarioInstance = new Usuario()

usuarioInstance.properties = params

return [usuarioInstance: usuarioInstance]

}

def save = {

def usuarioInstance = new Usuario(params)

if (usuarioInstance.save(flush: true)) {

flash.message = "${message(code: 'default.created.message',

args: [message(code: 'usuario.label', default: 'Usuario'), usuarioInstance.id])}"

redirect(action: "show", id: usuarioInstance.id)

}

else {

render(view: "create", model: [usuarioInstance: usuarioInstance])

}

}

def show = {

def usuarioInstance = Usuario.get(params.id)

if (!usuarioInstance) {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'usuario.label', default: 'Usuario'), params.id])}"

redirect(action: "list")

}

else {

[usuarioInstance: usuarioInstance]

}

}

def edit = {

def usuarioInstance = Usuario.get(params.id)

if (!usuarioInstance) {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'usuario.label', default: 'Usuario'), params.id])}"

redirect(action: "list")

}

else {

return [usuarioInstance: usuarioInstance]

Page 83: 2011-Introdução ao Framework Grails

83

}

}

def update = {

def usuarioInstance = Usuario.get(params.id)

if (usuarioInstance) {

if (params.version) {

def version = params.version.toLong()

if (usuarioInstance.version > version) {

usuarioInstance.errors.rejectValue("version",

"default.optimistic.locking.failure", [message(code: 'usuario.label',

default: 'Usuario')] as Object[],

"Another user has updated this Usuario while you were editing")

render(view: "edit", model: [usuarioInstance: usuarioInstance])

return

}

}

usuarioInstance.properties = params

if (!usuarioInstance.hasErrors() && usuarioInstance.save(flush: true)) {

flash.message = "${message(code: 'default.updated.message',

args: [message(code: 'usuario.label', default: 'Usuario'), usuarioInstance.id])}"

redirect(action: "show", id: usuarioInstance.id)

}

else {

render(view: "edit", model: [usuarioInstance: usuarioInstance])

}

}

else {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'usuario.label', default: 'Usuario'), params.id])}"

redirect(action: "list")

}

}

def delete = {

def usuarioInstance = Usuario.get(params.id)

if (usuarioInstance) {

try {

usuarioInstance.delete(flush: true)

flash.message = "${message(code: 'default.deleted.message',

args: [message(code: 'usuario.label', default: 'Usuario'), params.id])}"

redirect(action: "list")

}

catch (org.springframework.dao.DataIntegrityViolationException e) {

flash.message = "${message(code: 'default.not.deleted.message',

args: [message(code: 'usuario.label', default: 'Usuario'), params.id])}"

redirect(action: "show", id: params.id)

}

}

else {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'usuario.label', default: 'Usuario'), params.id])}"

redirect(action: "list")

}

}

}

Page 84: 2011-Introdução ao Framework Grails

84

UsuarioController.groovy

//Classe de controle VendasaPrazoController.groovy

package sisgesso

class VendasaPrazoController {

static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

def index = {

redirect(action: "list", params: params)

}

def search = {

render VendasaPrazo.search(params.q, params)

}

def list = {

params.max = Math.min(params.max ? params.int('max') : 10, 100)

[vendasaPrazoInstanceList: VendasaPrazo.list(params),

vendasaPrazoInstanceTotal: VendasaPrazo.count()]

}

def create = {

def vendasaPrazoInstance = new VendasaPrazo()

vendasaPrazoInstance.properties = params

return [vendasaPrazoInstance: vendasaPrazoInstance]

}

def save = {

def vendasaPrazoInstance = new VendasaPrazo(params)

if (vendasaPrazoInstance.save(flush: true)) {

flash.message = "${message(code: 'default.created.message',

args: [message(code: 'vendasaPrazo.label',

default: 'VendasaPrazo'), vendasaPrazoInstance.id])}"

redirect(action: "show", id: vendasaPrazoInstance.id)

}

else {

render(view: "create", model: [vendasaPrazoInstance: vendasaPrazoInstance])

}

}

def show = {

def vendasaPrazoInstance = VendasaPrazo.get(params.id)

if (!vendasaPrazoInstance) {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'), params.id])}"

redirect(action: "list")

}

else {

[vendasaPrazoInstance: vendasaPrazoInstance]

}

}

def edit = {

def vendasaPrazoInstance = VendasaPrazo.get(params.id)

if (!vendasaPrazoInstance) {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'), params.id])}"

redirect(action: "list")

}

Page 85: 2011-Introdução ao Framework Grails

85

else {

return [vendasaPrazoInstance: vendasaPrazoInstance]

}

}

def update = {

def vendasaPrazoInstance = VendasaPrazo.get(params.id)

if (vendasaPrazoInstance) {

if (params.version) {

def version = params.version.toLong()

if (vendasaPrazoInstance.version > version) {

vendasaPrazoInstance.errors.rejectValue("version", "default.optimistic.locking.failure",

[message(code: 'vendasaPrazo.label', default: 'VendasaPrazo')] as Object[],

"Another user has updated this VendasaPrazo while you were editing")

render(view: "edit", model: [vendasaPrazoInstance: vendasaPrazoInstance])

return

}

}

vendasaPrazoInstance.properties = params

if (!vendasaPrazoInstance.hasErrors() && vendasaPrazoInstance.save(flush: true)) {

flash.message = "${message(code: 'default.updated.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'),

vendasaPrazoInstance.id])}"

redirect(action: "show", id: vendasaPrazoInstance.id)

}

else {

render(view: "edit", model: [vendasaPrazoInstance: vendasaPrazoInstance])

}

}

else {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'), params.id])}"

redirect(action: "list")

}

}

def delete = {

def vendasaPrazoInstance = VendasaPrazo.get(params.id)

if (vendasaPrazoInstance) {

try {

vendasaPrazoInstance.delete(flush: true)

flash.message = "${message(code: 'default.deleted.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'), params.id])}"

redirect(action: "list")

}

catch (org.springframework.dao.DataIntegrityViolationException e) {

flash.message = "${message(code: 'default.not.deleted.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'), params.id])}"

redirect(action: "show", id: params.id)

}

}

else {

flash.message = "${message(code: 'default.not.found.message',

args: [message(code: 'vendasaPrazo.label', default: 'VendasaPrazo'), params.id])}"

redirect(action: "list")

}

}

}

Page 86: 2011-Introdução ao Framework Grails

86

VendasaPrazoController.groovy

//Classe para codificação de Senhas SHACodec.groovy

import java.security.MessageDigest

class SHACodec{

static encode = {target->

MessageDigest md = MessageDigest.getInstance('SHA')

md.update(target.getBytes('UTF-8'))

return new String(md.digest()).encodeAsBase64()

}

}

SHACodec.groovy

//Classe Filtro para administração de acesso de usuários AdminFilters.groovy

package sisgesso

class AdminFilters {

def filters = {

usuariosLogados(controller:"*", action:"(list|show|create|edit|update|delete|save)")

{

before = {if(!session?.usuario) {

redirect(controller:"usuario", action:"login")

return false

}

}

}

adminOnly(controller:'usuario',

action:"(create|edit|update|delete|save)") {

before = {

if(!session.usuario.admin){

flash.message = "Somentes Usuários Administradores"

redirect(uri:"/")

return false

}

}

}

}

}

AdminFilters.groovy

//Biblioteca de Marcas para template parcial LogarTagLib.groovy

package sisgesso

class LogarTagLib {

def loginControl = {

if(request.getSession(false) && session.usuario){

out << "Olá ${session.usuario.login} "

Page 87: 2011-Introdução ao Framework Grails

87

out << """[${link(action:"logout",

controller:"usuario"){"Sair"}}]"""

} else {

out << """[${link(action:"login",

controller:"usuario"){"Entrar"}}]"""

}

}

def isAdmin = {

}

def loggedIn = {

}

}

LogarTagLib.groovy

//Biblioteca de Marcas para template parcial RodapeTagLib.groovy

package sisgesso

class RodapeTagLib {

def thisYear = {

out << new Date().format("yyyy")

}

def copyright = {attrs, body->

out << "&copy; " + attrs.startYear + " - "

out << thisYear() + " " + body()

}

}

RodapeTagLib.groovy

//Classe de Testes ClienteControllerTests.groovy

package sisgesso

import grails.test.*

class ClienteControllerTests extends ControllerUnitTestCase {

protected void setUp() {

super.setUp()

}

protected void tearDown() {

super.tearDown()

}

void testIndex() {

controller.index()

assertEquals "list",

controller.redirectArgs["action"]

}

void testShow(){

def Cli = new Cliente(nome:"Cliente")

def Cli2 = new Cliente(nome:"Cliente2")

Page 88: 2011-Introdução ao Framework Grails

88

mockDomain(Cliente, [Cli, Cli2])

controller.params.id = 2

def map = controller.show()

assertEquals "Cliente2", map.clienteInstance.nome

}

}

ClienteControllerTests.groovy

//Classe de Testes ClienteTests.groovy

package sisgesso

import grails.test.*

class ClienteTests extends GrailsUnitTestCase {

protected void setUp() {

super.setUp()

}

protected void tearDown() {

super.tearDown()

}

void testConstraints() {

mockDomain Cliente

//testes para validar atributos

def cliente = new Cliente()

assertFalse cliente.validate()

def cliente_ok = new Cliente(nome:"Fulano de tal", cpf:"123.456.700-89",

rua:"A", numero:"12", bairro:"Qualquer",

complemento:"casa", cep:"28970-000",

cidade:"Rio de Janeiro", uf:"RJ", tel:"0000000",

email:"[email protected]", telCel:"9999-9999",

outrasInf:"isso é um teste")

assertTrue cliente_ok.validate()

}

void testValidar_nome() {

mockDomain Cliente

def cliente_Nome = new Cliente(cpf:"123.456.700-89",

rua:"A", numero:"12", bairro:"Qualquer",

complemento:"casa", cep:"28970-000", cidade:"Rio de Janeiro",

uf:"RJ", tel:"0000000", email:"[email protected]",

telCel:"9999-9999", outrasInf:"isso é um teste")

assertFalse cliente_Nome.validate() //Campo nome é obrigatório

}

void testValidar_cpf() {

mockDomain Cliente

def cliente_validarCpf = new Cliente(nome:"Fulano de tal",

cpf:"123.456.700-8900000000000000000",

rua:"A", numero:"12", bairro:"Qualquer",

complemento:"casa", cep:"28970-000", cidade:"Rio de Janeiro",

uf:"RJ", tel:"0000000",

Page 89: 2011-Introdução ao Framework Grails

89

email:"[email protected]", telCel:"9999-9999",

outrasInf:"isso é um teste")

assertFalse cliente_validarCpf.validate() //Cpf não deve ser > 18

}

void testValidar_email(){

mockDomain Cliente

def cliente_validarEmail = new Cliente(nome:"Fulano de tal",cpf:"123.456.700-89",

rua:"A", numero:"12", bairro:"Qualquer",

complemento:"casa", cep:"28970-000", cidade:"Rio de Janeiro",

uf:"RJ", tel:"0000000",

email:"fulano", telCel:"9999-9999", outrasInf:"isso é um teste")

assertFalse cliente_validarEmail.validate() //formato de email inválido o correto é

//[email protected]

}

void testValidar_uf(){

mockDomain Cliente

def cliente_validarUf = new Cliente(nome:"Fulano de tal",cpf:"123.456.700-89",

rua:"A", numero:"12", bairro:"Qualquer",

complemento:"casa", cep:"28970-000", cidade:"Rio de Janeiro",

uf:"KK", tel:"0000000",

email:"fulano", telCel:"9999-9999", outrasInf:"isso é um teste")

assertFalse cliente_validarUf.validate()

assertEquals "inList", cliente_validarUf.errors["uf"]// O valor de uf não consta na lista

}

}

ClienteTests.groovy

//Classe de Testes UsuarioTests.groovy

package sisgesso

import grails.test.*

class UsuarioTests extends GrailsUnitTestCase {

protected void setUp() {

super.setUp()

}

protected void tearDown() {

super.tearDown()

}

void testContraints() {

mockDomain Usuario

def usuario = new Usuario()

assertFalse usuario.validate()

def usuario_ok = new Usuario(nome:"Adriano", login:"aba",

senha:"123456", papel:"Superadmin")

assertFalse usuario_ok.validate()

assertEquals "inList", usuario_ok.errors["papel"]

}

void testLoginUnico(){

Page 90: 2011-Introdução ao Framework Grails

90

def usuario = new Usuario(login:"aba")

def admin = new Usuario(login:"admin")

mockDomain (Usuario, [usuario,admin])

def usuario_repetido = new Usuario(login:"aba")

usuario_repetido.save()

assertEquals 2, Usuario.count()

assertEquals "unique", usuario_repetido.errors["login"] // O login 'aba' já está sendo usado

def usuario_unique = new Usuario(nome:"Adriano", login:"abaok",

senha:"123456", papel:"admin")

usuario_unique.save()

assertEquals 3, usuario_unique.count()

}

}

UsuarioTests.groovy

//Classe de Testes UsuarioControllerTests.groovy

package sisgesso

import grails.test.*

import org.codehaus.groovy.grails.plugins.codecs.*

class UsuarioControllerTests extends ControllerUnitTestCase {

protected void setUp() {

super.setUp()

String.metaClass.encodeAsBase64 = {->

Base64Codec.encode(delegate)

}

String.metaClass.encodeAsSHA = {->

SHACodec.encode(delegate)

}

}

protected void tearDown() {

super.tearDown()

}

void testIndex() {

controller.index()

assertEquals "list",

controller.redirectArgs["action"]

}

void testShow(){

def aba = new Usuario(login:"aba")

def usuario = new Usuario(login:"usuario")

mockDomain(Usuario, [aba, usuario])

controller.params.id = 2

def map = controller.show()

assertEquals "usuario", map.usuarioInstance.login

Page 91: 2011-Introdução ao Framework Grails

91

}

void testAutenticacao() {

def aba = new Usuario(login:"aba", senha:"123456".encodeAsSHA())

mockDomain(Usuario, [aba])

controller.params.login = "aba"

controller.params.senha = "123456"

controller.authenticate()

assertNotNull controller.session.usuario

assertEquals "aba", controller.session.usuario.login

controller.params.senha = "123"

controller.authenticate()

assertTrue controller.flash.message.startsWith("Desculpe, aba")

}

}

UsuarioControllerTests.groovy

//Classe de Teste VendasaPrazoTests.groovy

package sisgesso

import grails.test.*

class VendasaPrazoTests extends GrailsUnitTestCase {

protected void setUp() {

super.setUp()

}

protected void tearDown() {

super.tearDown()

}

void testContraints() {

mockDomain VendasaPrazo

def venda = new VendasaPrazo()

assertFalse venda.validate()

def venda_ok = new VendasaPrazo(cliente:"Adriano", numVenda: 3,

dataVenda:new Date(), valorTotal:-5, valorPago:45,

dataPagamento:new Date())

assertFalse venda_ok.validate()

assertEquals "min", venda_ok.errors["valorTotal"]

}

void testNumerovendaUnico(){

def venda = new VendasaPrazo(numVenda: 5)

def venda2 = new VendasaPrazo(numVenda: 4)

mockDomain (VendasaPrazo, [venda,venda2])

def venda_repetida = new VendasaPrazo(numVenda: 5)

venda_repetida.save()

assertEquals 2, VendasaPrazo.count()

assertEquals "unique", venda_repetida.errors["numVenda"] // O numero de venda '5' já existe

}

}

Page 92: 2011-Introdução ao Framework Grails

92

VendasaPrazoTests.groovy

//Classe de Teste VendasaPrazoControllerTests.groovy

package sisgesso

import grails.test.*

class VendasaPrazoControllerTests extends ControllerUnitTestCase {

protected void setUp() {

super.setUp()

}

protected void tearDown() {

super.tearDown()

}

void testIndex() {

controller.index()

assertEquals "list",

controller.redirectArgs["action"]

}

}

VendasaPrazoControllerTests.groovy

//Arquivo de configuração DATASOURCE.groovy

dataSource {

pooled = true

driverClassName = "com.mysql.jdbc.Driver"

username = "aba"

password = "desenv"

}

hibernate {

cache.use_second_level_cache=true

cache.use_query_cache=true

cache.provider_class='net.sf.ehcache.hibernate.EhCacheProvider'

}

// environment specific settings

environments {

development {

dataSource {

dbCreate = "update" // one of 'create', 'create-drop','update'

url = "jdbc:mysql://localhost:3306/sisgessodb_dev?"

}

}

test {

dataSource {

dbCreate = "update"

url = "jdbc:mysql://localhost:3306/sisgessodb_test?"

}

}

production {

dataSource {

Page 93: 2011-Introdução ao Framework Grails

93

dbCreate = "update"

url = "jdbc:mysql://localhost:3306/sisgessodb_prod?"

}

}

}

DataSource.groovy

//Arquivo de Configuração UrlMappings.groovy

class UrlMappings {

static mappings = {

"/$controller/$action?/$id?"{

constraints {

// apply constraints here

}

}

"/"(view:"/index")

"500"(view:'/error')

}

}

UrlMappings.groovy

<html>

<head>

<title>Sis. Gesso - Gesso Arte de Araruama</title>

<meta name="layout" content="main" />

<style type="text/css" media="screen">

#nav {

margin-top:20px;

margin-left:30px;

width:228px;

float:left;

}

.homePagePanel * {

margin:0px;

}

.homePagePanel .panelBody ul {

list-style-type:none;

margin-bottom:10px;

}

.homePagePanel .panelBody h1 {

text-transform:uppercase;

font-size:1.1em;

margin-bottom:10px;

}

.homePagePanel .panelBody {

background: url(images/leftnav_midstretch.png) repeat-y top;

margin:0px;

padding:15px;

}

.homePagePanel .panelBtm {

background: url(images/leftnav_btm.png) no-repeat top;

height:20px;

Page 94: 2011-Introdução ao Framework Grails

94

margin:0px;

}

.homePagePanel .panelTop {

background: url(images/leftnav_top.png) no-repeat top;

height:11px;

margin:0px;

}

h2 {

margin-top:15px;

margin-bottom:15px;

font-size:20px;

}

#pageBody {

margin-left:280px;

margin-right:20px;

}

</style>

</head>

<body>

<table>

<td>

<div id="nav">

<div class="homePagePanel">

<div class="panelTop">

</div>

<div class="panelBody">

<h2 align="center"><a class="cliente" href="${createLink(uri: '/cliente')}">Cliente</a></h2>

</div>

<div class="panelBtm">

</div>

</div>

</div>

<div id="nav">

<div class="homePagePanel">

<div class="panelTop">

</div>

<div class="panelBody">

<h2 align="center"><a class="promissoria" href="${createLink(uri: '/vendasaPrazo')}">

Venda a Prazo</a>

</h2>

</div>

<div class="panelBtm">

</div>

</div>

</div>

<div id="nav">

Page 95: 2011-Introdução ao Framework Grails

95

<div class="homePagePanel">

<div class="panelTop">

</div>

<div class="panelBody">

<h2 align="center"><a class="usuario" href="${createLink(uri: '/usuario')}">Usuário</a></h2>

</div>

<div class="panelBtm">

</div>

</div>

</div>

</td>

</table>

</body>

</html>

Índex.gsp (Página Principal)

<%@ page import="sisgesso.Cliente" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'cliente.label', default: 'Cliente')}" />

<title><g:message code="default.create.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label"

args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.create.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:hasErrors bean="${clienteInstance}">

<div class="errors">

<g:renderErrors bean="${clienteInstance}" as="list" />

</div>

</g:hasErrors>

<g:form action="save" method="post" >

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="nome"><g:message code="cliente.nome.label" default="Nome" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'nome', 'errors')}">

<g:textField name="nome" maxlength="130" value="${clienteInstance?.nome}" />

</td>

Page 96: 2011-Introdução ao Framework Grails

96

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="cpf"><g:message code="cliente.cpf.label" default="CPF" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'cpf', 'errors')}">

<g:textField name="cpf" maxlength="18" value="${clienteInstance?.cpf}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="rua"><g:message code="cliente.rua.label" default="Rua" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'rua', 'errors')}">

<g:textField name="rua" value="${clienteInstance?.rua}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="numero"><g:message code="cliente.numero.label" default="Número"/>

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'numero',

'errors')}">

<g:textField name="numero" value="${fieldValue(bean: clienteInstance, field:

'numero')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="bairro"><g:message code="cliente.bairro.label" default="Bairro" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'bairro', 'errors')}">

<g:textField name="bairro" value="${clienteInstance?.bairro}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="complemento"><g:message code="cliente.complemento.label"

default="Complemento" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'complemento',

'errors')}">

<g:textField name="complemento" value="${clienteInstance?.complemento}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="cidade"><g:message code="cliente.cidade.label" default="Cidade" /></label>

</td>

Page 97: 2011-Introdução ao Framework Grails

97

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'cidade', 'errors')}">

<g:textField name="cidade" value="${clienteInstance?.cidade}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="uf"><g:message code="cliente.uf.label" default="UF" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'uf', 'errors')}">

<g:select name="uf" from="${clienteInstance.constraints.uf.inList}"

value="${clienteInstance?.uf}" valueMessagePrefix="cliente.uf" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="cep"><g:message code="cliente.cep.label" default="CEP" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'cep', 'errors')}">

<g:textField name="cep" value="${clienteInstance?.cep}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="tel"><g:message code="cliente.tel.label" default="Telefone" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'tel', 'errors')}">

<g:textField name="tel" value="${clienteInstance?.tel}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="email"><g:message code="cliente.email.label" default="E-mail" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'email', 'errors')}">

<g:textField name="email" value="${clienteInstance?.email}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="telCel"><g:message code="cliente.telCel.label" default="Tel. Celeluar"

/></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'telCel', 'errors')}">

<g:textField name="telCel" value="${clienteInstance?.telCel}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="outrasInf"><g:message code="cliente.outrasInf.label" default="Outras

Informações" /></label>

Page 98: 2011-Introdução ao Framework Grails

98

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'outrasInf',

'errors')}">

<g:textField name="outrasInf" value="${clienteInstance?.outrasInf}" />

</td>

</tr>

</tbody>

</table>

</div>

<div class="buttons">

<span class="button"><g:submitButton name="create" class="save" value="${message(code:

'default.button.create.label', default: 'Create')}" /></span>

</div>

</g:form>

</div>

</body>

</html>

Cliente/create.gsp

<%@ page import="sisgesso.Cliente" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'cliente.label', default: 'Cliente')}" />

<title><g:message code="default.edit.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton">

<a class="home" href="${createLink(uri: '/')}">Principal</a>

</span>

<span class="menuButton">

<g:link class="list" action="list">

<g:message code="default.list.label" args="[entityName]" />

</g:link>

</span>

<span class="menuButton">

<g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" />

</g:link>

</span>

</div>

<div class="body">

<h1><g:message code="default.edit.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:hasErrors bean="${clienteInstance}">

<div class="errors">

<g:renderErrors bean="${clienteInstance}" as="list" />

</div>

Page 99: 2011-Introdução ao Framework Grails

99

</g:hasErrors>

<g:form method="post" >

<g:hiddenField name="id" value="${clienteInstance?.id}" />

<g:hiddenField name="version" value="${clienteInstance?.version}" />

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="nome">

<g:message code="cliente.nome.label" default="Nome" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'nome', 'errors')}">

<g:textField name="nome" maxlength="130" value="${clienteInstance?.nome}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="cpf">

<g:message code="cliente.cpf.label" default="CPF" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'cpf', 'errors')}">

<g:textField name="cpf" maxlength="18" value="${clienteInstance?.cpf}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="rua">

<g:message code="cliente.rua.label" default="Rua" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'rua', 'errors')}">

<g:textField name="rua" value="${clienteInstance?.rua}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="numero">

<g:message code="cliente.numero.label" default="Numero"/>

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'numero', 'errors')}">

<g:textField name="numero" value="${fieldValue(bean: clienteInstance,

field: 'numero')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="bairro">

Page 100: 2011-Introdução ao Framework Grails

100

<g:message code="cliente.bairro.label" default="Bairro" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'bairro', 'errors')}">

<g:textField name="bairro" value="${clienteInstance?.bairro}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="complemento">

<g:message code="cliente.complemento.label" default="Complemento" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance,

field: 'complemento', 'errors')}">

<g:textField name="complemento" value="${clienteInstance?.complemento}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="cidade">

<g:message code="cliente.cidade.label" default="Cidade" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'cidade', 'errors')}">

<g:textField name="cidade" value="${clienteInstance?.cidade}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="uf"><g:message code="cliente.uf.label" default="UF" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'uf', 'errors')}">

<g:select name="uf" from="${clienteInstance.constraints.uf.inList}"

value="${clienteInstance?.uf}" valueMessagePrefix="cliente.uf" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="cep"><g:message code="cliente.cep.label" default="CEP" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'cep', 'errors')}">

<g:textField name="cep" value="${clienteInstance?.cep}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="tel"><g:message code="cliente.tel.label" default="Telefone" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'tel', 'errors')}">

<g:textField name="tel" value="${clienteInstance?.tel}" />

Page 101: 2011-Introdução ao Framework Grails

101

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="email"><g:message code="cliente.email.label" default="E-mail" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'email', 'errors')}">

<g:textField name="email" value="${clienteInstance?.email}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="telCel">

<g:message code="cliente.telCel.label" default="Tel. Celular"/></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'telCel', 'errors')}">

<g:textField name="telCel" value="${clienteInstance?.telCel}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="outrasInf">

<g:message code="cliente.outrasInf.label" default="OutrasInformações" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance,

field: 'outrasInf', 'errors')}">

<g:textField name="outrasInf" value="${clienteInstance?.outrasInf}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="vendasaprazos">

<g:message code="cliente.vendasaprazos.label" default="Vendasaprazos" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: clienteInstance,

field: 'vendasaprazos', 'errors')}">

<ul>

<g:each in="${clienteInstance?.vendasaprazos?}" var="v">

<li>

<g:link controller="vendasaPrazo" action="show"

id="${v.id}">${v?.encodeAsHTML()}</g:link>

</li>

</g:each>

</ul>

<g:link controller="vendasaPrazo" action="create"

params="['cliente.id': clienteInstance?.id]">

${message(code: 'default.add.label', args: [message(code:

'vendasaPrazo.label', default: 'VendasaPrazo')])}</g:link>

</td>

</tr>

Page 102: 2011-Introdução ao Framework Grails

102

</tbody>

</table>

</div>

<div class="buttons">

<span class="button">

<g:actionSubmit class="save" action="update"

value="${message(code: 'default.button.update.label', default: 'Update')}" />

</span>

<span class="button"><g:actionSubmit class="delete" action="delete"

value="${message(code: 'default.button.delete.label', default: 'Delete')}"

onclick="return confirm('${message(code: 'default.button.delete.confirm.message',

default: 'Are you sure?')}');" />

</span>

</div>

</g:form>

</div>

</body>

</html>

Cliente/edit.gsp

<%@ page import="sisgesso.Cliente" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'cliente.label', default: 'Cliente')}" />

<title><g:message code="default.list.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton">

<a class="home" href="${createLink(uri: '/')}">Principal</a>

</span>

<span class="menuButton">

<g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.list.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<div class="list">

<table>

<thead>

<tr>

<g:sortableColumn property="id" title="${message(code: 'cliente.id.label',

default: 'Id')}" />

<g:sortableColumn property="nome" title="${message(code: 'cliente.nome.label',

default: 'Nome')}" />

<g:sortableColumn property="cpf" title="${message(code: 'cliente.cpf.label',

default: 'CPF')}" />

<g:sortableColumn property="rua" title="${message(code: 'cliente.rua.label',

Page 103: 2011-Introdução ao Framework Grails

103

default: 'Rua')}" />

<g:sortableColumn property="numero" title="${message(code: 'cliente.numero.label',

default: 'Numero')}" />

<g:sortableColumn property="bairro" title="${message(code: 'cliente.bairro.label',

default: 'Bairro')}" />

<g:sortableColumn property="complemento"

title="${message(code: 'cliente.complemento.label', default: 'Complemento')}"/>

<g:sortableColumn property="cep" title="${message(code: 'cliente.cpf.label',

default: 'CEP')}"/>

<g:sortableColumn property="cidade" title="${messge(code: 'cliente.cidade.label',

default: 'Cidade')}"/>

<g:sortableColumn property="uf" title="${message(code: 'cliente.uf.label',

default: 'UF')}"/>

<g:sortableColumn property="tel" title="${message(code: 'cliente.tel.label',

default: 'Telefone')}"/>

<g:sortableColumn property="telCel" title="${message(code: 'cliente.telCel.label',

default: 'Celular')}"/>

<g:sortableColumn property="email" title="${message(code: 'cliente.email.label',

default: 'E-mail')}"/>

</tr>

</thead>

<tbody>

<g:each in="${clienteInstanceList}" status="i" var="clienteInstance">

<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">

<td><g:link action="show" id="${clienteInstance.id}">

${fieldValue(bean: clienteInstance, field: "id")}</g:link></td>

<td>${fieldValue(bean: clienteInstance, field: "nome")}</td>

<td>${fieldValue(bean: clienteInstance, field: "cpf")}</td>

<td>${fieldValue(bean: clienteInstance, field: "rua")}</td>

<td>${fieldValue(bean: clienteInstance, field: "numero")}</td>

<td>${fieldValue(bean: clienteInstance, field: "bairro")}</td>

<td>${fieldValue(bean: clienteInstance, field: "complemento")}</td>

<td>${fieldValue(bean: clienteInstance, field: "cep")}</td>

<td>${fieldValue(bean: clienteInstance, field: "cidade")}</td>

<td>${fieldValue(bean: clienteInstance, field: "uf")}</td>

<td>${fieldValue(bean: clienteInstance, field: "tel")}</td>

<td>${fieldValue(bean: clienteInstance, field: "telCel")}</td>

<td>${fieldValue(bean: clienteInstance, field: "email")}</td>

</tr>

</g:each>

Page 104: 2011-Introdução ao Framework Grails

104

</tbody>

</table>

</div>

<div class="paginateButtons">

<g:paginate total="${clienteInstanceTotal}" />

</div>

</div>

</body>

</html>

Cliente/list.gsp

<%@ page import="sisgesso.Cliente" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'cliente.label', default: 'Cliente')}" />

<title><g:message code="default.show.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton">

<a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list">

<g:message code="default.list.label" args="[entityName]" /></g:link></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.show.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.id.label" default="Id" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "id")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.nome.label" default="Nome" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "nome")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.cpf.label" default="Cpf" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "cpf")}</td>

</tr>

Page 105: 2011-Introdução ao Framework Grails

105

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.rua.label" default="Rua" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "rua")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.numero.label" default="Numero" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "numero")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.bairro.label" default="Bairro" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "bairro")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.complemento.label" default="Complemento" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "complemento")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.cidade.label" default="Cidade" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "cidade")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.uf.label" default="Uf" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "uf")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.cep.label" default="Cep" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "cep")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.tel.label" default="Tel" /></td>

<td valign="top" class="value">${fieldValue(bean: clienteInstance, field: "tel")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.email.label" default="Email" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "email")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.telCel.label" default="Tel Cel" /></td>

Page 106: 2011-Introdução ao Framework Grails

106

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "telCel")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.outrasInf.label" default="Outras Inf" /></td>

<td valign="top" class="value">

${fieldValue(bean: clienteInstance, field: "outrasInf")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="cliente.vendasaprazos.label" default="Vendasaprazos" /></td>

<td valign="top" style="text-align: left;" class="value">

<ul>

<g:each in="${clienteInstance.vendasaprazos}" var="v">

<li>

<g:link controller="vendasaPrazo" action="show" d="${v.id}">${v?.encodeAsHTML()}</g:link>

</li>

</g:each>

</ul>

</td>

</tr>

</tbody>

</table>

</div>

<div class="buttons">

<g:form>

<g:hiddenField name="id" value="${clienteInstance?.id}" />

<span class="button">

<g:actionSubmit class="edit" action="edit" value="${message(code: 'default.button.edit.label',

default: 'Edit')}" /></span>

<span class="button">

<g:actionSubmit class="delete" action="delete" value="${message(code:

'default.button.delete.label', default: 'Delete')}" onclick="return

confirm('${message(code: 'default.button.delete.confirm.message',

default: 'Are you sure?')}');" /></span>

</g:form>

</div>

</div>

</body>

</html>

Cliente/show.gsp

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

<meta name="layout" content="main" />

<title>SisGesso</title>

</head>

<body>

<div class="body">

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

Page 107: 2011-Introdução ao Framework Grails

107

<g:each in="${clienteInstanceList}"

status="i" var="clienteInstance">

<div class="cliente">

<h2>${clienteInstance.nome}</h2>

<p class="cliente-details">

<span class="question">Endereço?</span>

<span class="answer">

${clienteInstance.rua}, ${clienteInstance.numero}, ${clienteInstance.bairro},

${clienteInstance.cidade}, ${clienteInstance.uf}, ${clienteInstance.cep}</span>

</p>

<p class="cliente-details">

<span class="question">Documento Indentificador?</span>

<span class="answer">

${clienteInstance.cpf}

</span>

</p>

<p class="cliente-details">

<span class="question">Contatos?</span>

<span class="answer">

${clienteInstance.tel}, ${clienteInstance.telCel}, ${clienteInstance.email}

</span>

</p>

</div>

</g:each>

<div class="paginateButtons">

<g:paginate total="${clienteInstanceTotal}" />

</div>

</div>

</body>

</html>

Cliente/list_resultSearch.gsp

<%@ page import="sisgesso.Usuario" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'usuario.label', default: 'Usuario')}" />

<title><g:message code="default.create.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list">

<g:message code="default.list.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.create.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:hasErrors bean="${usuarioInstance}">

<div class="errors">

<g:renderErrors bean="${usuarioInstance}" as="list" />

Page 108: 2011-Introdução ao Framework Grails

108

</div>

</g:hasErrors>

<g:form action="save" method="post" >

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="nome"><g:message code="usuario.nome.label" default="Nome" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'nome', 'errors')}">

<g:textField name="nome" value="${usuarioInstance?.nome}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="login"><g:message code="usuario.login.label" default="Login" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'login', 'errors')}">

<g:textField name="login" value="${usuarioInstance?.login}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="senha"><g:message code="usuario.senha.label" default="Senha" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'senha', 'errors')}">

<g:passwordField name="senha" value="${usuarioInstance?.senha}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="papel"><g:message code="usuario.papel.label" default="Papel" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'papel', 'errors')}">

<g:select name="papel" from="${usuarioInstance.constraints.papel.inList}"

value="${usuarioInstance?.papel}" valueMessagePrefix="usuario.papel" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="admin"><g:message code="usuario.admin.label" default="Admin" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'admin', 'errors')}">

<g:checkBox name="admin" value="${usuarioInstance?.admin}" />

</td>

</tr>

</tbody>

</table>

</div>

Page 109: 2011-Introdução ao Framework Grails

109

<div class="buttons">

<span class="button"><g:submitButton name="create" class="save"

value="${message(code: 'default.button.create.label', default: 'Create')}" /></span>

</div>

</g:form>

</div>

</body>

</html>

Usuario/create.gsp

<%@ page import="sisgesso.Usuario" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'usuario.label', default: 'Usuario')}" />

<title><g:message code="default.edit.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label"

args="[entityName]" /></g:link></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.edit.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:hasErrors bean="${usuarioInstance}">

<div class="errors">

<g:renderErrors bean="${usuarioInstance}" as="list" />

</div>

</g:hasErrors>

<g:form method="post" >

<g:hiddenField name="id" value="${usuarioInstance?.id}" />

<g:hiddenField name="version" value="${usuarioInstance?.version}" />

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="nome"><g:message code="usuario.nome.label" default="Nome" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'nome', 'errors')}">

<g:textField name="nome" value="${usuarioInstance?.nome}" />

</td>

</tr>

<tr class="prop">

Page 110: 2011-Introdução ao Framework Grails

110

<td valign="top" class="name">

<label for="login"><g:message code="usuario.login.label" default="Login" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'login', 'errors')}">

<g:textField name="login" value="${usuarioInstance?.login}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="senha"><g:message code="usuario.senha.label" default="Senha" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'senha', 'errors')}">

<g:passwordField name="senha" value="${usuarioInstance?.senha}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="papel"><g:message code="usuario.papel.label" default="Papel" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'papel', 'errors')}">

<g:select name="papel" from="${usuarioInstance.constraints.papel.inList}"

value="${usuarioInstance?.papel}" valueMessagePrefix="usuario.papel" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="admin"><g:message code="usuario.admin.label" default="Admin" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: usuarioInstance, field: 'admin', 'errors')}">

<g:checkBox name="admin" value="${usuarioInstance?.admin}" />

</td>

</tr>

</tbody>

</table>

</div>

<div class="buttons">

<span class="button"><g:actionSubmit class="save" action="update"

value="${message(code: 'default.button.update.label', default: 'Update')}" /></span>

<span class="button"><g:actionSubmit class="delete" action="delete"

value="${message(code: 'default.button.delete.label', default: 'Delete')}"

onclick="return confirm('${message(code: 'default.button.delete.confirm.message',

default: 'Are you sure?')}');" /></span>

</div>

</g:form>

</div>

</body>

</html>

Usuario/edit.gsp

<%@ page import="sisgesso.Usuario" %>

<html>

Page 111: 2011-Introdução ao Framework Grails

111

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'usuario.label', default: 'Usuario')}" />

<title><g:message code="default.list.label" args="[entityName]" /></title>

</head>

<body>

<g:if test="${session?.usuario?.admin}">

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

</g:if>

<div class="body">

<h1><g:message code="default.list.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<div class="list">

<table>

<thead>

<tr>

<g:sortableColumn property="id" title="${message(code: 'usuario.id.label', default: 'Id')}" />

<g:sortableColumn property="nome" title="${message(code: 'usuario.nome.label',

default: 'Nome')}" />

<g:sortableColumn property="login" title="${message(code: 'usuario.login.label',

default: 'Login')}" />

<g:sortableColumn property="senha" title="${message(code: 'usuario.senha.label',

default: 'Senha')}" />

<g:sortableColumn property="papel" title="${message(code: 'usuario.papel.label',

default: 'Papel')}" />

<g:sortableColumn property="admin" title="${message(code: 'usuario.admin.label',

default: 'Admin')}" />

</tr>

</thead>

<tbody>

<g:each in="${usuarioInstanceList}" status="i" var="usuarioInstance">

<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">

<td><g:link action="show" id="${usuarioInstance.id}">

${fieldValue(bean: usuarioInstance, field: "id")}</g:link></td>

<td>${fieldValue(bean: usuarioInstance, field: "nome")}</td>

<td>${fieldValue(bean: usuarioInstance, field: "login")}</td>

<td>${fieldValue(bean: usuarioInstance, field: "senha")}</td>

Page 112: 2011-Introdução ao Framework Grails

112

<td>${fieldValue(bean: usuarioInstance, field: "papel")}</td>

<td><g:formatBoolean boolean="${usuarioInstance.admin}" /></td>

</tr>

</g:each>

</tbody>

</table>

</div>

<div class="paginateButtons">

<g:paginate total="${usuarioInstanceTotal}" />

</div>

</div>

</body>

</html>

Usuario/list.gsp

<%@ page import="sisgesso.Usuario" %>

<html>

<head>

<meta http-equiv="Content-Type"

content="text/html; charset=UTF-8"/>

<meta name="layout" content="main" />

<title>Login</title>

</head>

<body>

<div class="body">

<h1>Login</h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:form action="authenticate" method="post" >

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="login">Login:</label>

</td>

<td valign="top">

<input type="text" id="login" name="login"/>

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="senha">Senha:</label>

</td>

<td valign="top">

<input type="password" id="senha" name="senha"/>

</td>

</tr>

</tbody>

</table>

Page 113: 2011-Introdução ao Framework Grails

113

</div>

<div class="buttons">

<span class="button">

<input type="submit" value="Acessar" />

</span>

</div>

</g:form>

</div>

</body>

</html>

Usuário/login.gsp

<%@ page import="sisgesso.Usuario" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'usuario.label', default: 'Usuario')}" />

<title><g:message code="default.show.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list">

<g:message code="default.list.label" args="[entityName]" /></g:link></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.show.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name"><g:message code="usuario.id.label" default="Id" /></td>

<td valign="top" class="value">${fieldValue(bean: usuarioInstance, field: "id")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="usuario.nome.label" default="Nome"/></td>

<td valign="top" class="value">

${fieldValue(bean: usuarioInstance, field: "nome")}</td>

</tr>

<tr class="prop">

Page 114: 2011-Introdução ao Framework Grails

114

<td valign="top" class="name">

<g:message code="usuario.login.label" default="Login" /></td>

<td valign="top" class="value">${fieldValue(bean: usuarioInstance, field: "login")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="usuario.senha.label" default="Senha" /></td>

<td valign="top" class="value">${fieldValue(bean: usuarioInstance, field: "senha")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="usuario.papel.label" default="Papel"/></td>

<td valign="top" class="value">${fieldValue(bean: usuarioInstance, field: "papel")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="usuario.admin.label" default="Admin" /></td>

<td valign="top" class="value">

<g:formatBoolean boolean="${usuarioInstance?.admin}" /></td>

</tr>

</tbody>

</table>

</div>

<div class="buttons">

<g:form>

<g:hiddenField name="id" value="${usuarioInstance?.id}" />

<span class="button"><g:actionSubmit class="edit" action="edit"

value="${message(code: 'default.button.edit.label', default: 'Edit')}" />

</span>

<span class="button"><g:actionSubmit class="delete" action="delete"

value="${message(code: 'default.button.delete.label',

default: 'Delete')}" onclick="return

confirm('${message(code: 'default.button.delete.confirm.message',

default: 'Are you sure?')}');" /></span>

</g:form>

</div>

</div>

</body>

</html>

Usuário/show.gsp

<%@ page import="sisgesso.VendasaPrazo" %>

<html>

Page 115: 2011-Introdução ao Framework Grails

115

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'vendasaPrazo.label', default: 'VendasaPrazo')}" />

<title><g:message code="default.create.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list">

<g:message code="default.list.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.create.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:hasErrors bean="${vendasaPrazoInstance}">

<div class="errors">

<g:renderErrors bean="${vendasaPrazoInstance}" as="list" />

</div>

</g:hasErrors>

<g:form action="save" method="post" >

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="cliente">

<g:message code="vendasaPrazo.cliente.label" default="Cliente"/></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'cliente', 'errors')}">

<g:select name="cliente.id" from="${sisgesso.Cliente.list()}"

optionKey="id" value="${vendasaPrazoInstance?.cliente?.id}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="numVenda"><g:message code="vendasaPrazo.numVenda.label"

default="Número Venda" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'numVenda', 'errors')}">

<g:textField name="numVenda" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'numVenda')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="dataVenda"><g:message code="vendasaPrazo.dataVenda.label"

default="Data de Venda" /></label>

</td>

Page 116: 2011-Introdução ao Framework Grails

116

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'dataVenda', 'errors')}">

<g:datePicker name="dataVenda" format="dd/mm/aaaa" precision="day"

value="${vendasaPrazoInstance?.dataVenda}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="valorTotal">

<g:message code="vendasaPrazo.valorTotal.label" default="Valor Total" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'valorTotal', 'errors')}">

<g:textField name="valorTotal" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'valorTotal')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="valorPago">

<g:message code="vendasaPrazo.valorPago.label" default="Valor Pago" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'valorPago', 'errors')}">

<g:textField name="valorPago" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'valorPago')}" />

</td>

</tr>

<!--tr class="prop">

<td valign="top" class="name">

<label for="valorReceber">

<g:message code="vendasaPrazo.valorReceber.label" default="Valor Receber" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'valorReceber', 'errors')}">

<g:textField name="valorReceber" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'valorReceber')}" />

</td>

</tr-->

<tr class="prop">

<td valign="top" class="name">

<label for="dataPagamento">

<g:message code="vendasaPrazo.dataPagamento.label" default="Data Pagamento" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'dataPagamento', 'errors')}">

<g:datePicker name="dataPagamento" format="dd/mm/aaaa" precision="day"

value="${vendasaPrazoInstance?.dataPagamento}" />

</td>

</tr>

</tbody>

Page 117: 2011-Introdução ao Framework Grails

117

</table>

</div>

<div class="buttons">

<span class="button"><g:submitButton name="create" class="save"

value="${message(code: 'default.button.create.label', default: 'Create')}" /></span>

</div>

</g:form>

</div>

</body>

</html>

Vendasaprazo/create.gsp

<%@ page import="sisgesso.VendasaPrazo" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'vendasaPrazo.label', default: 'VendasaPrazo')}" />

<title><g:message code="default.edit.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label"

args="[entityName]" /></g:link></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.edit.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<g:hasErrors bean="${vendasaPrazoInstance}">

<div class="errors">

<g:renderErrors bean="${vendasaPrazoInstance}" as="list" />

</div>

</g:hasErrors>

<g:form method="post" >

<g:hiddenField name="id" value="${vendasaPrazoInstance?.id}" />

<g:hiddenField name="version" value="${vendasaPrazoInstance?.version}" />

<g:hiddenField name="valorReceber" value="${vendasaPrazoInstance?.valorReceber}" />

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name">

<label for="cliente"><g:message code="vendasaPrazo.cliente.label" default="Cliente" />

</label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

Page 118: 2011-Introdução ao Framework Grails

118

field: 'cliente', 'errors')}">

<g:select name="cliente.id" from="${sisgesso.Cliente.list()}" optionKey="id"

value="${vendasaPrazoInstance?.cliente?.id}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="numVenda"><g:message code="vendasaPrazo.numVenda.label"

default="Número Venda" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'numVenda', 'errors')}">

<g:textField name="numVenda" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'numVenda')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="dataVenda"><g:message code="vendasaPrazo.dataVenda.label"

default="Data de Venda" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'dataVenda', 'errors')}">

<g:datePicker name="dataVenda" format="dd/mm/aaaa" precision="day"

value="${vendasaPrazoInstance?.dataVenda}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="valorTotal"><g:message code="vendasaPrazo.valorTotal.label"

default="Valor Total" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'valorTotal', 'errors')}">

<g:textField name="valorTotal" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'valorTotal')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="valorPago"><g:message code="vendasaPrazo.valorPago.label"

default="Valor Pago" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance, field: 'valorPago',

'errors')}">

<g:textField name="valorPago" value="${fieldValue(bean: vendasaPrazoInstance,

field: 'valorPago')}" />

</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<label for="dataPagamento"><g:message code="vendasaPrazo.dataPagamento.label"

Page 119: 2011-Introdução ao Framework Grails

119

default="Data Pagamento" /></label>

</td>

<td valign="top" class="value ${hasErrors(bean: vendasaPrazoInstance,

field: 'dataPagamento', 'errors')}">

<g:datePicker name="dataPagamento" format="dd/mm/aaaa" precision="day"

value="${vendasaPrazoInstance?.dataPagamento}" />

</td>

</tr>

</tbody>

</table>

</div>

<div class="buttons">

<span class="button"><g:actionSubmit class="save" action="update" value="${message(code:

'default.button.update.label', default: 'Update')}" /></span>

<span class="button"><g:actionSubmit class="delete" action="delete" value="${message(code:

'default.button.delete.label', default: 'Delete')}" onclick="return

confirm('${message(code: 'default.button.delete.confirm.message',

default: 'Are you sure?')}');" /></span>

</div>

</g:form>

</div>

</body>

</html>

Vendasaprazo/edit.gsp

<%@ page import="sisgesso.VendasaPrazo" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'vendasaPrazo.label', default: 'VendasaPrazo')}" />

<title><g:message code="default.list.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.list.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<div class="list">

<table>

<thead>

<tr>

<g:sortableColumn property="id" title="${message(code: 'vendasaPrazo.id.label',

default: 'Id')}" />

<th><g:message code="vendasaPrazo.cliente.label" default="Cliente" /></th>

<g:sortableColumn property="numVenda" title="${message(code:

Page 120: 2011-Introdução ao Framework Grails

120

'vendasaPrazo.numVenda.label', default: 'Número Venda')}" />

<g:sortableColumn property="dataVenda" title="${message(code:

'vendasaPrazo.dataVenda.label', default: 'Data de Venda')}" />

<g:sortableColumn property="valorTotal" title="${message(code:

'vendasaPrazo.valorTotal.label', default: 'Valor Total')}" />

<g:sortableColumn property="valorPago" title="${message(code:

'vendasaPrazo.valorPago.label', default: 'Valor Pago')}" />

</tr>

</thead>

<tbody>

<g:each in="${vendasaPrazoInstanceList}" status="i" var="vendasaPrazoInstance">

<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">

<td><g:link action="show" id="${vendasaPrazoInstance.id}">

${fieldValue(bean: vendasaPrazoInstance, field: "id")}</g:link></td>

<td>${fieldValue(bean: vendasaPrazoInstance, field: "cliente")}</td>

<td>${fieldValue(bean: vendasaPrazoInstance, field: "numVenda")}</td>

<td><g:formatDate date="${vendasaPrazoInstance.dataVenda}" /></td>

<td>${fieldValue(bean: vendasaPrazoInstance, field: "valorTotal")}</td>

<td>${fieldValue(bean: vendasaPrazoInstance, field: "valorPago")}</td>

</tr>

</g:each>

</tbody>

</table>

</div>

<div class="paginateButtons">

<g:paginate total="${vendasaPrazoInstanceTotal}" />

</div>

</div>

</body>

</html>

Vendasaprazo/list.gsp

<%@ page import="sisgesso.VendasaPrazo" %>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta name="layout" content="main" />

<g:set var="entityName" value="${message(code: 'vendasaPrazo.label', default: 'VendasaPrazo')}" />

<title><g:message code="default.show.label" args="[entityName]" /></title>

</head>

<body>

<div class="nav">

<span class="menuButton"><a class="home" href="${createLink(uri: '/')}">Principal</a></span>

Page 121: 2011-Introdução ao Framework Grails

121

<span class="menuButton"><g:link class="list" action="list">

<g:message code="default.list.label" args="[entityName]" /></g:link></span>

<span class="menuButton"><g:link class="create" action="create">

<g:message code="default.new.label" args="[entityName]" /></g:link></span>

</div>

<div class="body">

<h1><g:message code="default.show.label" args="[entityName]" /></h1>

<g:if test="${flash.message}">

<div class="message">${flash.message}</div>

</g:if>

<div class="dialog">

<table>

<tbody>

<tr class="prop">

<td valign="top" class="name"><g:message code="vendasaPrazo.id.label" default="Id" />

< /td>

<td valign="top" class="value">${fieldValue(bean: vendasaPrazoInstance, field: "id")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name"><g:message code="vendasaPrazo.cliente.label"

default="Cliente" /></td>

<td valign="top" class="value">

<g:link controller="cliente" action="show" id="${vendasaPrazoInstance?.cliente?.id}">

${vendasaPrazoInstance?.cliente?.encodeAsHTML()}</g:link></td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="vendasaPrazo.numVenda.label" default="Número Venda" /></td>

<td valign="top" class="value">${fieldValue(bean: vendasaPrazoInstance,

field: "numVenda")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="vendasaPrazo.dataVenda.label" default="Data de Venda" /></td>

<td valign="top" class="value">

<g:formatDate date="${vendasaPrazoInstance?.dataVenda}" /></td>

</tr>

<tr class="prop">

<td valign="top" class="name">

<g:message code="vendasaPrazo.valorTotal.label" default="Valor Total" /></td>

<td valign="top" class="value">

Page 122: 2011-Introdução ao Framework Grails

122

${fieldValue(bean: vendasaPrazoInstance, field: "valorTotal")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name"><g:message code="vendasaPrazo.valorPago.label"

default="Valor Pago" /></td>

<td valign="top" class="value">

${fieldValue(bean: vendasaPrazoInstance, field: "valorPago")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name"><g:message code="vendasaPrazo.valorReceber.label"

default="Valor Receber" /></td>

<td valign="top" class="value">${fieldValue(bean: vendasaPrazoInstance,

field: "valorReceber")}</td>

</tr>

<tr class="prop">

<td valign="top" class="name"><g:message code="vendasaPrazo.dataPagamento.label"

default="Data Pagamento" /></td>

<td valign="top" class="value"><g:formatDate

date="${vendasaPrazoInstance?.dataPagamento}" /></td>

</tr>

</tbody>

</table>

</div>

<div class="buttons">

<g:form>

<g:hiddenField name="id" value="${vendasaPrazoInstance?.id}" />

<span class="button"><g:actionSubmit class="edit" action="edit" value="${message(code:

'default.button.edit.label', default: 'Edit')}" /></span>

<span class="button"><g:actionSubmit class="delete" action="delete" value="${message(code:

'default.button.delete.label', default: 'Delete')}" onclick="return

confirm('${message(code: 'default.button.delete.confirm.message',

default: 'Are you sure?')}');" /></span>

</g:form>

</div>

</div>

</body>

</html>

Vendasaprazo/show.gsp

<html>

<head>

<title><g:layoutTitle default="Grails" /></title>

<link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />

<link rel="shortcut icon" href="${resource(dir:'images',file:'gesso.ico')}" type="image/x-icon" />

<g:layoutHead />

<g:javascript library="application" />

</head>

Page 123: 2011-Introdução ao Framework Grails

123

<body>

<div id="spinner" class="spinner" style="display:none;">

<img src="${resource(dir:'images',file:'spinner.gif')}" alt="Spinner" />

</div>

<div id="Logo" class="logo"><a href="/SisGesso/">

<img src="${resource(dir:'images',file:'sisgesso_logo.png')}" alt="Gesso" border="0" /></a>

</div>

<g:render template="/layouts/cabecalho" />

<g:layoutBody />

<g:render template="/layouts/rodape" />

</body>

</html>

Layout/main.gsp

<g:render template="/layouts/search" />

<div id="header">

<p class="header-sub">Gesso Arte de Araruama - Sis Gesso v. beta 0.1</p>

<div id="loginHeader">

<g:loginControl />

</div>

</div>

Layout/cabecalho.gsp

<div id="rodape">

<hr />

<g:copyright

startYear="2010">Sis. Gesso, Inc. - version beta 0.1</g:copyright>

</div>

Layout/rodape.gsp

<div id="search">

<g:form url='[controller: "cliente", action: "search"]'

id="SearchForm"

name="SearchForm"

method="get">

<g:textField name="q" value="${params.q}" />

<input type="submit" value="Procurar" />

</g:form>

</div>

Layout/search.gsp