InfoQ CheatSheets: dicas que ajudam

Eu sei, eu sei....
Tenho andado totalmente sumido.... essa vida tá a maior correria....

o InfoQ tem se tornado leitura obrigatória para mim. Muito bom, prático, com boas entrevistas, vídeos, PDFs, etc.

A última dica que vi no InfoQ foi descobrir o "FREE Cheatsheets for Developers". Muito legal.

Lá tem aqueles PDFs curtos, com dievrsas dicas. Cada PDF é sobre um assunto. No momento, são eles:

Não tenho trabalhado muito com Grails ultimamente (infelizmente). Adivinhe só. Tenho trabalhado com .NET. É isso mesmo....coisas da vida profissional.

Abcs

Detalhe do Grails com Eclipse

Pessoal

eu já passei maus bocados uma vez por causa da questão que irei escrever aqui. Hoje, meu companheiro de desenvolvimento João Paulo passou pelo mesmo problema...Depois de algum tempo ele resolveu me perguntar, e lendo o erro que ele me passou, não deu outra, era o problema que já passei.

Quando você ler um erro como este:

No signature of method: Requestmap.save() is applicable for argument types: () values: {}

(é claro que no seu caso a sua classe de domain não será Requestmap, será Pessoa, Categoria, Produto, sei lá o que)

Uma das possíveis causas disso é uma configuração no eclipse, que faz com que o Eclipse compile as classes groovy, gerando os arquivos .class . Neste caso, o grails, ao rodar a aplicação com "grails run-app"
, ele também compila, aí tudo se perde.

Não deixe de configurar o Eclipse para não compilar os arquivos de groovy. Para isso:
- Clique com botão direito no seu projeto, no eclipse
- Selecione "Groovy project Properties"
- Marque a opção "Disable Groovy Compiler Generating Class Files"

Abcs
Felipe

Grails 1.0.1 e many-to-many com GORM DSL

Oi pessoal,

primeiro queria divulgar o forum do GrailsBrasil ( www.grailsbrasil.com ). Um ótimo espaço para os brazucas, que cada vez mais descobrem e se encantam com o Grails.

Em seguida, queria falar, com certo atraso, da tão esperada Release 1.0 do Grails, que na verdade já está na 1.0.1. Isso é uma grande notícia.

Por último, a razão deste post....

O Grails 1.0.1 possui o GORM DSL, que oferece grande facilidade para controlar detalhes do mapeamento objeto relacional dos objetos de domínio. Ao migrar uma aplicação do grails 0.6 para o 1.0.1, quis alterar alguns detalhes do mapeamento, já que agoraeu conseguiria isso sem precisar apelar para mapeamento Hibernate com XML.

O problema que eu queria resolver era:
Digamos que eu tenha uma classe Usuario e outra Privilegio, com um relacionamento many-to-many entre elas. Logo teremos:


class Usuario {
String nome
static hasMany = [privilegios:Privilegio]
}

class Privilegio {
String nome
static hasMany = [usuarios:Usuario]
static belongsTo = Usuario
}

Com as classes acima, o grails gera as seguintes tabelas:
usuario
id
nome

privilegio
id
nome

usuario_priv
usuarios_id (que é uma FK para privilegio.id)
privilegios_id (que é uma FK para usuario.id)
É isso mesmo: o campo usuarios_id é uma chave estrangeira para o id da tabela privilegio; e o campo privilegios_id é uma chave estrangeira para o id da tabela usuario. A explicação pra isso está aqui (vejam o comentário do Graeme).

Eu não sei quanto a vocês, mas pra mim isso soa muito estranho. Mas é assim mesmo que o grails gera por padrão. A forma que eu gosto de trabalhar é com campos no singular e com o nome do campo da chave estangeira condizente com o nome da tabela de referência:
usuario_priv.usuario_id = usuario.id
usuario_priv.privilegio_id = privilegio.id

Para isso, então, eu antigamente teria que fazer o mapemanto com XML do hibernate (já fiz vários para outras aplicações com grails). Mas agora na versão atual posso fazer o que quero com o GORM DSL. E é isso que quero mostrar, pois há um detalhe que precisei fazer alguns testes até entender o comportamento do Grails com essa DSL. Vamos lá...

class Usuario {
String nome
static hasMany = [privilegios:Privilegio]

static mapping = {
privilegios column:'usuario_id', joinTable:'usuario_priv'
}
}


class Privilegio {
String priv
static hasMany = [usuarios:Usuario]
static belongsTo = Usuario

static mapping = {
usuarios column:'privilegio_id', joinTable:'usuario_priv'
}
}


O que eu acho curioso e anti-intuitivo no código acima, é que numa primeira tentativa eu coloquei:
class Usuario {
static mapping = {
privilegios column:'privilegio_id', joinTable:'usuario_priv'
}
}
Mas isso acabou sendo errado. Na verdade temos que colocar como nome da coluna (para ter o resultado que eu esperava), o nome da classe em que me encontro, e não o nome do atributo de relacionamento. Em fim: o correto é o código acima completo das classe Usuario e Privilegio, e não o código acima com fundo avermelhado.

Fiz questão de colocar isso aqui, pois a documentação não me parece muito clara quanto a isso. (talvez eu é que tenha entendido errado a documentação, sei lá....em fim....tá aí pra quem precisar deste detalhe).


Abcs
Felipe

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