Anda di halaman 1dari 123

UNIVERSIDADE VEIGA DE ALMEIDA

BACHARELADO EM SISTEMAS DE INFORMAO

INTRODUO AO FRAMEWORK GRAILS

Adriano Basto Antunes

Cabo Frio 2011

ADRIANO BASTO ANTUNES

INTRODUO AO FRAMEWORK GRAILS

Trabalho desenvolvido durante a disciplina Monografia e apresentada ao Curso de Sistemas de Informao da Universidade Veiga de Almeida, Campus Cabo Frio, como pr-requisito para a obteno do ttulo de Bacharel em Sistemas de Informao.

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

Cabo Frio Junho/2011

Universidade Veiga de Almeida - UVA Faculdade de Informtica Curso de Bacharelado em Sistemas de Informao

Reitor: Prof. Dr. Mrio Veiga de Almeida Jr. Vice-Reitor: Prof. Tarqunio Prisco Lemos da Silva

Coordenador do Curso de Informtica: Prof. Edgar Augusto Gonalves Gurgel do Amaral

Banca Examinadora:

_____________________________ Prof. Jorge Ricardo Vallardan Domingos (Orientador) M.Sc em Matemtica Puc-Rio

_____________________________ Prof. Matheus Bousquet Bandini M.Sc em Sistemas e Computao IME/RJ

_____________________________ Prof. Douglas Ericson Marcelino de Oliveira M.Sc em Sistemas e Computao IME/RJ

Universidade Veiga de Almeida Cabo Frio Estrada das Perynas, s/n CEP: 28901-970 - Cabo Frio RJ

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

AGRADECIMENTOS

A minha me que sempre me apoiou e incentivou fervorosamente meus estudos. Aos meus irmos que viro em mim chance de realizar seus sonhos. Aos meus amigos, colegas e professores com quem dividi experincias e aprendi muito nesta longa caminhada.

LISTA DE FIGURAS
Figura 2.1 A evoluo do ambiente tecnolgico ................................................................... 17 Figura 2.2 O padro MVC ..................................................................................................... 22 Figura 3.1 Cdigo: Comparao Simples de Java e Groovy ................................................. 31 Figura 3.2 Cdigo: Exemplo do uso de Meta-Objeto............................................................ 33 Figura 3.3 Cdigo: Exemplo de GString ............................................................................... 34 Figura 3.4 Cdigo: Os mtodos findAll e each. .................................................................... 35 Figura 3.5 - Cdigo: Exemplos de Closure .............................................................................. 36 Figura 3.6 Entendendo o SiteMesh ....................................................................................... 41 Figura 3.7 rvore de diretrios de uma aplicao Grails ...................................................... 45 Figura 3.8 Cdigo do DataSource.groovy ............................................................................. 48 Figura 3.9 Scaffold ................................................................................................................ 51 Figura 3.10 Exemplo de GSP ................................................................................................ 52 Figura 3.11 Cdigo: Incluindo template parcial .................................................................... 53 Figura 4.1 Diagrama de Classes ............................................................................................ 60 Figura 4.2 Classe de domnio: Cliente.groovy ...................................................................... 61 Figura 4.3 - Classes de domnio: VendasaPrazo.groovy .......................................................... 62 Figura 4.4 Diagrama Hierrquico 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 Usurio............................................................................................. 68 Figura 4.10 Tela Criar Venda a Prazo ................................................................................... 69 Figura 4.11 Tela Mostrar Resultados da busca ..................................................................... 70 Figura 4.12 rvore de diretrios war .................................................................................... 72

LISTA DE TABELAS
Tabela 3.1 Principais diretrios de uma aplicao Grails. .................................................... 46 Tabela 4.1 Product Backlog .................................................................................................. 57 Tabela 4.2 Sprint Backlog ..................................................................................................... 58

LISTA DE ABREVIATURAS E SIGLAS


COC CPD CRUD CSS DI DRY GORM GSP HTML HTTP IDE Convention Over Configuration (Conveno sobre Configurao) Centro de Processamento de Dados Create Read Update Delete (Criar-Ler-Editar-Excluir) Cascading Style Sheets Dependency Injection (Injeo de Dependncias) Dont Repeat Your Self (No se repita) Grails Object Relational Mapping (Mapeamento Objeto-Relacional do Grails) Groovy Server Pages Hyper Text Markup Language (Linguagem de Marcao de Hipertexto) Hyper Text Transfer Protocol (Protocolo de Transferncia de Hipertexto) Integrated Development Environment (Ambiente Integrado de

Desenvolvimento) IoC J2EE JDK JEE JVM KISS MOP MVC OO PC PHP RoR SQL TDD UML URL WAR XML XP Inversion of Controll (Inverso de Controle) Java 2 Platform, Enterprise Edition (Plataforma Java 2, Edio Empresarial) Java Development Kit (Kit de Desenvolvimento Java) Java Enterprise Edition (Java Edio Empresarial) Java Virtual Machine (Mquina Virtual Java) Keep It Simple and Short (Mantenha-o Simples e Curto) Meta-Object Protocol (Protocolo de Meta-Objeto) Model View - Controller (Modelo Viso Controlador) Orientao a Objetos Personal Computer (Computador Pessoal) Hypertext Preprocessor ou Personal Home Page Ruby on Rails Struct Query Language (Linguagem de Consultas Estruturada) Test Driven Development (Desenvolvimento Direcionado a Testes) Unified Modeling Language (Linguagem Unificada de Modelagem) Uniform Resource Location (Localizao de Recurso Uniforme) Web Archive (Arquivo Web) eXtensible Markup Language (Linguagem de Marcao Estendida) eXtreme Programming (Programao Extrema)

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 soluo no modelo de desenvolvimento gil para a plataforma Java na web. Este trabalho apresenta uma introduo a ferramenta, apresentando suas funcionalidades, principais tecnologias e o desenvolvimento prtico de uma aplicao que demonstrar a utilizao desses poderosos recursos.

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.

SUMRIO

INTRODUO .................................................................................................. 13 1.1 1.2 1.3 1.4 1.5 MOTIVAO .................................................................................................. 13 OBJETIVO ...................................................................................................... 13 JUSTIFICATIVA ............................................................................................... 14 METODOLOGIA DE PESQUISA ......................................................................... 14 ORGANIZAO DO TEXTO .............................................................................. 15

O UNIVERSO DE GRAILS .............................................................................. 16 2.1 2.2 2.3 2.4 2.5 HISTRICO DA COMPUTAO ........................................................................ 16 DESENVOLVIMENTO GIL .............................................................................. 18 FRAMEWORKS ............................................................................................... 20 O PADRO MVC............................................................................................ 21 JAVA VS. RUBY ON RAILS ............................................................................. 22

O FRAMEWORK GRAILS .............................................................................. 26 3.1 3.1.1 3.1.2 3.2 3.2.1 3.2.2 3.2.3 3.2.4 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 O QUE GRAILS? .......................................................................................... 26 Origem do Grails ...................................................................................... 27 Groovy + Ruby on Rails = Grails ............................................................ 28 GROOVY: A LINGUAGEM DO GRAILS............................................................. 29 O que Groovy? ...................................................................................... 29 Groovy e Java: Comparao e Integrao .............................................. 30 Por dentro do Groovy .............................................................................. 32 Closures ................................................................................................... 35 GRAILS: ALGUMAS TECNOLOGIAS................................................................. 37 Spring ....................................................................................................... 37 Hibernate .................................................................................................. 38 SiteMesh ................................................................................................... 39 Outras Tecnologias .................................................................................. 42 CONHECENDO O GRAILS................................................................................ 43 Comeando com Grails ............................................................................ 43

3.4.2 3.4.3 3.4.4 3.4.5 3.5 4

Estrutura de Diretrios e o Padro MVC ................................................ 44 Persistncia de Dados no Grails .............................................................. 47 Scaffold: Problema ou Soluo? .............................................................. 49 A camada de Visualizao........................................................................ 51 CASOS DE SUCESSO ....................................................................................... 53

ESTUDO DE CASO ........................................................................................... 55 4.1 4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 DESCRIO DO PROBLEMA ........................................................................... 55 O SISTEMA ..................................................................................................... 55 Desenvolvendo em Scrum ........................................................................ 56 Preparando o ambiente para o sistema................................................... 59 Classes de domnio e Controladores ....................................................... 59 Provendo Segurana do Sistema ............................................................. 62 Desenvolvendo direcionado a Testes ...................................................... 63 Conectando ao Banco de Dados ............................................................. 65 Visualizaes da aplicao ..................................................................... 66 Trabalhando com plugins ........................................................................ 69 Implantando a aplicao ......................................................................... 70

CONSIDERAES FINAIS ............................................................................. 73 5.1 5.2 CONCLUSES ................................................................................................ 73 TRABALHOS FUTUROS ................................................................................... 74

REFERENCIAS BIBLIOGRFICAS......................................................................75 ANEXOS A - CDIGO FONTE................................................................................77

INTRODUO

1.1

MOTIVAO
A rea de tecnologia da informao 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 rpidos resultados que proporcionem rpidas, porm eficientes, decises. A internet cada vez mais ao alcance de todos e o advento de dispositivos mveis 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 difcil negar a importncia 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 solues, com destaque para o desenvolvimento web, criam-se frameworks e linguagens alternativas como ferramentas que possibilitem o aproveitamento do que j fazia sucesso acrescentando caractersticas inovadoras que podem garantir a continuidade desse mesmo sucesso.

1.2

OBJETIVO
Objetiva-se mostrar a importncia do framework Grails e da linguagem de

programao Groovy para desenvolvimento de solues de software no atual mercado tecnolgico, visando demonstrar e comparar as novas ferramentas com as j existentes, e trazer a imensa gama de desenvolvedores da plataforma Java solues que permitam uma maior capacidade competitiva. 13

No estudo da linguagem Groovy pretende-se conhecer suas principais caractersticas e entender de que forma a mesma pode trazer aos atuais profissionais da rea melhorias nos projetos de desenvolvimento de software. Na anlise 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 atravs de um desenvolvimento prtico.

1.3

JUSTIFICATIVA
O avano da Internet trouxe ao mercado de tecnologia da informao uma migrao

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 informao est cada vez mais acessvel e a perca da mesma pode levar muitos negcios falncia. 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 mudanas. Permitir ao desenvolvedor o desenvolvimento gil de aplicaes de forma com que esteja preparado para acompanhar o atual mercado e seu futuro prximo. Justifica-se ainda o intuito de deixar contedo e conhecimento de solues de desenvolvimento gil para web numa transio 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

bibliogrfica e dentro deste contexto tm-se como fontes de pesquisas a consulta a livros, artigos e estudo de caso. Sero utilizados os mtodos lgicos dedutivo, hipottico-dedutivo no contexto da anlise das ferramentas de desenvolvimento de software em estudo e, para demonstrar a 14

evoluo e o atual cenrio tecnolgico do desenvolvimento de software, sero utilizados os mtodos auxiliares histrico, comparativo e estatstico. No tipo de pesquisa utilizada a bibliogrfica 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 aplicao modelo.

1.5

ORGANIZAO DO TEXTO
O texto est organizado em 5 captulos com a inteno de apresentar uma introduo

as principais tecnologias do framework em estudo e um apanhado histrico do universo que o originou, alm de um exemplo prtico atravs de um estudo de caso. O Capitulo 2 traz uma apresentao do universo que envolve o framework Grails, o histrico da computao e das ferramentas de software, a definio de framework, o ambiente de desenvolvimento gil, o padro de projeto utilizado e as inspiraes e influencias de Java e Ruby on Rails. O Capitulo 3 abrange o ponto principal da pesquisa apresentando o framework Grails, seu histrico, caractersticas e suas principais tecnologias e mostra um apanhado bsico da linguagem de programao Groovy que utilizada pelo framework, salientando sua integrao com Java e fazendo comparaes 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 contedo da pesquisa, seguido das consideraes finais no Capitulo 5.

15

O UNIVERSO DE GRAILS

2.1

HISTRICO DA COMPUTAO
A histria da computao como conhecemos hoje teve seu incio h quase meio sculo

atrs quando os primeiros microcomputadores PCs (Personal Computers) foram introduzidos no mercado, mas a idia da construo de uma mquina capaz de executar operaes e clculos bem antiga tendo seu incio nos esforos de Pascal, Leibnitz e Babbage [RODR 02]. A partir da introduo dos computadores pessoais a tecnologia da informao comeou a passar por um processo de transformao cada vez mais acelerado saindo do antigo modelo centralizado pelas Centrais de Processamento de Dados (CPDs) at chegar ao atual ambiente totalmente descentralizado e cada vez mais virtual. Foi com a introduo dos PCs na dcada de 1980 que a revoluo comeou, com a disseminao das redes locais utilizando alta velocidade de comunicao e conexo com outras redes locais e de longa distncia. Com a popularizao dos ambientes de redes dentro das organizaes os CPDs iniciaram o processo de extino e a dcada de 1990 iniciou com um ambiente de processamento de dados mais dinmico e distribudo. Foi tambm na dcada de 1990 que a rede mundial de computadores, criada na dcada de 1960 pelos militares americanos, deixou de ser apenas de uso das universidades e instituies militares e se tornou popular entre os usurios comuns com o uso do correio eletrnico e das home-pages. A disseminao da Internet trouxe uma nova era tecnolgica, o ambiente computacional, que nos seus primrdios se caracterizava pelos CPDs, passou pelo Time Sharing (sistemas computacionais de tempo compartilhado), pelas redes Lans, pela arquitetura Cliente/Servidor e hoje com a difuso da internet vive a denominada Computao em nuvem, onde o processamento de informaes cada vez mais virtual. A figura 2.1 mostra os estgios de evoluo do ambiente tecnolgico. 16

Figura 2.1 A evoluo da Tecnologia da Informao Fonte: [RODR 02] Desde sua criao 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 Programao. A primeira idia de uma linguagem de programao que expressasse instrues para o computador veio de Ada Lovelace para o projeto de computador de Charles Babbage, o projeto no foi concretizado e a idia da linguagem de Ada no chegou a ser testada. Tempos depois vrias outras linguagens de programao foram surgindo, mas sem grandes impactos, at o surgimento da primeira grande linguagem de alto nvel, o Fortran em 1954. Seguiu-se ao Fortran o surgimento do COBOL e LISP, tambm linguagens de alto nvel que so assim conhecidas por apresentarem uma proximidade maior a lngua humana. Foi nas dcadas de 1960 e 1970 que uma grande revoluo iniciou-se em meio as linguagens de programao, surgiam as linguagens Pascal, C e Smalltalk entre tantas outras e 17

tambm na mesma poca surgia um novo paradigma de programao conhecido como Orientao a Objetos. A programao orientada a objetos trouxe grandes mudanas no desenvolvimento de software que antes era dominado pelo paradigma estruturado das linguagens como Pascal e C, onde era priorizada a criao de estruturas simples, usando subrotinas e funes. Na programao orientada a objetos as diversas unidades de software so chamadas de objetos, esses objetos agregam o comportamento do que representam, e o fluxo de execuo neste tipo de programa feito atravs de troca de mensagens entre os objetos. A dcada de 1990 foi destaque pelo grande aumento da popularidade da internet e nessa poca comeou a surgir a necessidade de linguagens que criassem aplicaes para o meio virtual fazendo a histria das linguagens de programao subir mais um degrau na escala de evoluo. Foi nessa poca que surgiram as linguagens como Java e PHP seguidas pelas linguagens dinmicas, ou linguagens de script, que viriam a dominar o mercado nos anos 2000, como Ruby, Python e Groovy. As linguagens dinmicas so linguagens de alto nvel, com tipagem dinmica, ou seja, cujo tipo da varivel definido em tempo de execuo. Essas linguagens, como todos os outros tipos de linguagens de programao, apresentam suas vantagens e desvantagens dependendo da situao em que so empregadas. O destaque desse tipo de linguagem se d a necessidade do mercado que atualmente exige resultados cada vez mais rpidos sem perder eficincia. O histrico das linguagens de programao mostra que no decorrer dos anos a tecnologia se adapta as necessidades surgidas sem necessariamente definir uma regra, mas no se deve negar a importncia do desenvolvedor conhecer mais do que uma linguagem de programao. O seu conhecimento das linguagens de programao a chave para o seu portflio pessoal como um desenvolvedor de software. [KNI 07]

2.2

DESENVOLVIMENTO GIL
Desde a dcada de 1970 o desenvolvimento de softwares vivia uma crise no que dizia

a respeito a gesto de seus projetos. Ferramentas tradicionais de gerncia de projetos no 18

conseguiam suprir as necessidades que os projetos de software apresentavam como prazo, oramento e as constantes mudanas de escopo no decorrer do desenvolvimento. Motivados pela busca de uma soluo para esses problemas, um grupo de pensadores da rea de engenharia de software se juntou no final dos anos 90 e incio 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 publicaes da rea. O manifesto consistia, basicamente, de quatro grandes premissas: 1. 2. 3. 4. Indivduos e Interaes mais que processos e ferramentas. Software funcionando mais que documentao abrangente. Colaborao com cliente mais que negociao de contratos Resposta a mudana mais que seguir um plano.

A essas premissas segue-se um conjunto de 12 princpios que aqueles que desejam empregar o desenvolvimento gil devem seguir. Com o surgimento do manifesto gil o mercado de desenvolvimento de software comeou a ganhar novo impulso e, movido pelo crescimento cada vez maior do nmero de usurios da internet, ferramentas que se adequavam mais a esse novo ambiente de desenvolvimento foram surgindo. A maioria das linguagens de programao 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 criao de software ganharam novos olhares e a funo do programador passou a ser vista como um trabalho criativo e no 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 no necessitou mais ser totalmente fechado. 19

Hoje se observa, no entanto, que muitas organizaes que dizem trabalhar com Desenvolvimento gil esto na verdade empregando de maneira errada o que prega o manifesto. ... usar as ferramentas apenas como ferramentas, no funciona se os valores no foram entendidos [MORE 09]. O desenvolvimento gil no significa garantia de sucesso, mas representa um avano na gesto de projetos de software como nunca visto antes.

2.3

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

imensido deles para as mais diversas plataformas, mas muita confuso ainda existe sobre o que realmente so. Entende-se por framework de software o conjunto de classes implementadas em uma linguagem de programao especifica provendo uma funcionalidade genrica que auxilia no desenvolvimento de software [DEPA 10]. Existe a confuso por parte de alguns entre framework e bibliotecas de classes. Nos frameworks, ao contrrio das bibliotecas de classes, as classes so dependentes e possui um modelo de colaborao entre si que livra o projetista da preocupao de saber quando chamar cada mtodo, por exemplo. Nas bibliotecas de classes cada classe nica e no possvel o conhecimento do domnio, sendo este feito apenas pelas prprias aplicaes que criam as colaboraes 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 lgica de negcios e no dos detalhes tcnicos. Alm disso, os frameworks caracterizam-se por serem partes mais concisas de software o que possibilita uma maior facilidade na deteco de erros. Acima de tudo o uso de framework poupa muito o trabalho do desenvolvedor eliminando a perca de tempo com coisas que no o interessam, mesmo sendo importantes. Muito da configurao do projeto de software resolvido quase que automaticamente pela maioria dos frameworks atuais, trazendo aos projetos maior agilidade, maior lucro, antecipao de entrega e satisfao dos clientes. Atualmente nota-se que muitos frameworks

20

destacaram-se de tal forma que j chegam ao patamar de plataforma de programao devido ao grande nmero de funcionalidades e facilidades que eles proporcionam.

2.4

O PADRO 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 padres. Um desses padres, conhecido por MVC (Model-View-Controller) tem destaque principalmente no desenvolvimento para Web. O padro MVC consiste em dividir a estrutura da aplicao em 3 (trs) camadas: Modelo, Visualizao e Controlador. Essa diviso visa separar a lgica de negcio da camada de apresentao e do fluxo da aplicao e dessa forma garantir maior independncia do cdigo. Cada uma dessas camadas possui funes, 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 aplicao a responsvel por guardar as informaes dos dados, os atributos e mtodos de uma classe e seus respectivos tipos. A camada de Controle responsvel pelo fluxo da aplicao, a interao entre usurio e sistema controlando todas as operaes da aplicao. A terceira camada a de Visualizao, responsvel pela interface da aplicao. Tambm conhecida como camada de apresentao a visualizao determina como os dados do modelo so mostrados ao usurio. A interao entre as trs camadas do padro MVC pode ser melhor entendida pela anlise da Figura 2.2.

21

Figura 2.2 O padro 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 Visualizao se baseiam para criar suas funcionalidades. O Controlador da aplicao, responsvel pelas principais funcionalidades da aplicao a camada que controla a interao entre as demais. O padro MVC tem sido exigncia em muitas plataformas de desenvolvimento sendo, em algumas, imprescindvel o seu conhecimento. Muitos frameworks tem sua estrutura construda no formato do padro separando em trs camadas distintas as classes e demais arquivos pertinentes a Modelo, Visualizao 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 tendncia no mercado tecnolgico futuro. A idia era preparar a convergncia dos computadores com os eletrodomsticos utilizados no dia-a-dia com a criao de um dispositivo que funcionasse como um controle remoto desses equipamentos. Mais tarde observou-se que tal projeto era muito avanado 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 programao orientada a objetos que pudesse ser executada no aparelho, essa linguagem era independente 22

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 programao com tal nome. Em meados da dcada 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 verso do Oak, rebatizada de Java e trazia para o WWW (Word Wide Web) uma interatividade nunca antes vista, permitindo execuo de contedo multimdia 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 mquina virtual, a JVM (Java Virtual Machine). Com a JVM, os programas escritos em Java podiam funcionar em qualquer plataforma de hardware ou software que possua uma verso da mesma instalada tornando as aplicaes independentes da plataforma onde funcionam. O sucesso do Java foi absoluto e rapidamente cresceu o nmero de usurios 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 padres de desenvolvimento que oferecem recursos (bibliotecas) e funcionalidades para programar software distribudo. O surgimento do J2EE representou uma grande evoluo para o Java trazendo grande produtividade a linguagem. A introduo do desenvolvimento em camadas, que trouxe maior segurana e organizao ao cdigo. O sucesso da linguagem fez crescer o nmero de desenvolvedores Java que no incio dos anos 2000 j dominava o mercado de software. Todavia existiam na plataforma algumas desvantagens que comeavam a por em risco tal sucesso. Essas desvantagens destacavam-se principalmente por: Alto nvel de complexidade; Grande consumo de tempo; 23

Tarefas repetitivas; E a falta de uma diretiva ntida a respeito de quais convenes seguir.

Para ajudar a resolver esses problemas vrios frameworks eram criados, sendo o Struts a melhor referncia de sucesso e responsvel por influenciar muitos dos frameworks que surgiram aps seu lanamento. O objetivo bsico desses frameworks era facilitar o desenvolvimento de aplicaes web na plataforma Java, diminuindo sua complexidade e aumentando significativamente sua produtividade, mas alguns problemas ainda se repetiam. At que o incio 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 Japo, Yukihiro Matsumoto criara uma linguagem que combinava programao funcional com programao imperativa, cujo objetivo era ser mais poderosa que o Perl e mais orientada a objetos que o Python. Apresentada ao pblico em 1995, o Ruby era uma linguagem dinmica, totalmente orientada a objetos e com grande expressividade e foi justamente sua expressividade que mais tarde levou o dinamarqus 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 comeou a se popularizar entre os desenvolvedores, disputando com PHP, Python e Java o mercado de desenvolvimento para web [BARR 09]. Adotando princpios geis como Dont Repeat Yourself (DRY) e Convention over Configuration (CoC) que tratam, respectivamente, sobre reaproveitamento de cdigo e foco na conveno com o mnimo de configurao e, utilizando a estrutura em camadas do padro MVC, o RoR representou uma ameaa maior ao Java principalmente pelas seguintes caractersticas: Stack completo: componentes pr-integrados, eliminando a necessidade de integrar cada componente necessrio a uma aplicao;

24

Scaffold: eliminando a repetio de tarefas, criando a base para construo da aplicao; Expansibilidade: permitindo criar plugins, de maneira intuitiva, para recursos que a linguagem no oferece.

O Ruby on Rails trouxe ao mercado de desenvolvimento web a soluo de uma exigncia atual, incentivada principalmente pelo Manifesto gil de Fevereiro de 2001: A necessidade de criar ferramentas que permitissem o desenvolvimento de aplicaes eficientes de maneira gil. Uma aplicao simples em Rails pode ser criada em tempo mnimo e a imensa comunidade de desenvolvedores que a plataforma apresenta possibilita a troca de informaes que torna o RoR cada vez mais poderoso. Dentro deste universo gil os desenvolvedores Java comearam a procurar solues para manter a plataforma dentro do que o mercado exigia e assim continuar usufruindo da enorme quantidade de bibliotecas que o Java apresentava. Surgiu ento o projeto JRuby que seria uma implementao de Ruby dentro da plataforma Java alm do projeto Jython, mesma idia do anterior s que em Python. Os projetos no tiveram grande aceitao devido a grande diferena no cdigo de ambas para o que se estava acostumado no Java. A soluo seguinte veio na forma de um novo framework baseado no RoR e utilizando uma linguagem que no era Java apenas por algumas diferenas, 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.

25

O FRAMEWORK GRAILS

3.1

O QUE GRAILS?
Grails um framework open source para desenvolvimento de aplicaes web na

plataforma Java criado com o intuito de fornecer a mesma um maior nvel de abstrao, com enfoque em seguir convenes no lugar de configurar sempre e numa sintaxe mais expressiva e limpa proporcionada pela linguagem na qual se baseia, a linguagem dinmica Groovy. Grails se baseia em ferramentas como Ruby on Rails, Django e TurboGears assumindo princpios Dry (Dont Repeat Yourself), CoC (Convention over Configuration) e KISS (Keep It Simple and Short) que regem as principais caractersticas das ferramentas geis. Caractersticas essas como: Evitar tarefas repetitivas; Necessidade mnima de configurao atravs do enfoque em seguir uma conveno; Proporcionar cdigo simples, pequeno e limpo; Desenvolvimento em camadas utilizando padres de projeto como o MVC (Model-View-Controller). Grails foi desenvolvido no topo da plataforma Java o que lhe permite uma grande integrao com frameworks, bibliotecas e at uso de cdigo Java. Apresenta um ambiente completo de desenvolvimento sem a necessidade de preocupar-se com a configurao de outras ferramentas como servidores de aplicao, por exemplo. Alm disso, Grails tem a seu lado os poderosos e maduros frameworks Hibernate, para mapeamento objeto-relacional (ORM Object Relational Mapping), e Spring, para inverso de controle (IoC Inversion of Controll), com os quais apresenta um enorme nvel de integrao. A alta produtividade e enorme quantidade de funes e ferramentas que apresenta do ao Grails caractersticas de plataforma em lugar de apenas um framework. Alm da compatibilidade com as duas ferramentas j mencionadas Grails tem ainda em seu quadro outras populares tecnologias de cdigo aberto como: 26

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 soluo gil para plataforma Java na web mais bem sucedida trazendo a imensa gama de desenvolvedores menos preocupao com detalhes desnecessrios 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 solues em ferramentas para o desenvolvimento de aplicaes web na plataforma Java que proporcionasse pouca escrita de cdigo, zero de retrabalho e rpidos resultados levou um grupo de desenvolvedores americanos a, em 2005, iniciar o projeto de criao de um framework baseado em Ruby on Rails e utilizando a linguagem dinmica Groovy. Surgia assim o Grails, cuja verso 1.0 viria a ser disponibilizada em 2006. Graeme Rocher trabalhava com Java no desenvolvimento de sistemas de gesto de aprendizagem quando cansado da enorme quantidade de trabalho que poderia ser evitado lhe fez questionar se no havia solues mais simples e rpidas para faz-los. Mais tarde, quando comeou a trabalhar com TV Digital, Graeme conheceu o Groovy e j era bastante amigvel as poucas regras das linguagens dinmicas 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 ento 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 princpios de RoR e utilizava a linguagem Groovy para assim criar o framework web Grails.

27

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 possua e toda a portabilidade proporcionada pela sua conhecida mquina virtual. Grails surgiu para se unir ao poder do Java, trazendo solues que outras ferramentas no conseguiram ajudando a manter ainda por muito tempo o sucesso que a plataforma j apresentava com uma enorme gama de desenvolvedores e empresas que no parecem dispostos a abandonar seu poderio. Grails foi desenvolvido em cdigo aberto, caracterstica comum das ferramentas geis, e aps a disponibilizao da verso 1.0, a comunidade do framework iniciou atividades e vrios desenvolvedores se juntaram ajudando na melhora do mesmo, criando plugins e adicionando tecnologias que forneciam suporte ao desenvolvimento em Grails. Hoje vrios so os casos de sucesso que utilizaram Grails no desenvolvimento de aplicaes. Na criao 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 responsvel por outras tecnologias do mundo Java. Grails hoje possui uma enorme quantidade de plugins e vrias IDEs que facilitam o desenvolvimento de aplicaes 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 criao do Grails, Graeme e sua equipe batizaram o projeto de Groovy on Rails, devido a forte inspirao nos conceitos e princpios 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 solues rpidas e simples apenas seguindo convenes sem a necessidade de gerao de arquivos XML a todo o momento, alm de apresentar um ambiente completo de desenvolvimento, que fez Graeme se interessar no que o framework tinha a oferecer. Alm disso, RoR apresentava todo o poder e organizao do desenvolvimento em camadas atravs do padro MVC, a capacidade de 28

transformar trabalhos repetitivos da gerao de CRUD em uma nica linha de comando e possibilitar ao desenvolvedor criar suas prprias solues quando o mesmo no as oferecia, atravs da expansibilidade. Ruby on Rails parecia resolver todos os problemas que o desenvolvimento em J2EE apresentava. Mas como fazer uso dessas solues sem abandonar tudo o que Java j proporcionava? Antes do surgimento do Grails outras solues geis para a plataforma Java foram pensadas e algumas com grande sucesso. Uma dessas solues foi implementar Ruby (linguagem dinmica do RoR) em Java criando o JRuby, porm a diferena da sintaxe de Ruby para Java afastou muitos programadores devido a enorme curva de aprendizado apresentada. O JRuby ainda utilizado como soluo para muitos casos mesmo no tendo uma aceitao total no mundo Java. Assim como Ruby, uma soluo em linguagem Python veio atravs de Jython que trazia solues dinmicas 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 criao do Groovy que solues dinmicas comearam a mostrar real sucesso na plataforma Java. A enorme semelhana e integrao de Groovy com Java diminuam quase totalmente a curva de aprendizado para os desenvolvedores da plataforma. Juntar Groovy com Rails foi a idia 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 programao gil e dinmica para a plataforma Java com muitas caractersticas inspiradas em linguagens como Python, Ruby e Smalltalk, disponibilizando-as para os desenvolvedores utilizando uma sintaxe similar a do Java [SMIT 09].

29

Groovy surgiu da idia de um programador Java de trazer para a plataforma uma sintaxe mais expressiva e comportamento dinmico. 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 dinmicas. 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 mrito maior no esse. Ser a linguagem dinmica mais amigvel com a plataforma Java o que d ao Groovy um grande potencial. Groovy to 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 tambm permite que se trabalhe de forma procedural, pode ser compilada para bytecode Java, pode ser integrada a aplicaes Java sem grandes complicaes e faz uso de toda a variedade de classes que a biblioteca Java oferece, alm dos frameworks. Cada tipo de Groovy um subtipo de java.lang.Object e cada objeto uma instncia deu um tipo na forma normal. Por exemplo, um tipo data em Groovy um java.util.Date [SMIT 09]. Falar da integrao de Groovy com Java pouco e pode levar a se entender que a linguagem apenas Java com poucas adies, j que boa parte do que Groovy faz pode ser feito em Java. Porm 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: Comparao e Integrao


Um dos motivos do surgimento da linguagem dinmica Groovy foi o de trazer para plataforma Java maior agilidade com menos escrita de cdigo. A capacidade do Groovy de se integrar com Java, permitindo at misturar cdigo Java na aplicao com um mnimo de esforo, e a curta curva de aprendizado para o desenvolvedor Java faz da linguagem a soluo gil mais prxima do sucesso dentre as opes existentes para plataforma. Uma comparao 30

entre as linguagens ressaltando os benefcios 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 exemplificao da maneira como Groovy se assemelha ao Java fazendo uma pequena anlise de sua sintaxe. A sintaxe de Groovy bastante amigvel ao que est acostumado o desenvolvedor Java, com o ganho de permitir que se escreva menos cdigo, deixando a programao na plataforma mais limpa. O trecho de cdigo a seguir compara a sintaxe do Groovy com a j conhecida do Java mostrando a pouca diferena entre as duas.

Cdigo Java import Java.util.*;

Cdigo Groovy today = new Date()

Date today = new Date(); Figura 3.1 Cdigo: Comparao Simples de Java e Groovy Fonte: [SMIT 09] Como se observa o cdigo de Groovy tem a mesma funo que o correspondente em Java e grande semelhana com o mesmo, porm sem a necessidade do uso de ponto-e-vrgula, sem a importao de nenhum pacote e, com sua tipagem dinmica, sem a necessidade de declarao de variveis. Essa pequena amostra serve apenas de introduo ao poder do cdigo 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 alm e permite que um cdigo completo em Java rode nele sem apresentar erro. Groovy considerado por muitos um subconjunto de Java por apresentar grande integrao com a plataforma, porm acrescenta recursos que a plataforma no possua. Assim como Java, Groovy uma linguagem que compila para forma binria (bytecode) e roda na JVM. Compilar cdigo Groovy para bytecode uma das maneiras mais simples de integrar Groovy com Java. Os arquivos .class gerados do Groovy so disponibilizados para Java que pode fazer uso do mesmo. A Mquina Virtual Java roda Groovy como se estivesse rodando o prprio Java, mesmo que ajam diferenas em cdigo. 31

Estas aplicaes podem se beneficiar da expressividade, brevidade e dos poderosos recursos do Groovy. Em outras situaes, no entanto, Groovy pode no ser a melhor soluo. Isto particularmente verdadeiro para aplicaes que exigem alto desempenho, dada o inevitvel trade-off 1 entre agilidade e velocidade em Groovy. [ABDU 09] O uso do Groovy como soluo colaborativa as aplicaes Java, fornecendo recursos que no esto presentes na mesma, bem vindo, porm tiram todo o poder que a linguagem pode oferecer a aplicao por si s. Groovy no tem somente semelhanas e integraes com Java. H uma gama enorme de funcionalidades que a linguagem oferece como: blocos de cdigos executveis (closure), fcil comunicao com base de dados, eficincia em orientao a objetos, entre outros recursos que sero apresentados a seguir.

3.2.3 Por dentro do Groovy


J foi descrito que Groovy uma linguagem dinmica, ou de script, orientada a objetos e que tambm pode ser compilada para bytecode Java atravs da JVM. A forma como a linguagem faz uso dessa capacidade hbrida e o poder de tal caracterstica est em sua sintaxe. Groovy salva a plataforma Java, mas no exclui as vantagens que a mesma j apresenta, muito pelo contrrio adiciona a ela ainda mais produtividade tornando o cdigo mais legvel, limpo, simples e, claro, gil. Em sua declarao de tipos Groovy permite trabalhar de forma dinmica (script) ou de forma esttica, diferenciando-se de outras linguagens como Ruby e Python que s aceitam a tipagem dinmica, isto diminui as crticas que esse tipo de linguagem costuma receber em relao deteco de erros em tempo de execuo. Groovy possui a vantagem das linguagens dinmicas de utilizar o Protocolo de MetaObjeto (Meta-Object Protocol ou MOP) que cria para cada objeto um meta-objeto que
1

Trade-off ou tradeoff uma expresso que define uma situao em que h conflito de escolha. Ele se caracteriza em uma ao econmica que visa resoluo de problema mas acarreta outro, obrigando uma escolha. Ocorre quando se abre mo de algum bem ou servio distinto para se obter outro bem ou servio distinto. (Fonte: Wikipdia)

32

armazena os mtodos separando-os, de certa forma, dos objetos em si. Isso d ao programador a vantagem de poder alterar o meta-objeto em tempo de execuo, adicionando novas funes ao objeto. A funo de meta-objeto tambm pode ser vista como o Duck Typing que um conceito utilizado pelas linguagens dinmicas que traz grande flexibilidade a aplicao. Tal nome vem da expresso 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 Cdigo: Exemplo do uso de Meta-Objeto

O cdigo acima mostra o exemplo do uso de meta-objeto em Groovy. Em tempo de execuo, o mtodo toString adicionado a classe dando a aplicao um novo comportamento. Em linguagens de tipagem forte, como o Java, por exemplo, isso no ocorreria, pois os mtodos so 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 mtodos e em outro, 15. Muito do que Java apresenta em sua sintaxe deixa o cdigo pesado e trabalhoso, Groovy reduz a necessidade de escrita de cdigo deixando opcional o uso desses recursos. Alm da declarao de tipos facilitada pela tipagem dinmica, quando trabalha-se com scripting, onde o tipo opcional, em Groovy opcional tambm o uso de modificadores de acesso, ponto e vrgula e return. Algumas caractersticas bsicas do Groovy so:

33

Por padro tudo o que no especificado com modificador de acesso visto como pblico; O uso de ponto e vrgula s ser necessrio em caso de mais de um comando em uma mesma linha; A instruo return opcional, pois se adota o retorno do ltimo comando como valor de retorno do mtodo ou funo; 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 no; 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 princpio DRY (Dont Repeat Yourself) implementado pelo modelo de desenvolvimento gil. Ao contrrio do Java, em Groovy no necessrio a declarao dos mtodos gets e sets, isso feito dinamicamente pela linguagem. O Groovy Beans entende que se o escopo de uma varivel indefinido os mtodos bsicos da mesma devem ser criados dinamicamente, tornando a programao mais limpa e com menos escrita de cdigos. String em Groovy outro atrativo da linguagem que torna o cdigo ainda mais legvel. As GString, como so denominadas, tem caractersticas da linguagem PHP e permitem o acoplamento de String misturando o contedo de uma varivel, uma classe Java ou o resultado de uma expresso numa mesma sada 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 Cdigo: Exemplo de GString.

Groovy possui ainda muitas funcionalidades e mtodos que simplificam e muito o trabalho do desenvolvedor. Algumas funes importantes e frequentemente utilizadas, principalmente no framework Grails, so os mtodos each e find. O uso de listas e mapas em Groovy juntamente com esses mtodos um recurso poderoso da linguagem.

34

def lista = [fornecedor, advogado, dentista, mecnico] lista.findAllbyPalavraChave { it == advogado }.each { println it } Figura 3.4 Cdigo: Os mtodos findAll e each.

O cdigo acima exemplifica o uso dos mtodos find e each em uma lista de Strings. O mtodo findAll procura na lista todas as ocorrncias do valor informado em it, que uma varivel usada no Groovy para implicitamente representar a varivel corrente, ou no caso o valor iterado. O mtodo each retorna ento cada (each) ocorrncia e imprime na tela o valor de it. Groovy apresenta ainda muitas outras ferramentas e funes que melhoram a programao na plataforma Java, entre eles os GSP (Groovy Server Pages) que sero discutidos nos tpicos seguintes do Grails, antes, porm preciso falar de outra grande proeza do Groovy, o uso de Closure.

3.2.4 Closures
Closure so blocos de cdigo executveis. Podem ser vistas como variveis diferentes das demais que retornam um conjunto de instrues que executado retornando ou iterando dentro de variveis locais no contexto em que est inserida [ABDU 09]. O uso de closure no novo, mas pouco conhecido. muito utilizado em linguagens funcionais seu uso teve incio na dcada 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 declarao de uma closure feita da mesma maneira com a qual declara-se as variveis comuns, com a diferena de, em lugar de incluir apenas um valor, inclui-se um

35

bloco de cdigo. Devido a essas e outras caractersticas que defini-se as closure como variveis. Em Groovy as closure so uma instancia da classe groovy.lang.Closure e sua referencia, assim como a declarao feita da mesma maneira com que referencia-se qualquer varivel convencional. O uso de closure em Groovy constante e sua execuo dentro de uma aplicao acontece como a execuo de um mtodo onde a nica obrigatoriedade para sua execuo o uso de parnteses. O cdigo a seguir demonstra o uso de closure em Groovy, da declarao execuo dentro de um contexto.

Closure Declarao

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]) } } Referncia/Execuo

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

Figura 3.5 - Cdigo: Exemplos de Closure

No cdigo acima os itens em destaque demonstram a closure save() que recebe um bloco de cdigo e logo abaixo sua execuo feita com o objeto chamando-a como chama-se um mtodo comum.

36

3.3

GRAILS: ALGUMAS TECNOLOGIAS


O poder do desenvolvimento em Grails, alm de possuir ao seu lado total integrao

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 trs do Grails o Spring. Este um poderoso container de injeo de dependncia que sustenta o framework livrando os programadores de uma imensido de trabalho. Porm, mais do que uma ferramenta integrante do Grails, Spring um poderoso recurso hoje utilizado por grandes empresas at mesmo pelas que no adotam cdigo-aberto como exigncia em suas aplicaes. Podemos dizer que boa parte do que o Grails executa est ligado ao Spring e todo o poder de injeo de dependncia que o mesmo oferece. O fato de ser conhecido tambm como um container de inverso de controle est no ncleo do Spring que assim chamado. Todavia o uso do termo pode limitar o framework a apenas essa funo quando na verdade o seu foco principal a injeo de dependncias. Para entender o real funcionamento do Spring preciso compreender os conceitos de Inverso de Controle (Invertion of Control - IoC) e Injeo de dependncias (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 padro de projeto factory. O container do Spring encarrega-se de instanciar as classes e definir as dependncias entre elas, permitindo o baixo acoplamento entre classes, um problema enfrentado muitas vezes pelo uso do factory. O conceito de Inverso de Controle visto por muitos como algo genrico uma vez que consiste de uma caracterstica comum dos frameworks onde, a sequncia de chamada de mtodos tirada das mos dos programadores para uma infra-estrutura de software que toma controle sobre a execuo. basicamente esta caracterstica que tambm diferencia um 37

framework das bibliotecas de classes. J a idia de Injeo de Dependncia, criada por Martin Fowler, leva o IoC um pouco mais alm. Ao invs de apenas tomar controle sobre os mtodos, o container injeta em cada classe, por exemplo, suas dependncias declaradas. Um mdulo montador separado responsvel por injetar a implementao no objeto, assegurando que qualquer usurio siga esta conveno [CARV 08]. Mas as funcionalidades do Spring vo alm, com o objetivo principal de simplificar o desenvolvimento de aplicaes, o framework apresenta um conjunto de mdulos que podem ser utilizados de acordo com a necessidade do projeto. Voltados para persistncia de dados, desenvolvimento web, acesso remoto, entre outros, esses mdulos do ao framework a possibilidade de ser um timo substituto para a plataforma J2EE. O trabalho do Spring no Grails fundamentado principalmente na injeo de dependncias, mas o framework est presente tambm no suporte persistncia de dados, segurana, gerenciamento de transaes do GORM, configurao em tempo de execuo, delegao de controladores, entre outras. Uma aplicao Grails praticamente desenvolvida em cima do Spring que viabiliza toda a gama de convenes que o framework segue e dessa forma faz do Grails a poderosa ferramenta que . Por isso, um conhecimento avanado do Grails exige antes um conhecimento tambm do Spring.

3.3.2 Hibernate
Surgiu com o objetivo de simplificar os processos de persistncia de dados para programao 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 atravs do GORM (Grails Object Relational Mapping), possibilitando ao desenvolvedor a pouca escrita de cdigo de acesso a banco de dados e de comandos SQL, acelerando a velocidade do desenvolvimento de uma forma fantstica. As caractersticas bsicas do Hibernate so:

38

Permitir o desenvolvimento de persistncia de dados orientada a objetos naturalmente, incluindo herana, polimorfismo, e encapsulamento; No necessidade de tabelas especiais ou campos e gerando a maior parte do SQL em tempo de inicializao do sistema, em vez de tempo de execuo; No necessidade de interfaces ou classes base para classes persistentes, permitindo a persistncia de qualquer estrutura de classes ou de dados.

A integrao de Hibernate e Grails bem vinda principalmente porque Grails trabalha com a maior parte da lgica de negcios na prpria aplicao, dependendo pouco de funes especficas 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 incluso de caractersticas prprias do paradigma como herana, polimorfismo e encapsulamento. Os arquivos de configurao do Hibernate so gerados na criao da aplicao em Grails e localizam-se no diretrio 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 tpicos posteriores.

3.3.3 SiteMesh
Para suporte da camada de visualizao do Grails a tecnologia presente o SiteMesh, uma ferramenta para gerao e manipulao de layout de pginas web baseado no padro decorador (decorator). O SiteMesh foi originalmente desenvolvido como ferramenta de

cdigo fechado para a plataforma Java passando a cdigo aberto por volta do ano 2000 sob a licena da OpenSymphony. O SiteMesh funciona atravs de um filtro Servlet
2

que intercepta o HTML a ser

retornado para o navegador, extrai dele o contedo 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 apresentao de um aplicativo Web.

39

diferena bsica do modelo que o SiteMesh adota de outro modelo comumente utilizado por outras ferramentas. O padro do modelo decorador (decorator) cria um layout central com espaos vazios onde apenas os elementos ausentes (no presentes nas visualizaes) so preenchidos deixando os demais espaos para manipulao direta das pginas de visualizao. O outro padro, conhecido por composio (compositive), utilizado por ferramentas como o Tiles da Apache, por exemplo, e tem seu layout central espaos vazios que so preenchidos como um todo por templates gerados pelas visualizaes. Resumindo, pode-se dizer que o padro do SiteMesh faz uma fuso dos componentes do layout com os da visualizao, enquanto que o padro composio faz a incluso dos componentes da visualizao no layout [RUDO 06]. O SiteMesh parte integrante das ferramentas Grails e por padro vem configurada como o provedor de layouts do framework. Os arquivos de layout do SiteMesh so alocados no diretrio grails-app/views/layouts no ato de criao da aplicao grails.

40

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 (trs) tags peculiares: g:layoutTitle, g:layoutHead e g:layoutBody. No ato de criao da visualizao no Grails, caso um dos elementos referentes a title, head ou body no sejam preenchidos e o uso do layout criado pelo SiteMesh estiver inserido no cabealho da visualizao, como mostrado na figura, os valores padres sero mesclados aos contidos na visualizao. 41

O uso do SiteMesh no exclusividade do Grails e nem da plataforma Java, a ferramenta hoje pode ser integrada tambm a PHP, Python, Perl, entre tantas outras ferramentas de desenvolvimento web.

3.3.4 Outras Tecnologias


Grails possui integrao ainda com muitas outras tecnologias de sucesso no mundo de software para web, sendo muitas delas padro do framework e integrantes de seu pacote de instalao. Alm das tecnologias j apresentadas o framework permite integrao com:

Tomcat Um servidor web sob licena livre da Apache Software Fundation que a partir da verso 1.2 do Grails passou a vir por padro junto ao framework. Uma ferramenta elogiada no desenvolvimento web que prov um servidor HTTP puramente em Java. No Grails a grande contribuio do Tomcat est na facilidade de se fazer o deploy da aplicao. Basta configurar o arquivo config.groovy da aplicao, localizado em grails-app/conf, com as informaes pertinentes e executar o comando grails tomcat deploy que o deploy da aplicao ser realizado sem grandes problemas.

Jetty Soluo alternativa ao Tomcat como servidor web, um servidor HTTP totalmente escrito em Java que pode ser integrado ao Grails atravs de plugin. As vantagens do Jetty so a sua fcil configurao e o fato de suportar uma carga maior de usurios simultneos sem depender do auxilio de outras estratgias.

JUnit O framework de testes automatizados do Java que vem por padro entre os componentes do framework Grails e assim como em Java, permite padronizar os testes da aplicao. Grails segue o princpio de TDD (Test Driven Development), que em portugus refere-se a desenvolvimento direcionado a testes, um princpio comum no meio de 42

desenvolvimento gil. atravs do JUnit que o framework realiza os testes unitrios, funcionais e de integrao de toda a aplicao.

HSQLDB o banco de dados padro do Grails. Vem junto ao pacote de instalao do framework e pr-configurado no DataSource.groovy, porm tem a caracterstica de no ser um banco de armazenamento constantes. O HSQLD armazena os dados da aplicao Grails em memria enquanto a mesma est sendo executada e os apaga quando a aplicao finalizada. Possui as caractersticas de ser bastante leve e simples de ser manuseado e por isso bastante recomendado para execuo de testes.

Quartz o agendador de tarefas do Grails. Implementa agendamentos para execuo de cdigos em intervalos de tempo regulares. Uma ferramenta open-source que originalmente integrava o pacote do Grails e hoje pode ser obtida atravs da instalao de plugin.

3.4

CONHECENDO O GRAILS
Adquirir um conhecimento avanado sobre uma ferramenta nova e com tantas

funcionalidades como o Grails exige uma grande dedicao, no apenas no aprofundamento do framework em questo, como tambm das tecnologias que o sustentam, tais como: Spring, Hibernate, Groovy, e at mesmo Java. Mas, para uma introduo do que o framework j oferece, pouco tempo suficiente para conhec-lo.

3.4.1 Comeando com Grails


Trabalhar com o framework Grails, apesar de exigir um conhecimento bsico da sintaxe do Groovy, mostra-se bastante simples, at mesmo nos primeiros momentos, e principalmente aos j habituados com a plataforma Java. Desde a instalao at o desenvolvimento atravs de IDEs no h grandes dificuldades apresentadas. 43

Ao instalar o Grails o desenvolvedor no precisa se preocupar com nada, exceto ao fato de ter instalado um pacote JDK 1.4, ou posterior, em sua mquina e configurar as variveis de ambiente necessrias. No download e instalao do Grails todas as tecnologias integrantes como Spring e Hibernate, e at mesmo Groovy, j esto embutidas no pacote de instalao do framework que aloca tudo em seus devidos lugares para o funcionamento da plataforma de desenvolvimento. Esse procedimento no 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 variveis de ambientes necessrias, o desenvolvedor deve apenas escolher de que forma pretende escrever seus cdigos 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 configurao.

3.4.2 Estrutura de Diretrios e o Padro MVC


Um conhecimento introdutrio do Grails exige antes conhecer a estrutura em camadas que o framework implementa. J no ato de criao de uma aplicao atravs do comando grails create-app, seja via linha de comando ou via IDE, Grails cria no diretrio definido para aplicao uma rvore de diretrios fundamentada no padro em camadas MVC. Como j visto, o padro MVC separa os recursos principais da aplicao em 3 nveis (camadas) Modelo Visualizao Controle, tornando a aplicao organizada, legvel e facilitando a manipulao desses recursos separadamente sem interferir diretamente entre si. A rvore de diretrios gerada pelo grails create-app demonstrada na Figura 3.6, apresenta os diretrios: grais-app/domain, grails-app/view e grails-app/controllers. Esses diretrios so responsveis por armazenar os arquivos referentes s camadas de modelo de dados, visualizao e controle respectivamente.

44

Figura 3.7 rvore de diretrios de uma aplicao Grails

no diretrio grails-app que os recursos mais importantes da aplicao se encontram. Alm dos diretrios j apresentados, outros diretrios e subdiretrios da rvore apresentam funes especficas dentro da aplicao. A Tabela 3.1 explica as funes bsicas de alguns deles.

45

Tabela 3.1 Principais diretrios de uma aplicao Grails. Fonte: [DAVI 10] Diretrio Funo grails-app Responsvel por manter em seus subdiretrios as classes principais da aplicao. grails-app/conf Armazena os arquivos de configurao da aplicao tais como fontes de dados, mapeamento de URL e arquivos de configurao do Spring e Hibernate. grails-app/controllers Armazena as classes de controle da aplicao, o C do padro MVC. grails-app/domain Armazena as classes de modelo (domnio) da aplicao. Cada arquivo deste diretrio tem uma tabela correspondente no banco de dados. grails-app/i18n Armazena os recursos de internacionalizao da aplicao como mensagens de erro, por exemplo. grails-app/services Armazena os servios da aplicao, que seriam classes que prestam suporte a lgica de negcio, encapsulando determinados aspectos das mesmas. Essas classes so gerenciadas pelo Spring. grails-app/taglib Armazena tags customizadas criadas pelo Grails. grails-app/utils Armazena arquivos utilitrios do Grails tais como codecs e classes utilizadas por plugins. grails-app/views Armazena arquivos de visualizao da aplicao, os GSP (Groovy Server Pages). o V do padro MVC. lib Responsvel por armazenar os arquivos de bibliotecas terceirizadas como drivers JDBC, por exemplo. scripts Responsvel por armazenar os scripts criados para facilitar o desenvolvimento da aplicao src Responsvel por armazenar cdigo fonte legado a ser reaproveitado pela aplicao. Possui subdiretrios que separam cdigo Groovy e cdigo Java, alm de templates. Normalmente guarda cdigo fonte que no se encaixa facilmente na estrutura de diretrios do Grails. test Responsvel por armazenar as classes de testes unitrios, funcionais e de integrao da aplicao. web-app Responsvel por armazenar todo contedo esttico da aplicao, tais como: CSS, imagens, cones, arquivos html. Grails implementa o MVC muitas vezes dinamicamente, atravs do comando scaffold que, com base nos valores e atributos das classes de domnio, gera os controladores e respectivas visualizaes das classes presentes no diretrio grails-app/domain. Porm o uso do scaffold pode se apresentar arriscado dependendo do tipo de problema, como veremos mais adiante.

46

3.4.3 Persistncia de Dados no Grails


Banco de dados em Grails um assunto interessante e, assim como todas as suas demais funes, tem um procedimento de configurao mnimo. Alm 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 gerao automtica de comandos SQL para banco de dados externo como o MySql, por exemplo. O desenvolvedor tem contato apenas com um arquivo, alm das classes de domnio que implementa o modelo de dados e suas respectivas validaes. neste arquivo que os dados referentes conexo da aplicao ao banco de dados ficam armazenados, nele que ocorre o gerenciamento de todo o trabalho de configurao executados por ferramentas como Hibernate atravs do recurso conhecido como GORM no Grails. A figura 3.8, apresenta o cdigo do arquivo DataSource.groovy, localizado no diretrio grails-app/conf e responsvel por guardar as informaes referentes aos bancos de dados da aplicao. Conforme se observa na figura, comum o DataSource apresentar 3 sesses de blocos de cdigos que possuem cada um uma funo especfica dentro deste arquivo, so eles: Datasource: guarda as configuraes da base de dados comum aos 3 ambientes de execuo que o Grails implementa (desenvolvimento, testes e produo), tais como driver do banco a ser utilizado, dados para acesso ao banco (username e senha), entre outras; Hibernate: guarda informaes especificas do hibernate que normalmente ficariam em um arquivo prprio do mesmo, como uso ou no de cach (true ou false), exposio ou no de comandos SQL;

47

Figura 3.8 Cdigo do DataSource.groovy

Environments: composta basicamente de trs ambientes de execuo guardando as informaes especificas de acesso a banco de dados para cada um deles. Cada ambiente possui uma extenso da sesso dataSource com as configuraes especificas de: endereo do banco usado e forma de manipulao do mesmo pela propriedade dbcreate.

Ambiente de execuo um conceito que o Grails implementa para tornar a aplicao mais eficiente, a idia dividir a aplicao em ambientes voltados a cada tipo de execuo, seja ela para testes, desenvolvimento ou produo. 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 produo, principal ambiente da aplicao. Se um mesmo banco de dados for utilizado pelos trs ambientes, ou seja, se ambos compartilharem as mesmas informaes, a soluo melhor configurar tais informaes na sesso datasource, que abrange os 3 ambientes da sesso environment.

48

Uma propriedade que merece destaque na sesso environment do exemplo o recurso dbcreate. no dbcreate que o desenvolvedor define se a aplicao deve ou no criar automaticamente as tabelas nos bancos correspondentes. Essa propriedade aceita quatro valores e cada qual realiza uma funo especifica na execuo da aplicao, so 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 aplicao finalizada; Update: atualiza as tabelas existentes e cria novas quando essas no existem no banco; Validate: verifica se as classes de domnio e as tabelas nos bancos de dados esto 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 no se recomenda ao ambiente de produo. Na persistncia de dados o trabalho do Hibernate realmente comea. O GORM (Grails Object Relational Mapping), j no ato de criao das classes de domnio, inicia o mapeamento das informaes de cada classe, desde atributos a validaes (constraints). atravs do GORM que o Hibernate cria, na execuo de mtodos 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 domnio. O trabalho do GORM com Hibernate na persistncia de dados envolve ainda os relacionamentos entre classes e suas correspondentes tabelas, a herana das classes entre tantos outros recursos.

3.4.4 Scaffold: Problema ou Soluo?


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 49

camada de controle e de visualizao da aplicao. Grails tambm possui essa funo entre suas principais funcionalidades e dessa forma permite a criao da base de uma aplicao 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 soluo [ABDU 09]. O uso do scaffold por vezes esconde do desenvolvedor os recursos referentes aos controladores e as visualizaes da aplicao, isso pode ser um problema quando h a necessidade de se criar cdigos especficos, como no caso de criar uma closure para autenticao, por exemplo. A utilizao do scaffold no Grails opcional, o framework possui outras funcionalidades e comandos que geram todo o cdigo bsico de controladores e suas respectivas visualizaes. Atravs do comando grails generate-all, por exemplo, gerado para cada classe de domnio o seu correspondente na camada de controle e na camada de visualizao, alm das classes de testes, porm, ao contrrio do scaffold, este comando no esconde os arquivos e cdigos gerados, apenas facilita sua criao. A utilizao do scaffold simples e basicamente o que tal funo faz dentro do controlador gerar o CRUD (Create Read Update Delete) da aplicao. O CRUD de uma aplicao Grails composto das propriedades bsicas da aplicao, propriedades essas chamadas em Grails por action (ao). Cada action implementa uma closure com cdigos pra realizar uma funo especfica de acordo com o que o usurio solicita e, em certos casos, cada action gera um arquivo .gsp que representa uma visualizao daquela ao na camada de apresentao.

50

Figura 3.9 Scaffold

A figura acima mostra o cdigo que implementa a funcionalidade scaffold no Grails, o nico contedo do controlador que usa scaffold o demonstrado, escondendo do desenvolvedor as action que so geradas dinamicamente em tempo de execuo.

3.4.5 A camada de Visualizao


A segunda camada do modelo MVC a responsvel por tratar as visualizaes, ou seja, tudo o que envolve a aparncia da aplicao e a interface de usurio. Grails apresenta em suas tecnologias poderosos recursos que facilitam a gerao de layout e templates, alm da gerao das paginas de visualizao. Como foi dito anteriormente, comum algumas action dos controladores gerarem uma visualizao, isso acontece dinamicamente quando a funo scaffold usada, nesse caso, para cada classe de domnio/controle criado um subdiretrio em grails-app/views onde os arquivos de visualizao so armazenados. Em Grails os arquivos de visualizao tem a extenso .gsp de Groovy Server Pages. Os GSP contm todo o cdigo que implementam as interfaces da aplicao e s diferenciam dos arquivos html pela presena de tags especificas iniciadas por <g:> que fazem valer os recursos exclusivos do Grails. A Figura 3.10 destaca a presena das tags do grails, alm das tags html convencionais, como por exemplo a tag <g:each></g:each> que, atravs da funo each do Groovy, percorre uma determinada lista retornando um valor a cada iterao.

51

Figura 3.10 Exemplo de GSP

A manipulao de layout no Grails facilitada por tecnologias como o SiteMesh, por exemplo. O framework possibilita ainda a customizao de templates de maneira rpida e intuitiva e que torna-se ainda mais poderosa se usada em conjunto com a funcionalidade scaffold. Grails possibilita a criao de templates parciais em que o desenvolvedor pode definir em um arquivo .gsp a aparncia e contedo que tero suas visualizaes. Para isso basta inserir ao incio do nome do arquivo gsp o smbolo underline (_) e incluir o mesmo no diretrio grails-app/views/layouts. Aps isso preciso configurar o layout do main.gsp do SiteMesh, conforme o exemplo do cdigo abaixo.

52

<body><!-- snip --> <g:render template="/layouts/meutemplateparcial" /> <g:layoutBody /> </body> Figura 3.11 Cdigo: Incluindo template parcial

O cdigo mostra que o grails ir renderizar o template atravs da tag <g:render> e exibir seu contedo nas visualizaes que forem criadas. possvel ainda customizar a forma como o Grails gera as visualizaes quando utilizada a funo scaffold bastando configurar os arquivos de templates que tornam-se visveis ao desenvolvedor ao chamar o comando grails install templates. A camada de visualizao do Grails ainda responsvel pela manipulao dos arquivos CSS e possibilita a customizao de bibliotecas de marcas (TagLibs).

3.5

CASOS DE SUCESSO
Grails tem colhido frutos dentro da comunidade de desenvolvimento gil para web e

muitos so os casos de sucesso de aplicaes desenvolvidas com o framework. A prpria histria do Grails demonstra isso pelo fato de hoje ter o ncleo de gerenciamento de suas operaes de suporte e desenvolvimento de solues junto de uma das tecnologias mais elogiadas do mundo Java, o Spring Framework. Parte integrante da SpringSource desde 2008, o ncleo 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 verso 1.4 e o Groovy na verso 1.8. Elogiado pela maneira como gerencia memria de suas aplicaes, o Grails segue desmentindo casos que sugerem o no suporte a mltiplos usurios. Segue abaixo alguns casos de sucesso com grails no Brasil e no mundo:

53

Mins.ms: encurtador URL utilizando Grails no App Engine; NoiteUniversitria.com.br: site de entretenimento brasileiro feito inicialmente em Grails 0.4; AndroidGateway.com: Android; ExperienceOz.com: site ecommerce para passeios tursticos na Austrlia; ImoveisnoMorumbi.com.br: site da agncia imobiliria brasileira focada em clientes de alto nvel. Possui mais de 100 mil requerimentos por dia e funciona com dois servidores Tomcat. voltado para desenvolvedores de aplicativos do

54

ESTUDO DE CASO

Este estudo de caso tem por objetivo apresentar uma introduo prtica do uso do framework Grails como ferramenta de desenvolvimento para aplicaes Web. Para exemplificar o funcionamento do framework uma aplicao simples foi elaborada explorando um problema real e que demonstra parte das principais tecnologias que compem 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

DESCRIO DO PROBLEMA
Para conquistar a confiana e manter o bom relacionamento com seus clientes, uma

das preocupaes 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 fiis uma modalidade de venda exclusiva, as vendas a prazo. A Gesso Arte de Araruama uma empresa do ramo de construo civil que oferece solues em servios e venda de produtos de gesso e derivados. A empresa mantm o gerenciamento de suas informaes em planilhas e fichas de papel, porm, o problema de se controlar tais informaes fez surgir a necessidade de implantar um sistema informatizado que, de maneira rpida, resolvesse ao menos parte dos seus problemas.

4.2

O SISTEMA
O sistema proposto para resoluo do problema apresentado visa gerenciar as

informaes da Gesso Arte atravs de uma aplicao web, dividida em mdulos que corresponda a cada departamento ou operao que a empresa realiza. Por possuir sede e uma filial em endereos distintos e pelas vantagens que o modelo web e a plataforma JVM proporcionam que foi sugerido o desenvolvimento desta aplicao 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 documentao ao extremo. Os mdulos nos quais o sistema 55

se divide, sero representados no Scrum como sprints, e para demonstrao 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 rpida e sem grandes complicaes. Dentre estas ferramentas o Scrum uma das mais conhecidas e utilizadas que trabalha basicamente com 3 premissas: a definio de papis (ScrumMaster, dono do produto, equipe), reunies peridicas (planejamento, reviso, retrospectiva, reunio diria) e criao de artefatos (product backlog, sprint backlog, burndown charts). Um desenvolvimento baseado em Scrum no necessariamente precisa seguir rigidamente essas regras. Pode-se adotar a incluso de diagramas do modelo UML ou a excluso de alguns artefatos do Scrum de acordo com cada projeto e com o que for melhor para a equipe desenvolvedora. No caso especfico deste estudo de caso o uso de alguns dos artefatos do Scrum priorizado e os papis servem apenas para identificar os envolvidos no processo. No h a necessidade de descrio detalhada das reunies ou criao de muitos diagramas para o sprint. Comeando 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 estrias, ou seja, funcionalidades, que o sistema deve possuir. O dono do produto pontua por importncia (IMP) o que, a seu ver, deve ser executado primeiro. com base nessas informaes que o primeiro sprint do projeto criado. Ao analisar o quadro do Product Backlog a equipe e ScrumMaster tem de pensar em estrias que levem em considerao a pontuao do dono do produto (IMP), o tempo estimado para cada estria (EST) e decidir quais estrias podem entrar no sprint para proporcionar um resultado funcional ao final do mesmo, num perodo de pouco tempo. nesse momento tambm que se define um objetivo para o sprint. Todo sprint deve possuir um objetivo que deve ser descrito durante a reunio de sprint, no caso deste problema o objetivo do primeiro sprint foi o de retornar uma primeira verso funcional do sistema que realize algumas das funcionalidades listadas no product backlog. 56

Tabela 4.1 Product Backlog ID NOME DA ESTRIA IMP 10 EST 1 COMO DEMONSTRAR Usurio faz login, clica em clientes, na pgina clientes seleciona "criar novo", insere os dados e clica em salvar. Usurio faz login, clica em funcionrios, e se for autorizado de acordo com seu papel na aplicao vai a pagina funcionrio seleciona "criar novo", insere os dados e clica em salvar. Possuir dependncia direta do controle de estoque e de caixa. Se a forma de venda for a prazo, clicase em Venda a prazo, clica em "Criar nova", seleciona cliente por cdigo e nome, insere dados da venda e salva. Depende do controle de vendas, servios, compras, despesas Clica em realizar venda na sesso venda, insere os dados da venda e imprime cupom fiscal Digita um dado sobre a venda no campo buscar da sesso vendas a prazo e clica em buscar Digita um dado sobre o cliente no campo buscar da sesso clientes e clica em buscar Clica em cliente e uma lista de clientes cadastrados exibida Clica em vendas a prazo e uma lista de vendas exibida Usurio com permisso "cria novo usurio" fornecendo dados de nome, login e senha. Verificar autenticidade do usurio, se o mesmo se confirmar permite o acesso, caso contrario retorna a tela anterior.

1 CADASTRO DE CLIENTES

CADASTRO DE FUNCIONRIOS

CONTROLE DE VENDAS

10

CONTROLE DE VENDAS A PRAZO

10

9 15

CONTROLE DE CAIXA REALIZAR VENDA CONSULTAR VENDAS A PRAZO CONSULTAR CLIENTES LISTAR CLIENTES LISTAR VENDAS A PRAZO CADASTRO DE USURIOS

8 10

10 10

16

10

17 18 21 22

10 10 10 10

3 1 2 1

23

CONTROLE DE ACESSO

10

ID = Identificador da estria - IMP = Importncia - EST = Estimativa em Dias

57

Da anlise do Product Backlog criou-se o primeiro sprint backlog, que aps aprovao do dono do produto seguiu para o desenvolvimento. A tabela 4.2 demonstra o sprint backlog. Tabela 4.2 Sprint Backlog ID NOME DA ESTRIA IMP EST COMO DEMONSTRAR Usurio loga-se, clica em clientes, na pgina clientes seleciona "criar novo", insere os dados e clica em salvar.

CADASTRO DE CLIENTES

10

CONTROLE DE VENDAS A PRAZO

10

Se a forma de venda for a prazo, clica-se em Venda a prazo, clica em "Criar nova", seleciona cliente por cdigo e nome, insere dados da venda e salva. Digita um dado sobre a venda no campo buscar da sesso vendas a prazo e clica em buscar Digita um dado sobre o cliente no campo buscar da sesso clientes e clica em buscar Clica em cliente e uma lista de clientes cadastrados exibida Clica em vendas a prazo e uma lista de vendas exibida Usurio com permisso "cria novo usurio" fornecendo dados de nome, login e senha Verificar autenticidade do usurio, se o mesmo se confirmar permite o acesso, caso contrario retorna a tela anterior.

CONSULTAR VENDAS A PRAZO CONSULTAR CLIENTES LISTAR CLIENTES LISTAR VENDAS A PRAZO

10

4 5 6

10 10 10

3 1 2

CADASTRO DE USURIOS

10

8 9 10 11

CONTROLE DE ACESSO ... ... ...

10

Levando em conta o sprint gerado, a aplicao pode seguir o desenvolvimento. Com o Grails como framework e as vrias tecnologias que o acompanham, o primeiro mdulo da 58

aplicao teve seu desenvolvimento inciado objetivando a implementao 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 aplicao em Grails algumas tecnologias e ferramentas sero 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 injeo de dependncias Spring.

A verso do Grails utilizada nesta aplicao a 1.2.2, estando o framework hoje em sua verso 1.4. As demais ferramentas, com exceo do MySql, esto integradas na instalao do framework Grails. A verso do MySql usada foi a 5.1. Com a criao da base da aplicao e da estrutura de diretrios, o primeiro passo foi customizar a aplicao para que ela agisse da maneira como se esperava, personalizando o Grails para que fosse possvel a implementao futura de estruturas de autenticao, por exemplo, sem a necessidade de retrabalho. Este procedimento torna-se possvel atravs da instalao de templates que exibem uma lista de arquivos a serem configurados. Nesses arquivos informa-se de que forma agiro os controladores, classes de domnio, visualizaes, testes, entre outros componentes quando usada a funcionalidade scaffold.

4.2.3 Classes de domnio e Controladores


O projeto do primeiro sprint partiu ento para a criao das classes de domnio da camada de modelo da aplicao. Nota-se pela anlise das estrias do sprint a presena de estrias com caractersticas semelhantes a outras do product backlog e que, com o recurso de 59

herana do modelo OO (Orientado a objetos), poupar o trabalho nos sprints posteriores. Uma das estrias dessa questo o Cadastro de Clientes, com a criao da classe Pessoa ser possvel o reaproveitamento dos atributos da mesma atravs da herana dessa classe para a classe de domnio Cliente e posteriormente para as classes Funcionrio e Fornecedor. Como j dito anteriormente, o modelo de desenvolvimento gil e metodologias como Scrum no possuem a necessidade de criao de todos os diagramas implementados pelo modelo UML, no entanto no probem o seu uso. Para um melhor entendimento das classes da aplicao solicitadas pelo dono do produto para esse primeiro sprint, torna-se importante a criao do Diagrama de Classes apresentado na figura 4.1.

Figura 4.1 Diagrama de Classes

Alm das classes de domnio Pessoa.groovy e Cliente.groovy, tornou-se necessria a criao da classe de domnio Usuario.groovy para possibilitar a criao do mecanismo de acesso ao sistema. Para concluir as implementaes da camada de modelo, a classe de domnio VendasaPrazo.groovy foi criada para guardar as informaes referentes a modalidade de venda a prazo da empresa e realizar assim o objetivo do sprint de entregar algo funcional.

60

As figuras a seguir apresentam o cdigo de implementao de algumas dessas classes criadas em Grails, com seus respectivos atributos, validaes e relacionamentos.

Figura 4.2 Classe de domnio: Cliente.groovy

As figuras mostram o cdigo 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 herana, a diferena para a sintaxe Java pouca e por isso a grande aceitao do Grails entre os desenvolvedores da plataforma. As classes de domnio implementam ainda as validaes (constraints) e o relacionamento que as mesmas tero 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.

61

Figura 4.3 - Classes de domnio: VendasaPrazo.groovy

Algumas classes de domnio da aplicao tero seus respectivos controladores gerados atravs do mtodo scaffold do Grails, porm classes especficas com mtodos prprios evitaro este recurso por apresentar a necessidade de incluir informaes alm do que seria gerado. A classe Pessoa, por exemplo, por ser usada para herana de outras classes, no apresentou problemas no uso do scaffold.

4.2.4 Provendo Segurana do Sistema


A criao dos mecanismos de segurana do sistema comea pela classe de domnio Usuario.groovy e seu respectivo controller. Chamam-se mecanismos de segurana nesta aplicao as rotinas de autenticao de usurios e a codificao de senhas, alm da limitao de privilgios de acordo com o papel de cada usurio no sistema. Grails oferece solues prontas para autenticao de usurios, atravs do uso de plugins, mas no caso deste problema a mesma se deu atravs de cdigo programado diretamente nos controladores e classes utilitrias.

62

Para o controle do acesso, a classe de controle Usuario recebeu a implementao das closure login, authenticate e logout, cujos cdigos possibilitam respectivamente o acesso, autenticao e sada de sesso no sistema. A closure login no possui cdigo pois serve apenas para as chamadas visualizao login.gsp que recebe os dados do usurio e realiza a autenticao conforme cdigo da closure authenticate. O cdigo da closure logout realiza o encerramento da sesso do usurio. Ainda no que diz respeito a controle de acesso, a implementao de uma classe filtro para interceptar as tentativas de acesso e direcion-las de acordo com a limitao do papel de cada usurio feita pela classe AdminFilters.groovy. Este filtro verifica se a sesso do usurio encontra-se ativa e se o papel do usurio no sistema permite o acesso a determinada rea direcionando-o ou no a rea seguinte. Para a proteo de senhas de acesso utilizado uma classe utilitria que codifica as senhas geradas atravs do mtodo encodeAsBase64. As senhas ficam assim protegidas sendo gravadas nas bases de dados de modo mais seguro. Grails possibilita esses entre outros recursos para segurana, porm por tratar-se de simples acesso a aplicao reservou-se a implementao de mecanismos mais poderosos de segurana para os sprints posteriores do projeto.

4.2.5 Desenvolvendo direcionado a Testes


Seguindo a tradio do modelo gil de desenvolvimento a execuo de testes automatizados se faz necessria durante todo o processo de desenvolvimento, assim antes de seguir para persistncia de dados, foram criadas classes de testes para garantir a estabilidade da aplicao evitando erros. No ato de criao de classes de domnio, controle e de biblioteca de marcas, Grails automaticamente cria uma classe teste para cada uma. Os testes implementados por essas classes so conhecidos por testes unitrios que testa partes da aplicao 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 unitrio em Grails uma extenso de GrailsUnitTestCase, para classes de domnio; ControllerUnitTestCase, para controladores; e TagLibUnitTestCase, para

63

bibliotecas de marca. A figura 4.4 ilustra a hierarquia das classes de testes do Grails incluindo as classes de teste desta aplicao.

Figura 4.4 Diagrama Hierrquico das Classes de Testes

Os testes necessrios para essa primeira parte da aplicao objetivam-se a testar validao das classes de domnio e o funcionamento de algumas rotinas dos controladores, desta maneira evitando antecipadamente a presena de erros. No decorrer dos testes unitrios, por exemplo, foram notados erros nas classes de domnio e de controle Usurio, o que permitiu a correo dos mesmos antes de prosseguir com o restante do desenvolvimento. Isso mostra importncia do uso de testes durante o desenvolvimento e no somente aps a aplicao pronta, com a realizao dos chamados testes de caixa branca. O desenvolvimento direcionado a testes algo natural nas tecnologias geis e exigncia do modelo gil de desenvolvimento, isso garante maior preciso no cdigo e consequentemente a diminuio do retrabalho. Em Grails, por tratar-se de uma ferramenta em que os objetos e mtodos s so instanciados e chamados em tempo de execuo, para execuo de testes existe o recurso chamado mock que simula uma aplicao em execuo no prprio cdigo, garantindo o sucesso do teste. Para visualizar os resultados dos testes, Grails guarda no diretrio da aplicao um arquivo HTML que mostra se o teste passou ou no, ou se apresentou algum erro que impedia 64

o seu sucesso. A figura 4.5 apresenta a tela do resultado dos testes da aplicao, com os respectivos erros ou falhas.

Figura 4.5 Tela Unit Test Results

Antes da persistncia de dados, porm testes de execuo da aplicao tambm so necessrios e um recurso que auxilia este tipo de teste populando os campos das classes para comprovar o sucesso das rotinas de cdigo o BootStrap do Grails. No BootStrap as classes podem assumir valores criando instncias das mesmas que em tempo de execuo fazem o preenchimento dos campos permitindo-se analisar, por exemplo, o estado das visualizaes como list, show e edit; e os testes de acesso e autenticao de usurio.

4.2.6 Conectando ao Banco de Dados


Para persistncia de dados da aplicao foi escolhido o banco de dados MySql pelas caracterstica de ser de simples configurao e apresentar bastante compatibilidade com o Grails. Usando os recursos da linguagem, a conexo do banco ao sistema no apresentou grandes problemas e o trabalho de criao de estrutura SQL ficou a cargo do GORM do Grails junto ao framework Hibernate, atravs do mtodo dbcreate configurado no DataSource.groovy.

65

Durante o desenvolvimento, porm o uso do BootStrap do Grails juntamente com o banco de dados padro do framework, o HSQLDB, foi de grande ajuda para testes das funes implementadas at que por fim os bancos de dados foram criados no MySql. Utilizando a diviso de ambientes do DataSource, foram criados 3 bancos de dados para: desenvolvimento, testes e produo. O recurso foi utilizado pensando na continuidade do sistema nos sprints posteriores.

4.2.7 Visualizaes da aplicao


Para a camada de visualizao da aplicao no houve exigncia especfica a respeito de design. Para cada classe de domnio foi criado um diretrio que continham as visualizaes bsicas geradas atravs do comando grails generate all. Cada visualizao criada no diretrio est diretamente ligada a determinadas closures da classe de controle, assim as views: list.gsp, create.gsp, show.gsp e edit.gsp, no apresentaram grandes alteraes do que foi gerado pelo Grails, mas a incluso de views extras foi necessria, como o caso do login.gsp. Atravs do SiteMesh, que o Grails apresenta para o suporte a layout, foi possvel personalizar a aplicao criando bibliotecas de marcas e templates parciais que ofereceram recursos para simplificar o acesso as partes do sistema. Atravs do SiteMesh tambm foi feita a incluso do logotipo da empresa no topo da aplicao e a pgina principal gerada pelo Grails foi alterada para apresentar os recursos de forma mais organizada. As figuras a seguir apresentam as principais telas da aplicao:

66

Figura 4.6 Tela Principal

Figura 4.7 Tela de Login

67

Figura 4.8 Tela Listar Clientes

Figura 4.9 Tela Mostra Usurio

68

Figura 4.10 Tela Criar Venda a Prazo

4.2.8 Trabalhando com plugins


Durante o desenvolvimento da aplicao uma mudana no escopo do sprint foi pedida pelo dono do produto. Ao acompanhar o desenvolvimento e observar o modelo de consulta criado atravs de listagem o dono do produto pediu que fosse implementado um mecanismo de busca rpida que retornasse as principais informaes dos clientes cadastrados. O desafio de desenvolver algo para esse pedido foi facilmente solucionado por um dos recursos oferecidos pelo Grails. Atravs da instalao do plugin Searchable, foi possvel criar o mecanismo de busca solicitado. O uso de plugins uma caracterstica que garante a expansibilidade e o aproveitamento de cdigo do Grails, duas das caractersticas bsicas das ferramentas geis. O plugin em questo foi ento inserido ao projeto atravs do comando grails install plugin e devidamente configurado para possibilitar a busca de informaes de clientes. Apesar de estar integrado ao projeto, os plugins instalados atravs deste comando so alocados em um diretrio diferente do diretrio fonte da aplicao. Os cdigos compilados pelo Grails so

69

alocados no diretrio .grails, e neste mesmo diretrio so alocados os arquivos dos plugins instalados sendo os mesmos chamados em tempo de execuo. O trabalho por traz do plugin Searchable est na implementao de um servio que caracteriza-se por possibilitar lgica de negcio e comportamento a mais de uma classe de domnio. O trabalho por traz dessa proeza fica por conta do Spring framework atravs da injeo de dependncia entre essas classes. Na insero de mais essa funcionalidade ao sistema, foi necessria ainda a criao de uma view que apresentasse o resultado das buscas feitas pelo Searchable, bem como da incluso do respectivo formulrio 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 aplicao O ltimo passo para que o resultado do primeiro sprint possa ser apresentado diz respeito a preparar a aplicao para ser implantada. At o momento toda a execuo da aplicao ocorreu no ambiente de desenvolvimento, atravs do comando grails run-app. Para 70

que a aplicao funcione no modo de produo em Grails, necessita ser gerado um arquivo WAR (Web Application Archive) que prepara a aplicao com todos os componentes que a integram deixando a pronta para a realizao de deploy no Tomcat ou outro servidor utilizado. Um detalhe importante da configurao dessa etapa a ateno exigida com as informaes inseridas nos arquivos de configurao da aplicao, localizados no diretrio grails-app/conf. Em DataSource.groovy preciso certificar-se de que as configuraes de conexo e acesso a bases de dados estejam corretamente implementadas. No arquivo Config.groovy feita ento a configurao do Tomcat, ou outro servidor, para que o mesmo realize o deploy da aplicao corretamente. Neste caso, preciso observar na configurao do servidor o tipo de usurio que possui permisso para realizar o deploy e caso o mesmo no exista providenciar sua criao. No Config.groovy informa-se nome de usurio, senha e a url da aplicao, incluindo o endereo da porta do servidor. Com tudo devidamente conferido, o comando grails war cria o arquivo .war com o nome e verso da aplicao contido no arquivo application.properties e que, no caso da aplicao em estudo, gerou o arquivo: SisGesso-0.1.war. Um diretrio de nome /war dentro do diretrio .grails/1.2.2/projects/SisGesso armazena todos os componentes da aplicao desde as classes de domnio e controladores at as imagens e templates da camada de visualizao, conforme demonstra a estrutura da rvore de diretrios da figura 4.12.

71

Figura 4.12 rvore de diretrios war.

Com o arquivo .war gerado preciso apenas instalar o mesmo no servidor de aplicaes escolhido, tendo o Grails compatibilidade com vrios dos servidores da plataforma java. Finalizado o primeiro sprint da aplicao o sistema pode ser entregue ao cliente para uso e retorno de informaes para o prosseguimento nos sprints posteriores. O Grails permite fcil manipulao das estruturas de cdigos permitindo recuperar-se at mesmo depois de um deploy sem sucesso atravs do comando undeploy no servidor de aplicaes escolhido.

72

5 CONSIDERAES FINAIS
5.1 CONCLUSES
O atual do mercado de desenvolvimento de software tem exigido ferramentas que facilitem o trabalho dos desenvolvedores proporcionando o maior aproveitamento do tempo que dispem e voltando o foco para a criatividade no processo de desenvolvimento. Desta busca por solues foi que se expandiu o uso de frameworks na inteno de livrar o desenvolvedor de uma gama de trabalho repetitivo e detalhes tcnicos. Este trabalho fez uma introduo ao framework Grails surgindo como soluo para a plataforma Java nas novas exigncias de mercado. Foram citadas as principais tecnologias e funcionalidades do Grails e de que forma o mesmo est integrado ao Java. Atravs de comparaes 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 inspirao para o surgimento do Grails. Apresentou-se ainda a linguagem de programao Groovy, numa rpida introduo a suas caractersticas e funcionalidades. O trabalho apresentou ainda um estudo de caso que demonstrou todo processo de desenvolvimento de uma aplicao atravs do framework Grails. Procurou-se demonstrar de forma prtica a utilizao da metodologia gil Scrum para exemplificar todo processo de gerenciamento de software do modelo gil de desenvolvimento. Atravs do Scrum foram listadas as funcionalidades de um problema real e criou-se um mdulo de uma aplicao para soluo do mesmo. O uso do framework Grails no desenvolvimento de aplicaes web mostra-se promissor principalmente aos desenvolvedores da plataforma Java, j acostumados as tecnologias que o Grails incorpora. Porm, a curta curva de aprendizado faz do framework uma tima soluo para desenvolvimento de aplicaes simples e de rpido 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 criao de novas solues em softwares sem grandes preocupaes com configuraes o tempo todo como ocorre com muitas plataformas. Seguindo princpios como Convention over Configuration e Dont

73

Repeat Yourself, Grails faz jus ao que prega o Manifesto gil de 2001 para desenvolvimento de solues de software. Espera-se com isso ter conseguido produzir conhecimento introdutrio que motivem aos desenvolvedores na busca constante por atualizaes 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 criao de apenas um

mdulo do mesmo, representado atravs do sprint do Scrum. Para trabalhos futuros pretendese dar continuidade ao desenvolvimento do mesmo implementando outros mdulos 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.

74

REFERNCIAS BIBLIOGRFICAS

[ABDU 09] ABDUL-JAWAD, Bashar. Groovy and Grails Recipes. United States of America: Apress, 2009. [BARR 09] BARRETO, Juliano. Histrias do pai do Ruby on Rails. Disponvel 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: Introduo. Disponvel 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 Computao da UFCG. O que so frameworks? Disponvel em <http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/frame/oque.htm>. Acessado em 31/05/2010 s 15 horas. [KNI 07] KNIG, Dierk. Groovy em Ao (Ed. Traduzida). Rio de Janeiro: Alta Books, 2007. [MACO 10] MACORATTI, Jos Carlos. Padres de Projeto: O modelo MVC Model View Controller. Disponvel em < http://www.macoratti.net/vbn_mvc>. Acessado em 31/05/2010 s 15 horas. [MORE 09] MOREIRA, Daniela. Desenvolvimento gil funciona? Disponvel 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. Gesto do Conhecimento nas Empresas. Rio de Janeiro: E-papers Servios Editoriais, 2002. [SIER 05] SIERRA, Kathe & BATES, Bert. Use a cabea! Java (2 ed). Rio de Janeiro: Alta Books, 2005. 75

[SMIT 09] SMITH, Glen & LEDBROOK, Peter. Grails in Action (1st ed). United States of America: Manning Publications, 2009.

76

ANEXO A CDIGO FONTE


// Classe de Domnio Cliente.groovy package sisgesso class Cliente extends Pessoa{ String email String telCel String outrasInf static hasMany = [vendasaprazos: VendasaPrazo] //o mtodo 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 domnio Pessoa.groovy package sisgesso class Pessoa { String nome //Tambem receber razo social sem diferenciao especifica String cpf //ou cnpj, caso pessoa jurdica, 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 no obrigatrios static constraints = { nome(maxSize:130,blank:false) cpf(maxSize:18) rua()

77

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 alfabtica do nome

Pessoa.groovy
// Classe de domnio 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 domnio VendasaPrazo.groovy package sisgesso class VendasaPrazo { Cliente cliente int numVenda Date dataVenda BigDecimal valorTotal BigDecimal valorPago = 0 BigDecimal valorReceber

78

Date dataPagamento = new Date() String toString (){ "${this.numVenda}" - "${this.valorTotal}" } static belongsTo = [Cliente] //o mtodo 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)) {

79

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]) } }

80

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 = {

81

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]

82

} } 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") } } }

83

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") }

84

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") } } }

85

VendasaPrazoController.groovy
//Classe para codificao 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 administrao de acesso de usurios 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 Usurios 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} "

86

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")

87

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:"fulano@gmail.com", 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:"fulano@gmail.com", telCel:"9999-9999", outrasInf:"isso um teste") assertFalse cliente_Nome.validate() //Campo nome obrigatrio } 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",

88

email:"fulano@gmail.com", telCel:"9999-9999", outrasInf:"isso um teste") assertFalse cliente_validarCpf.validate() //Cpf no 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 invlido o correto //exemplo@exemplo.com } 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 no 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(){

89

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

90

} 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 } }

91

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 configurao 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 {

92

dbCreate = "update" url = "jdbc:mysql://localhost:3306/sisgessodb_prod?" } } }

DataSource.groovy
//Arquivo de Configurao 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;

93

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">

94

<div class="homePagePanel"> <div class="panelTop"> </div> <div class="panelBody"> <h2 align="center"><a class="usuario" href="${createLink(uri: '/usuario')}">Usurio</a></h2> </div> <div class="panelBtm"> </div> </div> </div> </td> </table> </body> </html>

ndex.gsp (Pgina 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>

95

</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="Nmero"/> </label> </td> <td valign="top" class="value ${hasErrors(bean: clienteInstance, field: 'numero', 'errors')}"> <g:textField '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> name="numero" value="${fieldValue(bean: clienteInstance, field:

96

<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 Informaes" /></label>

code="cliente.outrasInf.label"

default="Outras

97

</td> <td valign="top" 'errors')}">

class="value ${hasErrors(bean: clienteInstance, field: 'outrasInf',

<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>

98

</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">

99

<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}" />

100

</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="OutrasInformaes" /></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>

101

</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',

102

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>

103

</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>

104

<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>

105

<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>

106

<g:each in="${clienteInstanceList}" status="i" var="clienteInstance"> <div class="cliente"> <h2>${clienteInstance.nome}</h2> <p class="cliente-details"> <span class="question">Endereo?</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" />

107

</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>

108

<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">

109

<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>

110

<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>

111

<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>

112

</div> <div class="buttons"> <span class="button"> <input type="submit" value="Acessar" /> </span> </div> </g:form> </div> </body> </html>

Usurio/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">

113

<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>

Usurio/show.gsp

<%@ page import="sisgesso.VendasaPrazo" %> <html>

114

<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="Nmero 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>

115

<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>

116

</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,

117

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="Nmero 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"

118

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:

119

'vendasaPrazo.numVenda.label', default: 'Nmero 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>

120

<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="Nmero 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">

121

${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>

122

<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

123

Anda mungkin juga menyukai