Grails, Gravl, SAP e REST intro

Oi pessoal,

hoje eu vou fazer um pequeno post com algumas coisas que achei interessantes recentemente.

Primeiro, nosso amigo Glen Smith, novamente, faz um desafio a si mesmo em benfício da comunidade Grails. Essas comunidades open source são demais mesmo....

O Glen está implementando um pequeno sistema de blog, chamado de Gravl, em no máximo 1000 linhas de código (LOC), para mostrar algumas funcionalidade do Grails e seus plugins. Ele está usando algumas das últimas novidades das recentes versões do Grails, como Web Flow, GORM DSL, URL Mappings, RSS Plugin, Searchable Plugin, Ajax Upload com barra de progresso, entre outras coisas. O código fonte está disponível como um projeto open source do google code, e seu objetivo é ser uma aplicação de exemplo do Grails. Vale conferir. ( veja outros posts dele sobre este tema ).

Segundo, a SAP anunciou que estará usando o Grails 1.0 para o seu produto Composition on Grails, que é uma aplicação que provê facilidade para o rápido desenvolvimento de "aplicações compostas"(composite applications) no SAP NetWeaver 7.1 CE. Esta notícia é muito interessante por colocar o Grails como a opção escolhida por uma corporação de peso como a SAP para um de seus produtos. Excelente notícia para a comunidade Grails. Veja o post do Grame Rocher sobre isso.

E em terceiro, (sem ter uma relação direta com grails, mas que me fez pensar muito nas facilidade que o grails tem a respeito de REST) li outro dia um artigo introdutório sobre REST no InfoQ, que foi muito bom apesar de eu já ter lido outros sobre este tema. Mostra de maneira simples uma possível implementação dos conceitos de REST, e reforça esta alternativa light ao mundo de web services. E só pra não deixar passar, veja as facilidades para REST que o Grails tem (veja item 13.1).

Até a próxima...

Grails muito perto da release 1.0

Olá,

depois de tanto tempo lonje do meu blog, infelizmente, volto a campo para comentar algumas coisas.

Primeiro, estou tão longe assim devido (eu sei que não é desculpa, mas...) ao trabalho e muito também a minha filha. Manuela completará 1 ano daqui a duas semanas. E este primeiro ano de pai de filha única e menina, realmente eu fiquei muito babão e dedicando todo meu tempo livre a ela.

Em fim....

Depois de um período de trabalhos de consultoria, um pouco longe da mão na massa, tenho voltado a codificar, e naturalmente usando o Grails. Tendo usado o grails desde a versão 0.3, e isso já faz quase um ano, e passando pelas migrações para as versões 0.4.1, 0.4.2, 0.5 e agora 0.6, percebo o quanto valeu a pena ter escolhido o Grails para novas aplicações quando ainda era 0.3 Na época existia um questionamento muito grande se eu deveria ou não usar o Grails 0.3, quando ainda era muito no início do framework, quando a cada nova release era necessário alguma reengenharia devido a mudanças de API (eu senti muito migrande da 0.4.2 para a 0.6). Hoje, agradeço a mim mesmo por ter apostado no Grails naquela época.

Tenho uma aplicação que começou a ser desenvolvida lá traz com 0.3, e hoje roda em produção com grails 0.6 (ainda não migrei para 1.0-RC1). Estou muito satisfeito com a decisão de usar o grails desde o início, pois o granho de produtividade foi tanto, que hoje quando precisamos dar manutenção, evoluir e criar novas funcionalidades, penso em como seria custoso se não estivessemos usando o Grails. Acho que seria caro demais para meu cliente, ou então usaríamos uma solução em PHP (neste caso, deste cliente).

O Grails está na versão 1.0 RC1, faltando poucas semanas para a release final 1.0, finalmente. Muitas pessoas, e principalmente empresas, só irão assumir a aposta num novo framework caso ele tenha um release 1.0 estável. E agora o Grails já está quase lá.

A quantidade de facilidades que o grails 1.0 nos dá é enorme:
- Facilidades para Web Services (REST ou SOAP)
- Diversos plugins. Destaques para:


Não dá nem para citar tudo aqui. Só lendo mesmo, e principalmente, experimentando.

Falando em "lendo", numa discussão há algumas semanas, o pessoal da lista colocou a opinião de que era fundamental para uma boa adoção do grails (corporativa principalmente) a existência de uma documentação MUITO melhor, pois o site era razoável apenas. Em resposta a isso, o pessoal da G2One (empresa criada para dar suporte ao Groovy e Grails) escreveu o primeiro draft do Reference Guide. Que para uma primeira versão, está muito bom. Vale a leitura completa para conhecer diversos detalhes do framework.

O que me motivou para escrever este post de hoje foi uma mensagem enviada para a lista pelo Matt Raible. Ele é um consultor/arquiteto/desenvolvedor Java, com bastante experiência, e criador do AppFuse. Já usei muito o AppFuse, e se não fosse o Grails, estaria usando até hoje.
O Matt Raible mandou uma mensagem perguntando algumas coisas sobre performance do Grails, sobre o uso do FreeMarker com o Grails, sobre a possibilidade de criar um Struts2 plugin para o grails, e outras coisas. Ele perguntava essas coisas pois queria ter mais argumentos para conseguir "vender" o grails para algumas emoresas em que ele está prestando consultoria, empresas essas que usam essas tecnologias e cujos diretores gostariam de manter a tecnologia em uso para os próximos projetos. Os argumentos e dúvidas do Matt são de que o Grails permitiria a continuidade do uso dessas tecnologias, e ainda oferece um desenvolvido mais produtivo, etc, etc...

Depois da release 1.0, com o nível de documentação que se está alcançando, com a comunidade ativa que o grails tem hoje...... Aí, quando eu leio o Matt defendendo o uso do Grails em empresas que ele dá consultoria, sinceramente é o último argumento que eu precisava. Não tem mais volta. Pra mim, aplicações web na plataforma java, só em grails.

Ah, em relação a minha aplicação que citei acima. É um site que tem mais de 200.000 usuários cadastrados, q tem 31.000 visitantes por dia, gerando aproximadamente 400.000 page views por dia. Há controle de login, processamento de imagens, envio de emails, módulo administrativo, geração de relatórios, etc, etc.
Vejam por si só:
http://www.noiteuniversitaria.com.br

Grande abraço e até a próxima.

Grails e ImageMagick, poderio em manipulação de imagens

Recentemente tive que lidar, mais uma vez, com manipulação de imagens numa aplicação web. O requsito era o clássico: usuário faz upload de uma imagem que a gente não sabe as dimensões, e a aplicação precisa criar um thumbnail (aquela versão bem reduzida da imagem para apresentar numa página junto com diversos outros elementos de página), e também um versão da imagem em tamanho grande pré-determinado.

Mas desta vez havia requisitos novos:
1) Era preciso adicionar uma marca d'água à foto grande, e;
2) Deveria ser possível fazer um upload de um arquivo zip com dezenas de fotos dentro, e a aplicação precisava processar todas as imagens do zip, criando o tumbnail, a foto grande e a marca d'água.

Uma das opções que surgiram no meio do caminho apareceu quando surgiu este assunto na lista do Grails e alguém fez com que eu conhecesse o ImageMagick. Esta biblioteca é uma biblioteca nativa de processamento de imagens...como se fosse um photoshop, porém sem interface gráfica, apenas por linha de comando. E o mais interessante é que ela realmente possui diversas funcionalidades de um photoshop, como filtros, transformações, conversões, ou seja, realmente edição de imagem. Vale a pena conhecer. Veja alguns exemplos aqui. Para exemplos de uso da API, veja aqui.

Ok....então passamos a conhecer o ImageMagic (IM). Ah, antes que eu esqueça, existem várias intefaces de acesso ao IM para várias linguagens. Há inclusive o JMagick, que é a API java para o IM. Porém, pesquisando a respeito no google a gente vê que em diversas situações o JMagick crasha (crash). Então, se a gente não pode ainda, ou não deve, usar o JMagick, a saída é usar o IM nativamente ( que deve ser o que o JMagick faz, mas não sabemos o que fizeram lá para ele entrar em crash né).

Portanto, finalmente, este post tem então o objetivo de mostar uma action de um controller grails que eu fiz num micro projetinho grails só pra testar o uso do IM usando groovy e executando o IM nativamente, seguindo as dicas do nosso amigo James Page da lista do grails.

O primeiro passo é instalar o ImageMagick na sua plataforma. Em windows há o instalador através de um arquivo .exe. No linux há o RPM. E é claro, você pode instalar a partir do fonte do ImageMagick também.

Depois de instalar, você pode testar facilmente pela linha de comando. Se funcionou, vamos para o mundo web com nosso grails.

Eu criei um projeto novo só pra testar. Para isso:

grails create-app


Chamei este projeto de "img". Após criar, vá para o diretório do projeto e

grails create-domain-class


Chamei esta classe de domínio de TaskFile (só porque em outro projeto eu tenho uma classe Task que possui diversos TaskFile).

class TaskFile { 
String name
Date uploaded = new Date()
String description
}



Em seguida gerei o controlador TaskFileController (com comando "grails generate-controller").

import org.springframework.web.multipart.MultipartFile;

class TaskFileController {
def index = { redirect(action:list,params:params) }
// .... todas as actions que o grails gera. Alterei a action save
// alem de alterar, criei metodos privados
def save = {
def taskFile = new TaskFile()
taskFile.properties = params

if(taskFile.save()) {
def f = request.getFile('taskFile')
if(!f.empty) {
def fileName = 'file_' + taskFile.id + getExtension(f)
f.transferTo( new File('imgs/' + fileName) )
processImg(fileName)
}
redirect(action:show,id:taskFile.id)
}
else {
render(view:'create',model:[taskFile:taskFile])
}
}

private void processImg(fileName){
final String original = 'imgs/' + fileName
def t = Thread.start {
def cmd = createCmd(original, '-thumbnail', createDimentions(100,0) , 'imgs/tumb_' + fileName)
def process = cmd.execute()
process.waitFor()

def cmdMain = createCmd(original, '-thumbnail', createDimentions(400,0) , 'imgs/main_' + fileName)
def processMain = cmdMain.execute()
processMain.waitFor()

def waterMarkCmd = ["cmd /c composite -compose atop watermark.png", 'imgs/main_' + fileName, 'imgs/wm_' + fileName]
waterMarkCmd.join(" ").execute()
}
}

private String getExtension(MultipartFile file){
String contentType = file.getContentType();
String fileExtension = null;
if (contentType.equalsIgnoreCase("image/pjpeg") || contentType.equalsIgnoreCase("image/jpeg")) {
fileExtension = ".jpg";
}
else if (contentType.equalsIgnoreCase("image/gif")) {
fileExtension = ".gif";
}
else if (contentType.equalsIgnoreCase("image/x-png")) {
fileExtension = ".png";
}

return fileExtension;
}




String createCmd(inpath, action, options ,outpath){
//@todo Need os specific code here... Remove c for Linux.....
def cmd = ['cmd','/c', 'convert', inpath, action , options, outpath]
return cmd.join(" ");
}

String createDimentions(width, height){
StringBuffer sb = new StringBuffer();
if(width > 0)
sb.append(width);

sb.append('x');
if(height > 0)
sb.append(height)

return sb.toString()
}
}





Percebam que no código do controlador, o interessante foi o uso de uma Thread separada para o processamento das imagens. Já que processar imagens pode levar algum tempo em determinados casos, não é necessário deixar o usuário final esperando isso. Assim, criei uma nova thread que faz este trabalho enquanto a thread do request já manda o response direto pro usuário. Neste exemplo, eu faço 3 coisas: salvo o arquivo original, crio o thumbnail, crio a imagem grande que chamei de main, e por último crio a imagem grande com a marca d'água (watermark). Tudo isso é feito no método processImg(fileName). Percebam que este método faz uso do método execute() do groovy, que executa um comando no sistema operacional e retorna um java.lang.Process.

Depois disso foi só gerar as views (grails generate-views). Alterei a create.gsp para que tivesse o upload do meu arquivo:

           <g:form action="save" method="post" enctype="multipart/form-data">
<div class="dialog">
<table>
<tbody>



<tr class='prop'><td valign='top' class='name'><label for='description'>Description:</label></td><td valign='top' class='value ${hasErrors(bean:taskFile,field:'description','errors')}'><input type='text' name='description' value="${taskFile?.description?.encodeAsHTML()}" /></td></tr>

<tr class='prop'><td valign='top' class='name'><label for='name'>Name:</label></td><td valign='top' class='value ${hasErrors(bean:taskFile,field:'name','errors')}'><input type='text' name='name' value="${taskFile?.name?.encodeAsHTML()}" /></td></tr>

<tr class='prop'><td valign='top' class='name'><label for='taskFile'>taskFile:</label></td><td valign='top' class='value ${hasErrors(bean:taskFile,field:'uploaded','errors')}'><input type="file" name="taskFile" /></td></tr>

</tbody>
</table>
</div>
<div class="buttons">
<span class="formButton">
<input type="submit" value="Create"></input>
</span>
</div>
</g:form>


E só isso. Até a próxima. Abcs.

Grails plugins mostrando sua força

O projeto Grails lançou recentemente sua versão 0.5.
A evolução tem sido bastante rápida, com o objetivo de chegar na versão 1.0 até o fim deste ano. Já dise uma vez e vou dizer de novo: estar na versão 0.5 ( ou qualquer uma que ainda não seja 1.0) não significa que não possa ser usado para sistemas em produção, significa apenas que a API pode ser alterada ao longo do caminho, forçando as aplicações a se atualizarem junto com a evolução do Grails.

Uma das novidades recentes é a API de Plugins do Grails....ok ok, eu sei que já falei disso.

Neste post que quero apenas comprovar como o Grails Plugins pode ser bastante poderoso. O Graeme Rocher enviou recentemente um post no seu blog demonstrando a beleza dos plugins ao criar um plugin para integrar o Wicket ao Grails.

Vale a pena olhar para quem tem interesse neste crescente projeto que é o Wicket.

Abcs
Felipe

Grails: Controller para download de arquivo em diretório

Eu tenho colocado ultimamente posts que são pequenos e possuem código fonte de algumas pequenas coisas. Hoje vou colocar aqui uma action de um controller que faz download de um arquivo qualquer de um diretório no sistema de arquivos.
Eu acho interessante ter estes pequenos posts de exemplos pois servem de referência para dúvidas futuras, inclusive minhas. Alguém acha ruim este tipo de post? Preferem os posts mais elaborados (porém demandam mais tempo né)?
Em fim, segue o código.

def downloadBook = {
def file = new File("c:/temp/onliso.pdf")
response.setHeader("Content-Type", "application/octet-stream;")
response.setHeader("Content-Disposition", "attachment;filename=\" onlisp.pdf\"")
response.setHeader("Content-Length", "${file.size()}")
response.outputStream << file.text.bytes
}


É simples ou não é desenvolver vom grails e groovy. Olha o tamanho deste código. QUal seria a alternativa em Java? Quantas linhas a mais? Não quero criticar não, eu adoro Java, mas ter uma linguagem de script como Groovy na plataforma Java é muito bom, MUITO BOM.

Até a próxima.
[]s
Felipe

Aplicação Swing em Groovy para Regular Expressions

Hoje um usuário (Jeremy Rayner) da lista do Grails nos enviou uma pequena aplicação desktop escrita em Groovy que pode ser bastante útil para testar Regular Expressions. É tão pequena que vou colocar o código fonte abaixo. Esta aplicação faz o highlight das partes de um texto que você colocar de acordo com a expressão regular inserida. Veja screen shot abaixo. Para executar basta salvar este código num script RegexCoach.groovy e executar o comando: groovy RegexCoach

// Groovy Regex Coach - Copyright 2007 Jeremy Rayner
// inspired by http://weitz.de/regex-coach/
import java.awt.*
import java.awt.event.*
import java.util.regex.*
import javax.swing.*
import javax.swing.text.DefaultHighlighter
import groovy.swing.SwingBuilder

// define the view
def swing = new SwingBuilder()
def gui = swing.frame(title:'The Groovy Regex Coach', location:[20,40], size:[600,500], defaultCloseOperation:WindowConstants.EXIT_ON_CLOSE) {
panel(layout:new BorderLayout()) {
splitPane(orientation:JSplitPane.VERTICAL_SPLIT, dividerLocation:150) {
panel(layout:new BorderLayout()) {
label(constraints:BorderLayout.NORTH, text:'Regular expression:')
scrollPane(constraints:BorderLayout.CENTER) {textPane(id:'regexPane')}
}
panel(layout:new BorderLayout()) {
label(constraints:BorderLayout.NORTH, text:'Target string:')
scrollPane(constraints:BorderLayout.CENTER) {textPane(id:'targetPane')}
panel(constraints:BorderLayout.SOUTH, layout:new FlowLayout()) {
button('<<-', id:'scanLeft')
button('->>', id:'scanRight')
}
}
}
}
}
def highlighter = new RegexHighlighter(swing:swing)
swing.regexPane.addKeyListener(highlighter)
swing.targetPane.addKeyListener(highlighter)
swing.scanLeft.addActionListener(highlighter)
swing.scanRight.addActionListener(highlighter)
gui.show()

class RegexHighlighter extends KeyAdapter implements ActionListener {
def swing // reference to the view
int scanIndex // how many times to execute matcher.find()
def orange = new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE)
def yellow = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW)
def red = new DefaultHighlighter.DefaultHighlightPainter(Color.RED)

// react to user actions
public void actionPerformed(ActionEvent event) {
if (event.actionCommand == '<<-') {scanIndex = Math.max(scanIndex - 1, 0)}
if (event.actionCommand == '->>') {scanIndex++}
doHighlights()
}
public void keyReleased(KeyEvent event) {
scanIndex = 0
doHighlights()
}

// the main regex logic
private void doHighlights() {
try {
swing.regexPane.highlighter.removeAllHighlights()
swing.targetPane.highlighter.removeAllHighlights()
def regex = swing.regexPane.text
def target = swing.targetPane.text
def matcher = (target =~ regex)
int scan = 0
while (scan < scanIndex) {
matcher.find()
scan++
}
if (matcher.find()) {
int i = 0
while (i++ < matcher.groupCount()) {
swing.targetPane.highlighter.addHighlight(matcher.start(i), matcher.end(i), orange)
}
swing.targetPane.highlighter.addHighlight(matcher.start(), matcher.end(), yellow)
} else {
scanIndex = Math.max(scan - 1, 0)
if (scanIndex > 0) {doHighlights()}
}
} catch (PatternSyntaxException e) {
swing.regexPane.highlighter.addHighlight(e.index, e.index + 2, red)
}
}
}




Bind de coleção de objetos com Grails

Muitas vezes os frameworks ágeis de programação web como Grails e Ruby on Rails ajudam muito nas operações CRUD simples. Você consegue rapidamente fazer criar, obter, alterar e apagar objetos de domínio com forms simples. Mas nas aplicações reais, fora dos "Hello World" usados nos exemplos, a gente se depara algumas vezes com a necessidade de fazer operações de CRUD em forms mais elaborados. Às vezes há casos que queremos reunir mais de um objeto de domínio num mesmo form, e há outros casos em que queremos reunir o mesmo objeto de domínio mais de uma vez: um exemplo seria salvar vários objetos Endereço de uma só vez.

Há uma maneira simples, usando o Grails, de se fazer o bind de uma coleção de objetos do mesmo tipo. Vamos a ela:

Neste exemplo, digamos que a gente queira salvar vários objetos Person de uma só vez, recebendo um post de um form único.

Crie um objeto helper em Groovy (um objeto comum que irá lhe ajudar nesta tarefa) como se segue:

class MyForm {
def personList = [new Person(), new Person()]
}



No arquivo GSP que terá o form, faça assim:
<input name="personList[0].firstname" value="Fred" />
<input name="personList[0].surname" value="Jones" />
<input name="personList[1].firstname" value="Bob" />
<input name="personList[1].surname" value="Smith" />


No controlador que irá receber o POST, você só precisará fazer o bind desta forma:
def form = new MyForm()
bind(form, params)



Pronto, simples assim. Desta forma você continua aproveitando o BIND automático do Grails (no fundo é Bind do Spring) e simplificando o código do seu controller.

[]s
Felipe