<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DUINSXo5fyp7ImA9WhRVFUw.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990</id><updated>2012-01-14T03:06:38.427-02:00</updated><category term="arquitetura" /><category term="grails" /><category term="performance" /><category term="scrum" /><category term="cloud" /><category term="banco de dados" /><category term="mysql" /><category term="java" /><category term="mac" /><category term="aprender" /><title>Felipenasc</title><subtitle type="html">Aplicações web com Java, Grails e Ajax, baseadas no mundo open source</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://felipenasc.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>53</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/WHRf" /><feedburner:info uri="blogspot/whrf" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUINSXo4fyp7ImA9WhRVFUw.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-4169330907799948630</id><published>2012-01-14T03:06:00.000-02:00</published><updated>2012-01-14T03:06:38.437-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-14T03:06:38.437-02:00</app:edited><title>Montando um super PC de alta performance</title><content type="html">&lt;span style="color: blue;"&gt;Um amigo me mandou um email me dando dicas para montagem de um PC de alta performance. Ele escreveu o que fez para montar a máquina dele, que disse ter ficado um verdadeiro avião. Ficou tão bom o email que aqui vai ele. Valeu Paulo Goes......:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
"Felipe,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
O coração do sistema é um processador i7 2600K. É o processador mais potente para uso pessoal (os outros i7 já são workstation ou servidor). Este processador incorpora um conjunto de instruções gráficas, de modo que dispensa o uso de processador gráfico, mesmo na placa mãe. O i7 2600 (sem o K) é um pouco mais barato, possui a mesmíssima capacidade de processamento, só não é “overclockable” e tem uma versão anterior do driver gráfico Intel (é uma excelente opção para reduzir um pouco o custo). Os i5 (acho que o i5 equivalente é o 2500/2500K) têm potência equivalente (e a mesma relação K/sem K dos i7), mas não suportam hiperthreading. Com hiperthreading as 4 CPUs do processador dual core aparecem como oito para o sistema operacional, proporcionando um ganho de paralelismo (se e somente se o seu mix de aplicações demandar tantos processos concorrentes). Assim os i5 são também excelentes opções para baratear o custo.&lt;br /&gt;
&lt;br /&gt;
O componente seguinte é a placa mãe. Atualmente estou bem exigente neste quesito, e só estou comprando ASUS ou Intel. As Intel estão mais baratas, e bem interessantes. No entanto, eu tinha alguns requisitos adicionais:&lt;br /&gt;
&lt;br /&gt;
- queria 16G de memória – isto hoje só é economicamente viável com placas que tenham 4 bancos de memória. A maioria das placas mais baratas só estão vindo com 2 bancos, mas as memórias de 8G estão ainda proibitivamente caras;&lt;br /&gt;
- tenho alguns dispositivos IDE, e as placas mais modernas e baratas só têm SATA&lt;br /&gt;
- meu adorado monitor ainda é VGA, e as placas mais modernas e baratas têm apenas DVI/HDMI, e eu não queria usar conversores&lt;br /&gt;
- SATA 6GB/s – as placas mais modernas têm interface SATA de 6GB/s. Na prática, não faz a menor diferença, porque os HDs não conseguem entregar nem os 3GB/s do SATA “II”. No entanto (ver abaixo), uma das principais “turbinas” do meu “avião” é um disco SSD que atinge com facilidade este throughput, de modo que SATA 6GB/s era mandatório.&lt;br /&gt;
- gosto de placas ATX – nada de micro-ATX ou mini-ATX (embora, na prática, sejam quase equivalentes)&lt;br /&gt;
- mouse, teclado, cam, impressora, scanner, iPhone, disco externo, pen-drives, tudo lá em casa é USB. Desejo uma placa mãe com o maior número possível de USBs externas.&lt;br /&gt;
&lt;br /&gt;
No mais, escolher uma placa é uma combinação de marca, com os slots/dispositivos que você necessita, mais aqueles que você acha que vai precisar no futuro. Neste sentido, achei que umas portas USB 3 seriam altamente desejáveis, e que um firewire não seria demais. Aí, é entrar no Boadica, filtrar por fornecedor, sortar por valor, e ir olhando as configurações até achar a primeira que te satisfaça. Escolhendo uma, entrar no Tomshardware, para ver se há algum comentário negativo sobre esta combinação processador/placa. Acabei escolhendo uma Asus, mas nem lembro o modelo agora.&lt;br /&gt;
&lt;br /&gt;
O terceiro componente importante é um SSD de 120G da OCZ (Vertex 3). Este é um componente ainda complicadinho. Memórias SSD têm um burnout depois de alguns milhões de escritas (ou seja, têm uma vida útil limitada). As controladoras mais modernas (Sandforce) maximizam a vida útil distribuindo igualmente as atividades de escrita por setores diferentes do disco, evitando assim, por exemplo, que o começo do disco estrague antes do final. Uma boa controladora também é essencial para conseguir os tais 6GB/s de throughput. Os OCZ são as Ferrari dos SSD. Tem uma outra linha (que não é Vertex) que é um pouco mais barata, mais ainda muito boa. Me aconselharam a evitar os Kingston (bem mais baratos) e me disseram que os Corsair talvez sejam bons. Li alguns artigos dizendo que os Samsung estão causando sensação por serem mais baratos e tecnologicamente competentes, mas não quis arriscar. A idéia é instalar o Windows neste SSD, conseguindo assim uma baita velocidade nos boots e na carga de qualquer programa/OS component. Configurar corretamente o Windows para maximizar o benefício e a vida útil do SSD é uma arte obscura, na qual ainda estou me iniciando (deixa o paging ou não? temporary IE files? temp files? como tirar os dumps do Windows do SSD? etc.).&lt;br /&gt;
&lt;br /&gt;
O gabinete é outro aspecto que eu tomo cuidado. Gabinetes devem ser silenciosos, práticos para montar (por exemplo, não necessitam de parafusos para fixar os HDs) e bem ventilados. Já a alguns anos que venho usando os gabinetes CoolerMaster. Sempre usei a linha básica (Elite), mas este eu comprei da linha ultra-silenciosa (Sileo), que vem também com duas ventoinhas (os Elite vêm com uma só – a gente sempre pode acrescentar ventoinhas, mas as originais da CoolerMarster são hiper-silenciosas).&lt;br /&gt;
&lt;br /&gt;
A fonte é um componente fundamental para a saúde do equipamento. A qualidade das fontes caiu, e fontes anteriormente de boa qualidade (como as Seventeen) hoje são consideradas suspeitas. Comprei uma Coolermaster 600W reais, meio overkill para o meu equipamento (uma de 450W já bastava) porque não tenho nenhum periférico/placa no meu ambiente que não seja um “array” de HDs (que consomem bem pouca energia), mas, pensando no futuro...&lt;br /&gt;
&lt;br /&gt;
A memória, comprei Corsair 4x4GB. Eu sempre usei Kingston (que custa metade do preço) sem problemas, mas meu filho me convenceu a comprar as Corsair... provavelmente bobagem.&lt;br /&gt;
&lt;br /&gt;
O componente final é um HD de 1TB (ainda o menor custo por byte armazenado), para se juntar aos meus atuais 2,5TB.&lt;br /&gt;
&lt;br /&gt;
Um aspecto interessante é que eu não jogo games e não faço processamento gráfico, de modo que não tenho placa de vídeo há anos (uso onboard ou, agora, inprocessor).&lt;br /&gt;
&lt;br /&gt;
Finalmente, como comprei: Primeiro, eu uso o Boadica para estabelecer referência de preços. Os preços do Boadica são muito bons, e normalmente não consigo estes preços nem na Santa Efigênia aqui em sampa. Como estava sem tempo, minha estratégia desta vez foi adquirir na Internet. Para começar, identifiquei no Buscapé os fornecedores web mais confiáveis para componentes (nenhum é muito confiável, nem inspira muita confiança, de modo que é preciso ser um pouco tolerante e aceitar algum risco aqui). Pré-selecionei uma meia dúzia, fiz uma análise de preços, e acabei ficando com 3 (Atera, Superbalão, e Kabum). Comprar em loja, e ainda mais parcelado (12x) se afasta um pouco dos preços do Boadica, mas é uma forma de diminuir o risco e o impacto imediato no bolso). Você não precisa fazer todas as compras na mesma loja, mas também não deseja comprar um componente em cada loja (maior risco de problemas e despesas de entrega), assim, tem que fazer algumas simulações para ver qual fornecedor consegue o menor preço médio dos componentes combinados. Comprei o gabinete, a fonte e as memórias na Kabum, e o processador, a placa mãe, e o HD no Superbalão. O SSD arrisquei um pouco mais e comprei no mercado livre.&lt;br /&gt;
&lt;br /&gt;
A compra no mercado livre foi a mais bem sucedida, embora o mercado pago tenha feito uma bobagem e faturado duas vezes o meu cartão. Escrevi para o vendedor, e ele em algumas horas estornou a venda (o mercado pago não ajuda você, você tem que se virar), e em menos de 24h após a compra o SSD estava lá em casa. Com a Kabum tive vários problemas por conta da operadora American Express (nunca tinha usado e nunca mais usarei). Cancelei a compra, refiz pelo Visa, e 48h depois recebi a mercadoria, sem problemas. No geral, fiquei muito satisfeito com a Kabum, por causa do comportamento deles nestes dificuldades com a AMEX. O pior foi o Superbalão. A entrega levou uma semana (após meu cartão ter autorizado), e o HD chegou sem lacre e arranhado (parece que já havia sido instalado em algum PC antes). Deu algum trabalho para trocar (eles queriam que eu pagasse o frete, e eu tive que chiar muito), e ainda estou aguardando receber a troca.&lt;br /&gt;
&lt;br /&gt;
That’s it. Isso tudo requereu muita pesquisa, conversa, visitas a fóruns e o escambau. A parte mais chata são sempre estas relações comercias selvagens do Brasil, combinadas com a estupidez da Amex. Por uns 10K reais faço tudo de novo prá você..."&lt;br /&gt;
&lt;br /&gt;
&lt;span style="color: blue;"&gt;Isso é que é dica..... Sensacional....&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-4169330907799948630?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CZb2eyk8jGzg4-6Yu02yYyvcnn0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CZb2eyk8jGzg4-6Yu02yYyvcnn0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CZb2eyk8jGzg4-6Yu02yYyvcnn0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CZb2eyk8jGzg4-6Yu02yYyvcnn0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/9I2gwritnqY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/4169330907799948630/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=4169330907799948630" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4169330907799948630?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4169330907799948630?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/9I2gwritnqY/montando-um-super-pc-de-alta.html" title="Montando um super PC de alta performance" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2012/01/montando-um-super-pc-de-alta.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMCRn48eCp7ImA9WhdQGUo.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-9219035760170224915</id><published>2011-08-21T22:26:00.001-03:00</published><updated>2011-08-21T22:27:47.070-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-21T22:27:47.070-03:00</app:edited><title>Grails de alta performance - parte 2</title><content type="html">Este post faz parte de uma série que estou escrevendo sobre técnicas para fazer uma aplicação grails de alta performance. Estou usando uma aplicação de exemplo, para demonstrar estas técnicas. Esta aplicação se chama &lt;a href="https://github.com/felipenasc/GPerform"&gt;GPerform&lt;/a&gt;, e está &lt;a href="https://github.com/felipenasc/GPerform"&gt;disponível no GitHub&lt;/a&gt;, e é uma espécie de Twitter + Instagram (em menor escala, naturalmente), onde usuários enviam posts de texto curto + foto.&lt;br /&gt;
&lt;br /&gt;
Na &lt;a href="http://felipenasc.blogspot.com/2011/07/gperform-uma-aplicacao-de-exemplo-com.html"&gt;parte 1&lt;/a&gt; desta série, eu mostrei a primeira prática para se desenvolver uma aplicação grails de alta performance:&amp;nbsp;Não usar Collections para as relações hasMany.&lt;br /&gt;
&lt;br /&gt;
Neste post vou mostrar os plugins que usei.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;1) Spring-events plugin:&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Este plugin dá a possibilidade de publicar eventos via Spring, de forma assíncrona.&lt;br /&gt;
&lt;br /&gt;
Para instalar o plugin, basta executar "grails install-plugin spring-events".&lt;br /&gt;
&lt;br /&gt;
Eu usei este plugin para lançar um evento indicando que alguém enviou um novo post no sistema, e que, portanto, o sistema precisa processar a foto (criando uma foto com tamanho (kb) menor, e outras fotos thumbnail).&lt;br /&gt;
&lt;br /&gt;
Mas, para não deixar o usuário esperando enquanto o sistema processa as fotos, e assim dar uma impressão de muita velocidade de resposta para o usuário, eu quis fazer este processamento de forma assíncrona, dando uma resposta para o usuário quase que imediata após o envio do seu post.&lt;br /&gt;
&lt;br /&gt;
A action que recebe o envio do post do usuário, com texto + foto, apenas grava a foto num diretório, salva a entidade Foto no banco de dados, e lança este evento assíncrono no Spring, retornando a resposta imediatamente para o usuário (sem processar a foto neste momento). Veja:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;    def compartilhar = {
        
        String msgErro = ""
        
        if(!session.usuario){
            redirect(controller:'home')
            return
        }
        
        // Pega a foto do formulario e salva no diretorio para ser processada
        MultipartFile fotoOriginal = request.getFile('fotoOriginal')
        String extensao = identificaExtensao(fotoOriginal)
        
        String nomeArquivo = RandomStringUtils.random(10).encodeAsSHA256() + extensao
        
        try {
            File destino = new File(ConfigurationHolder.config.gp.fotos.originais.folder + File.separator + nomeArquivo)
            fotoOriginal.transferTo(destino)
            
            // Salva uma isntancia do objeto de metadados Foto
            Foto foto = new Foto(params)
            foto.autor = Usuario.get(session.usuario.id)
            foto.nomeArquivo = nomeArquivo
            if(foto.save(flush:true)){
                
                // metodo adicionado pelo spring-events Plugin
                &lt;b&gt;publishEvent(new FotoSubidaEvent(new Expando(id:foto.id)))&lt;/b&gt;
                flash.message = "Foto enviada com sucesso. Aguarde processamento."
                redirect(action:index)
            }
            else{
                if(destino.exists()) destino.delete()
                msgErro = "Erro ao salvar os dados da foto."
                render(view:'index', model:[msgErro:msgErro, foto:foto])
            }
        } catch (IOException ioe) {
            msgErro = "Erro ao fazer upload do arquivo."
        } catch (IllegalStateException ie) {
            msgErro = "Erro ao fazer upload do arquivo."
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Veja que o método importante aqui é o "&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; line-height: 14px; white-space: pre;"&gt;&lt;b&gt;publishEvent()&lt;/b&gt;&lt;/span&gt;", que publica o evento &lt;b&gt;FotoSubidaEvent &lt;/b&gt;(eu sei que o nome ficou feio, mas ...). &amp;nbsp;Pronto, o evento foi publicado.&lt;br /&gt;
&lt;br /&gt;
Agora, precisamos criar uma classe que vai ser o Listener deste evento. A maneira mais fácil que encontrei foi criar uma classe de serviço que implementa "&lt;span class="Apple-style-span" style="font-family: Monaco; font-size: 11px;"&gt;ApplicationListener&lt;fotosubidaevent&gt;&lt;/fotosubidaevent&gt;&lt;/span&gt;", ou seja, ela será um Listener para os eventos do tipo FotoSubidaEvent. Ao implemetar esta interface, sua classe de Service terá que ter um método "&lt;span class="Apple-style-span" style="font-family: Monaco; font-size: 11px;"&gt;&lt;span class="s1"&gt;void&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Monaco; font-size: 11px;"&gt; onApplicationEvent(FotoSubidaEvent event)&lt;/span&gt;". Este método será chamado pelo Spring automaticamente quando um evento do tipo FotoSubidaEvent for lançado, de forma assíncrona.&lt;br /&gt;
&lt;title&gt;&lt;/title&gt;   &lt;style type="text/css"&gt;
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco}
span.s1 {color: #b5288b}
&lt;/style&gt;     &lt;title&gt;&lt;/title&gt;   &lt;style type="text/css"&gt;
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco}
span.s1 {color: #b5288b}
&lt;/style&gt;   &lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;2) Springcache plugin:&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
Este &lt;a href="http://gpc.github.com/grails-springcache/docs/guide/index.html"&gt;plugin&lt;/a&gt;&amp;nbsp;faz uso do projeto Spring Cache,&amp;nbsp;&amp;nbsp;e permite que se faça:&lt;/div&gt;&lt;div&gt;- Cache de métodos dos beans do Spring; por exemplo, para fazer cache do retorno de métodos das classes de serviços.&amp;nbsp;&lt;/div&gt;&lt;div&gt;- Fragmentos das páginas, ou páginas inteiras, geradas pelos controllers; por exemplo, para fazer o cache de uma determinada action de um controller;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;No caso da aplicação de exemplo,&amp;nbsp;&lt;a href="https://github.com/felipenasc/GPerform"&gt;GPerform&lt;/a&gt;, usei o Springcache para fazer cache da action "&lt;span class="Apple-style-span" style="color: #1000d1; font-family: Monaco; font-size: 11px;"&gt;HomeController.&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #1000d1; font-family: Monaco; font-size: 11px;"&gt;recentes()&lt;/span&gt;" , ou seja, eu coloquei em cache os posts de fotos mais recentes. Assim, não é preciso acessar o banco de dados o tempo todo para pegar os posts mais recentes, pois eles estão na memória do cache.&lt;br /&gt;
&lt;br /&gt;
Para usar este plugin, basta instalar usando o comando "grails&amp;nbsp;install-plugin springcache". Em seguida, coloquei uma anotação na action do meu controller (na action que quero que a resposta fique em cache):&lt;/div&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;    &lt;/span&gt;&lt;code&gt;&lt;b&gt;@Cacheable("recentesCache")&lt;/b&gt;
    def recentes = {
        log.info "Executando action 'recentes' e por isso nao ta usando o cache agora."
        def recentes = buscaFotosMaisRecentes(20)
        [fotosMaisRecentes:recentes]
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div&gt;Veja que eu coloquei um nome neste cache ("&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; line-height: 14px; white-space: pre;"&gt;recentesCache&lt;/span&gt;"), pois eu posso criar vários caches distintos, e controlar cada um da forma que eu quiser. Esta anotação&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; line-height: 14px; white-space: pre;"&gt;&lt;b&gt;@Cacheable("recentesCache")&lt;/b&gt;&lt;/span&gt;&amp;nbsp;é que indica para o plugin que o retorno desta action precisa ser guardado em memória no cache. Só isso.&lt;br /&gt;
&lt;br /&gt;
Agora o problema passa a ser como renovar o cache quando um novo post for enviado por um usuário do site. Para isso, basta limpar o cache (matar o cache) quando um novo post for inserido. No meu caso, o que fiz foi o seguinte: quando um usuário envia um novo post (que é um texto + foto), o controller recebe esta requisição, faz algumas verificações, salva a foto num diretório para ser processada posteriormente (de forma assíncrona -- falo sobre isso mais tarde), e grava os dados da entidade Foto no banco de dados (que são os metadados sobre a foto e o texto do post do usuário). Quando o sistema for processar a foto de forma assíncrona, aí sim a foto está pronta para ser mostrada no site, e é neste momento que eu preciso limpar o cache. O método que processa a foto e limpa o cache é um método de uma classe de Serviço (FotoService). Veja abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;    &lt;/span&gt;&lt;code&gt;&lt;b&gt;@CacheFlush("recentesCache")&lt;/b&gt;
    void onApplicationEvent(FotoSubidaEvent event) {
        if(log.isInfoEnabled()) log.info "Executando evento FotoSubidaEvent..."
        
        Foto foto = Foto.get(event.source.id)
        if(foto){
            // processa a imagem da foto
        }
        
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Assim que este método for executado pela aplicação, o cache será limpado (jogado fora), pois este método tem a anotação&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; line-height: 14px; white-space: pre;"&gt;&lt;b&gt;@CacheFlush("recentesCache")&lt;/b&gt;&lt;/span&gt;. Veja que usei o mesmo nome "recentesCache" para indicar qual cache quero limpar.&lt;br /&gt;
&lt;br /&gt;
Perceba também que este é aquele método "&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; line-height: 14px; white-space: pre;"&gt;onApplicationEvent()&lt;/span&gt;", citado no item 1 acima, usado pelo Spring quando o framework detecta o lançamento do evento do tipo FotoSubidaEvent.&lt;br /&gt;
&lt;br /&gt;
Pronto. Da próxima vez que a action &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;HomeController.recentes()&lt;/span&gt; for executada, o Springcache vai ver que o "recentesCache" não existe mais, aí vai executar a action, pegar seu resultado e colocar em cache novamente. E enquanto este cache existir, a action não é executada, e ao invés disso, o conteúdo do cache é enviado para o usuário.&lt;br /&gt;
&lt;br /&gt;
Um pequeno detalhe deste plugin é que ele tem uma configuração padrão que indica que o cache deve existir por apenas 120 segundos. Como era muito pouco para o meu caso, então configurei para que o cache vivesse por 3600 segundos. Veja como:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;springcache {
    defaults {
        eternal = false
        diskPersistent = false
        timeToLive= 86400
    }
    caches {
&lt;b&gt;        recentesCache {
            timeToLive= 3600
        }
&lt;/b&gt;    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Ficamos por aqui com este artigo que já tá longo. Ainda falta coisa pra falar, como resources plugin, cache-headers plugin, cached-resources plugin e zipped-resources plugin. Até a próxima.&lt;br /&gt;
&lt;br /&gt;
Lembre-se que você é bem vindo para contribuir com esta aplicação de exemplo &lt;a href="https://github.com/felipenasc/GPerform"&gt;GPerform via o GitHub&lt;/a&gt;. Abcs a todos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-9219035760170224915?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/eo3wxjntcKqbnkZ5LtmAn95lVXo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eo3wxjntcKqbnkZ5LtmAn95lVXo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/eo3wxjntcKqbnkZ5LtmAn95lVXo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eo3wxjntcKqbnkZ5LtmAn95lVXo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/9dJrKo1EpVk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/9219035760170224915/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=9219035760170224915" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/9219035760170224915?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/9219035760170224915?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/9dJrKo1EpVk/grails-de-alta-performance-parte-2.html" title="Grails de alta performance - parte 2" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2011/08/grails-de-alta-performance-parte-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMNRHo5cCp7ImA9WhdSF0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-7167657694101511974</id><published>2011-07-27T16:54:00.000-03:00</published><updated>2011-07-27T16:54:55.428-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-27T16:54:55.428-03:00</app:edited><title>GPerform: uma aplicação de exemplo com PERFORMANCE na alma</title><content type="html">Venho pensando num tema legal para escrever um post. Aí resolvi dar uma atualizada, ler um pouco, ver umas apresentações, ..... E uma coisa que tem me interessado muito ultimamente é o assunto performance. Como uso muito Grails, então o assunto seria Grails e Performance. Então vamos lá.&lt;br /&gt;
&lt;br /&gt;
Depois de algumas leituras, acho que juntei diversas dicas, plugins, e técnicas que vão fazer uma aplicação grails voar em alta velocidade. Mas não queria apenas ficar na leitura, pois sabemos bem que a teoria é uma coisa, na prática.....&lt;br /&gt;
&lt;br /&gt;
Então botei a mão na massa e resolvi criar uma nova aplicação que chamei de GPerform (Grails Performance). Criei uma aplicação (na verdade está sendo criada ainda) que é uma espécie de Twitter + Instagram (em menor escala, naturalmente). Você manda uma foto, com comentário. Você pode seguir pessoas, e pessoas podem te seguir. Você pode avaliar fotos como boa ou ruim. Tudo é público.&lt;br /&gt;
&lt;br /&gt;
A aplicação é 0.1, ok? Mas está &lt;a href="https://github.com/felipenasc/GPerform"&gt;disponível no GitHub&lt;/a&gt;. Seja bem vindo para contribuir se quiser (estou dando meus primeiros passos com o Git, então paciência comigo....).&lt;br /&gt;
&lt;br /&gt;
A primeira coisa a fazer foi criar o modelo de dados, e aí já começam as dicas para uma melhor performance da sua aplicação: Não usar Collections para as relações hasMany. E mais que isso: acabar com as relações diretas entre duas classes para os casos many-to-many e one-to-many. Pois é, parece estranho. &amp;nbsp;Mas tem fundamento.&lt;br /&gt;
&lt;br /&gt;
Para esclarecer o fundamento, vou dar um pequeno exemplo. Imagina:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class ContaCorrente{
    
    String numero
    String agencia
    
    static hasMany = [transacoes: Transacao]
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Transacao{
    
    BigDecimal valor
    
    static belongsTo = [conta: ContaCorrente]
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Imagine que você queira usar as facildades que o Grails dá para gerenciar esta relação one-to-many. Ou seja, você vai querer usar o método conta.addToTransacoes(t) que está disponível para você, claro.&lt;br /&gt;
&lt;br /&gt;
Mas imagine quantas transações tem numa conta corrente al longo de um ano. Se você tiver 30 transações por mês, no ano serão 360. Ou seja, no final do ano, quando o seu sistema for adicionar mais uma transação na conta do usuário, ele irá buscar as 360 transações para montar a collection "conta.transacoes" e só depois irá adicionar a nova transação nesta collection, para aí gravar esta alteração na collection no banco de dados. Se inicialmente você queria fazer apenas um insert, você acaba fazendo um select que retorna 360 itens pra memória (que você não vai usar nenhum deles), um insert da nova transação, e um update da ContaCorrente (pois o GORM atualiza o campo version deste objeto pai).&lt;br /&gt;
&lt;br /&gt;
É ou não é coisa demais, e é muito provável que a performance da aplicação será seriamente afetada?&lt;br /&gt;
&lt;br /&gt;
Para resolver isso, &lt;a href="http://burtbeckwith.com/"&gt;Burt Beckwith&lt;/a&gt; sugere, em uma &lt;a href="http://www.infoq.com/presentations/GORM-Performance"&gt;apresentação na infoQ&lt;/a&gt;, que não se use a relação one-to-many com o hasMany. Que se faça apenas o outro lado da relação, que é o many-to-one. Qual é a perda disso? Você não vai ter o método addToTransacoes(). Mas isso é fácil de resolver. E também não vai ter um atributo "transacoes" que te retorna todas as transacoes da sua conta (você provavelmente não iria usar nunca - nem deveria). (veja um &lt;a href="https://mrpaulwoods.wordpress.com/2011/02/07/implementing-burt-beckwiths-gorm-performance-no-collections/"&gt;post interessante&lt;/a&gt; sobre isso) Por exemplo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class ContaCorrente{    

    String numero
    String agencia
    
    def buscaTransacoesRecentes(int qtde){
        Transacao.executeQuery('from Transacao t where t.conta = :c order by t.dateCreated desc', [c:this], [max:qtde])
    }

    def adicionaTransacao(BigDecimal valor){
        new Transacao(valor:valor, conta:this).save()
    }

}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Transacao{
    
    BigDecimal valor
    Date dateCreated

    ContaCorrente conta

}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Pronto. Simples assim. Você agora conseguiu ter&amp;nbsp;apenas&amp;nbsp;o seu único insert que você queria. Sem selects desnecessários, e sem update desnecessário (não estou contando com o select da ContaCorrente, mas tbem não contei com ele ali em cima). Veja que eu criei métodos na classe ContaCorrente para adicionar uma nova transação e para buscar as mais recentes.&lt;br /&gt;
&lt;br /&gt;
Acho que tá bom por hoje né? Terei que escrever outros posts para contar tudo. Tem ainda o uso de diversos plugins, como por exemplo: springcache, spring-events, resources, cache-headers, cached-resources, zipped-resources, e por aí vai. Já já eu volto.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-7167657694101511974?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/smSAPWSEo2zWbhL8QtmgbQj6gw0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/smSAPWSEo2zWbhL8QtmgbQj6gw0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/smSAPWSEo2zWbhL8QtmgbQj6gw0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/smSAPWSEo2zWbhL8QtmgbQj6gw0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/wBnKtMi7s58" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/7167657694101511974/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=7167657694101511974" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/7167657694101511974?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/7167657694101511974?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/wBnKtMi7s58/gperform-uma-aplicacao-de-exemplo-com.html" title="GPerform: uma aplicação de exemplo com PERFORMANCE na alma" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2011/07/gperform-uma-aplicacao-de-exemplo-com.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAGQXo7cCp7ImA9Wx9TEUQ.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-2945863270888408931</id><published>2010-11-19T17:08:00.000-02:00</published><updated>2010-11-19T17:08:40.408-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-19T17:08:40.408-02:00</app:edited><title>Dicas e passo a passo para iniciar com o Amazon Web Services - AWS (em inglês)</title><content type="html">Estou começando a fazer uns testes com os servidores da Amazon, o Amazon Web Services. Aí descobri umas dicas e passo a passo com boas informações:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://bristle.com/Tips/CloudComputing.htm#aws"&gt;http://bristle.com/Tips/CloudComputing.htm#aws&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Abcs a todos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-2945863270888408931?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TUOikTX3TJ3jckxOckk8XmSUOVQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TUOikTX3TJ3jckxOckk8XmSUOVQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TUOikTX3TJ3jckxOckk8XmSUOVQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TUOikTX3TJ3jckxOckk8XmSUOVQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/Bl29jhggBlo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/2945863270888408931/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=2945863270888408931" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/2945863270888408931?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/2945863270888408931?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/Bl29jhggBlo/dicas-e-passo-passo-para-iniciar-com-o.html" title="Dicas e passo a passo para iniciar com o Amazon Web Services - AWS (em inglês)" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/11/dicas-e-passo-passo-para-iniciar-com-o.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkICQXszfip7ImA9Wx9TEU0.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-6853918095434623837</id><published>2010-11-18T15:16:00.000-02:00</published><updated>2010-11-18T15:16:00.586-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-18T15:16:00.586-02:00</app:edited><title>Grails: problema com uso de herança nos Controllers</title><content type="html">Ao fazer uma revisão na performance de uma aplicação Grails, acabei me deparando com um problema muito esquisito. &lt;br /&gt;
&lt;br /&gt;
Nesta aplicação, há alguns controllers que possuíam alguns métodos comuns. Então, nada mais natural do que criar um controller pai, abstrato, do qual os demais controllers herdavam para poderem utilizar os métodos comuns. Não eram actions, eram métodos simples.&lt;br /&gt;
&lt;br /&gt;
Percebi, então, que os alguns dos métodos do controller pai eram executados mesmo sem serem chamados. É isso mesmo. Não me perguntem como, mas estava acontecendo. Será que havia algum erro da minha aplicação. Pode ser que sim, mas....&lt;br /&gt;
&lt;br /&gt;
Então criei uma action de teste simples no meu controller filho:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class FilhoController extends PaiController {
    def teste = {
     render "ola"
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Ou seja, nada deveria ser executado além de aparecer um "ola" na tela. Mas o problema é que ao configurar o Grails para fazer o log das queries SQL (no DataSource.groovy coloquei loggingSql = true), quando eu acessava esta action http://localhost:8080/app/filho/teste , um monte de SQL aparecia no console. Eram as queries que existiam nos métodos do PaiController. E aí? Fiquei horas, literalmente, tentando entender. Achei que fosse algo em algum Filter, algo no BootStrap, no resources.groovy, sei lá aonde. Mas não imaginei que era a herança que estava causando isso.&lt;br /&gt;
&lt;br /&gt;
Bom, resolvi arriscar e acabei com a herança. Matei o "extends PaiController". Aí criei uma classe groovy comum contendo todos os métodos da antiga classe PaiController. Problema resolvido. Acredita nisso? Nem eu. Mas........&lt;br /&gt;
&lt;br /&gt;
Só mais um detalhe: nesta classe groovy, que chamei de WebHelper, eu precisava de session, de um service, do request, da taglib para poder usar o método message(), e por aí vai. Então, criei esta classe com.minhaapp.web.WebHelper na pasta src/groovy, e configurei o resources.groovy para poder injetar nestas minha classe tudo que eu precisava, da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;beans = {
    
  webHelper(com.minhaapp.web.WebHelper) { bean -&amp;gt;
    bean.scope = 'prototype' // aqui pode ser singleton se vc preferir
    bean.autowire = 'byName'
    applicationTagLib = ref('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
  }

}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
E a classe WebHelper então ficou assim:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;package com.minhaapp.web


import org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib
import org.springframework.web.servlet.support.RequestContextUtils
import org.springframework.web.context.request.RequestContextHolder

public class WebHelper {
    def grailsApplication
    def meuService
    def applicationTagLib
    
    def teste(){
        println grailsApplication.class
        println RequestContextHolder.currentRequestAttributes().session.class
        println applicationTagLib.class
        println meuService.class
    }
    
}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Abcs a todos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-6853918095434623837?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/S8vxbLSEfu1HHsK4vgk17mKmmLg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/S8vxbLSEfu1HHsK4vgk17mKmmLg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/S8vxbLSEfu1HHsK4vgk17mKmmLg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/S8vxbLSEfu1HHsK4vgk17mKmmLg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/tAead0UAXSE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/6853918095434623837/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=6853918095434623837" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/6853918095434623837?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/6853918095434623837?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/tAead0UAXSE/grails-problema-com-uso-de-heranca-nos.html" title="Grails: problema com uso de herança nos Controllers" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/11/grails-problema-com-uso-de-heranca-nos.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIDQHk-fip7ImA9Wx5aE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-3787562031885455670</id><published>2010-11-10T11:59:00.000-02:00</published><updated>2010-11-10T11:59:31.756-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-10T11:59:31.756-02:00</app:edited><title>Reportagens sobre Grails na revista Wide</title><content type="html">Pessoal&lt;br /&gt;
&lt;br /&gt;
a &lt;a href="http://www.revistawide.com.br/"&gt;revista Wide&lt;/a&gt; deste mês tem duas reportagens boas sobre o Grails. Uma delas é comigo mesmo, onde falo a respeito do uso do Grails no caso do &lt;a href="http://www.noiteuniversitaria.com.br/"&gt;NoiteUniversitaria.com.br&lt;/a&gt; ( e comento um pouco sobre o caso do &lt;a href="http://www.manubia.com.br/"&gt;Manubia&lt;/a&gt;&amp;nbsp;).&lt;br /&gt;
A outra é uma entrevista com o Graeme Rocher, desenvolvedor líder do projeto Grails.&lt;br /&gt;
&lt;br /&gt;
Interessante a revista. (não estou ganhando $$ com a revista não hein)....&lt;br /&gt;
&lt;br /&gt;
Abcs a todos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-3787562031885455670?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JzzbJLottD1BBtAd8F-CYyViIhw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JzzbJLottD1BBtAd8F-CYyViIhw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JzzbJLottD1BBtAd8F-CYyViIhw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JzzbJLottD1BBtAd8F-CYyViIhw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/SeWvqiXbmLo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/3787562031885455670/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=3787562031885455670" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3787562031885455670?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3787562031885455670?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/SeWvqiXbmLo/reportagens-sobre-grails-na-revista.html" title="Reportagens sobre Grails na revista Wide" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/11/reportagens-sobre-grails-na-revista.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAHRHY7eCp7ImA9WxFbE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-7150741679405925561</id><published>2010-07-06T01:27:00.002-03:00</published><updated>2010-07-06T01:32:15.800-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-06T01:32:15.800-03:00</app:edited><title>Grails e Roo: screencast de comparação ao gerar uma mesma aplicação</title><content type="html">Olá pessoal,&lt;br /&gt;
&lt;br /&gt;
venho dando uma olhada no &lt;a href="http://www.springsource.org/roo"&gt;Spring Roo&lt;/a&gt;. Esta ferramenta é bastante útil para quem desenvolve com Java. Ou seja, não apenas na plataforma Java, como o Grails, mas apenas com a linguagem Java. Se você tiver esta condição de ter que desenvolver com Java, vale a pena conhecer o Roo.&lt;br /&gt;
&lt;br /&gt;
Quero fazer uma comparação entre o desenvolvimento com Grails e Roo. Não é uma comparação justa, pois o Grails é um framework é em Groovy, e outro é uma ferramenta de geração que produz uma aplicação 99% Java (usando frameworks conhecidos com Spring, Hibernate, Log4j, etc). Porque então estou comparando? No fundo quero fazer um benchmark de performance entre as duas aplicações. Mas até chegar lá, vou mostrar desde o início, apresentando a geração da aplicação através dos comandos de geração das duas ferramentas.&lt;br /&gt;
&lt;br /&gt;
Para isso, então, escolhi uma aplicação bem simples, e o passo a passo a ser seguido tanto com Grails quanto com o Roo é:&lt;br /&gt;
&lt;br /&gt;
- Criar projeto&lt;br /&gt;
- Configurar persistência com Hibernate e Hypersonic DB in Memory (só Roo precisa deste passo)&lt;br /&gt;
- Criar entidade Project&lt;br /&gt;
- Criar atributos com validação: name, beginDate, active&lt;br /&gt;
- Criar 2 finders com os atributos active e beginDate (só Roo precisa deste passo)&lt;br /&gt;
- Configurar Log (só Roo precisa deste passo)&lt;br /&gt;
- Configurar arquivos Eclipse (só Roo precisa deste passo)&lt;br /&gt;
- Gerar Controller e views&lt;br /&gt;
- Executar a aplicação.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aí vão os vídeos.&amp;nbsp; Perdoem-me a pouca empolgação do vídeo 1, mas é que já era 1h da manhã e estava todo mundo dormindo lá em casa..... não podia fazer muito barulho pra não acordar minha filha&amp;nbsp;&amp;nbsp; :-)&lt;br /&gt;
Abraços a todos.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Vídeo 1: Gerando com Roo&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;object height="405" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ZeDEU1HMxhQ&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;border=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ZeDEU1HMxhQ&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="405"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Vídeo 2: &lt;/span&gt;&lt;span style="font-size: large;"&gt;Gerando com &lt;/span&gt;&lt;span style="font-size: large;"&gt;Grails&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;object height="405" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/NQ1A-y6wqus&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;border=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/NQ1A-y6wqus&amp;amp;hl=en_US&amp;amp;fs=1?rel=0&amp;amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="500" height="405"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-7150741679405925561?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Nq7h6BWljLJRFEHamFJamQ-IA6k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Nq7h6BWljLJRFEHamFJamQ-IA6k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Nq7h6BWljLJRFEHamFJamQ-IA6k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Nq7h6BWljLJRFEHamFJamQ-IA6k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/hTffbJSPxZs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/7150741679405925561/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=7150741679405925561" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/7150741679405925561?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/7150741679405925561?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/hTffbJSPxZs/grails-e-roo-screencast-de-comparacao.html" title="Grails e Roo: screencast de comparação ao gerar uma mesma aplicação" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/07/grails-e-roo-screencast-de-comparacao.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04FR3wycCp7ImA9WxFbEU8.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-5910139632116456672</id><published>2010-07-02T22:51:00.000-03:00</published><updated>2010-07-02T22:51:56.298-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-02T22:51:56.298-03:00</app:edited><title>Tudo sobre Grails GORM e as relações One-To-Many, Many-To-One e Many-To-Many</title><content type="html">Esta é mais uma dica rápida. Você já se pegou com dúvidas de como funcionam as relações entre entidades no Grails? Como fazer o cascade corretamente? como se livrar daquela exception que não insiste em ser lançada?&lt;br /&gt;
Pois é. O grails possui o mapeamento Objeto Relacional baseado no Hibernate, mas cria uma série de facilidades nas entidades para podermos lidar de forma fácil com as relações entre objetos.&lt;br /&gt;
GORM significa Grails' Object Relational Mappging. E as relações a que me refiro são One-To-Many, Many-To-One, e Many-To-Many.&lt;br /&gt;
Há um excelente resumo escrito por Peter Ledbrook no blog da SpringSource.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://blog.springsource.com/2010/07/02/gorm-gotchas-part-2/"&gt;http://blog.springsource.com/2010/07/02/gorm-gotchas-part-2/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Vale MUITO a pena a leitura. Este link acima é a Parte 2 de uma série sobre o GORM. Caso queira (vale a pena tbem) leia a &lt;a href="http://blog.springsource.com/2010/06/23/gorm-gotchas-part-1/"&gt;Parte 1&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Abcs&lt;br /&gt;
Felipe&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-5910139632116456672?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Se3Huw-9GZ0FowWK6zerY_lmhkM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Se3Huw-9GZ0FowWK6zerY_lmhkM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Se3Huw-9GZ0FowWK6zerY_lmhkM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Se3Huw-9GZ0FowWK6zerY_lmhkM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/wdhM17po0ic" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/5910139632116456672/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=5910139632116456672" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/5910139632116456672?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/5910139632116456672?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/wdhM17po0ic/tudo-sobre-grails-gorm-e-as-relacoes.html" title="Tudo sobre Grails GORM e as relações One-To-Many, Many-To-One e Many-To-Many" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/07/tudo-sobre-grails-gorm-e-as-relacoes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4HRHcycSp7ImA9WxFVF04.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-6090373466324448748</id><published>2010-06-16T22:23:00.001-03:00</published><updated>2010-06-16T22:25:35.999-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-16T22:25:35.999-03:00</app:edited><title>Grails TagLib em qualquer classe</title><content type="html">Uma dica rápida: se você precisar ter acesso a alguma Taglib do Grails dentro de alguma classe que não tem injetada a taglib, olhe só essa. Neste exemplo abaixo, digamos que você precise de uma mensagem internacionalizada dentro da classe BootStrap:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;def grailsTags = grailsApplication.mainContext.getBean( 'org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib' )
String msg = grailsTags.message(code:'exemplo.de.mensagem')
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Abcs&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-6090373466324448748?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zpHJh7GDcxZdA9-Qo0lGyHsvQ44/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zpHJh7GDcxZdA9-Qo0lGyHsvQ44/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zpHJh7GDcxZdA9-Qo0lGyHsvQ44/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zpHJh7GDcxZdA9-Qo0lGyHsvQ44/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/zY5qdfplNsQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/6090373466324448748/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=6090373466324448748" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/6090373466324448748?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/6090373466324448748?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/zY5qdfplNsQ/grails-taglib-em-qualquer-classe.html" title="Grails TagLib em qualquer classe" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/06/grails-taglib-em-qualquer-classe.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEENRH4yeCp7ImA9WxBaFE4.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-147657860335757783</id><published>2010-03-24T10:18:00.000-03:00</published><updated>2010-03-24T10:18:15.090-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-24T10:18:15.090-03:00</app:edited><title>Escalabilidade de aplicações Web: futuro vs presente = Cassandra vs Mysql+memcached</title><content type="html">Muito interessante o &lt;a href="http://about.digg.com/blog/looking-future-cassandra"&gt;post do Digg&lt;/a&gt; que fala sobre as tecnologias, estratégias e problemas que o Digg (assim como outras aplicações gigantes na Web) vive ao redor do tema escalabilidade.&lt;br /&gt;
&lt;br /&gt;
Quando se trata de aplicações web populares como Digg, Twitter e Facebook, escalabilidade se torna um desafio e tanto, e manter a aplicação com redundância, performance e consistência gera um custo grande de manutenção e monitoramento.&lt;br /&gt;
&lt;br /&gt;
Até muito recentemente, ou até hoje mesmo, muitos desses sites usam a solução de Mysql + memcached para poderem suportar o nível de escalabilidade necessário. Por exemplo, até o fim de 2008, o &lt;a href="http://www.facebook.com/note.php?note_id=39391378919"&gt;Facebook possuía mais de 800 servidores de memcached&lt;/a&gt;&amp;nbsp;para poder servir mais de 28 terabytes de cache. É mole? &lt;b&gt;28 Tera de cache! &lt;/b&gt;E isso, só para poder servir a leitura de dados em cache. &amp;nbsp;Na hora de escrever os dados, aí usa-se uma solução de Mysql configurado com Master-Slave, e muitas vezes com particionamento vertical.&lt;br /&gt;
&lt;br /&gt;
O fato atualmente é: esta solução não está mais dando conta do recado. Alguns desses sites estão saindo da solução com Mysql+memcached e estão indo para o mundo não SQL. E o que muitos deles estão adotando é o &lt;a href="http://cassandra.apache.org/"&gt;Cassandra&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Cassandra é um banco de dados distribuído, altamente escalável, baseado no conceito de &lt;a href="http://labs.google.com/papers/bigtable.html"&gt;BigTable&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
É isso. E vem por aí uma nova era para as soluções de aplicações web de alto volume.&lt;br /&gt;
Vale a leitura do post do Digg.&lt;br /&gt;
Abcs&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-147657860335757783?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LAoV4oATdmzahpzonVQE7HjvcE4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LAoV4oATdmzahpzonVQE7HjvcE4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LAoV4oATdmzahpzonVQE7HjvcE4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LAoV4oATdmzahpzonVQE7HjvcE4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/i3Au3opzyAg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/147657860335757783/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=147657860335757783" title="3 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/147657860335757783?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/147657860335757783?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/i3Au3opzyAg/escalabilidade-de-aplicacoes-web-futuro.html" title="Escalabilidade de aplicações Web: futuro vs presente = Cassandra vs Mysql+memcached" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/03/escalabilidade-de-aplicacoes-web-futuro.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIGQXs6fip7ImA9WxBaE00.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-4890746680279334568</id><published>2010-03-22T21:17:00.001-03:00</published><updated>2010-03-22T21:35:20.516-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-22T21:35:20.516-03:00</app:edited><title>GWT + Grails = Rock n Roll: Parte 2 - Separados e falando com RequestBuiler e JSON</title><content type="html">Este post é a Parte 2 da sequência de posts sobre o tema GWT + Grails = Rock n Roll. Você pode ver a &lt;a href="http://felipenasc.blogspot.com/2010/02/grails-gwt-rock-n-roll-parte-1.html"&gt;Parte 1 aqui&lt;/a&gt;. Nesta primeira mostrei como criar uma aplicação baseada em GWT e Grails. Para juntar os dois, usei o plugin Grails-Gwt. &lt;br /&gt;
&lt;br /&gt;
Neste post de hoje, depois de alguns dias lendo sobre GWT, fazendo testes e brincando com a aplicação criada no post da Parte 1, resolvi tentar também desenvolver outra aplicação com GWT + Grails mas desta vez sem usar o plugin. Desta forma, poderia eu mesmo decidir se prefiro com ou sem o Plugin. Este post, então, mostrará como criar uma solução composta de duas aplicações isoladas, uma GWT e outra Grails, que se falam via troca de dados usando JSON.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Separando Grails e GWT em duas aplicações distintas&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Como descrevi na Parte 1, não usar o plugin e ter duas aplicações distintas (uma GWT e outra Grails) significa ter que lidar com a Same Origin Policy (SOP) em tempo de desenvolvimento. Em produção simplesmente pode-se dar um jeito de levar os arquivos Html, Css e Javascript gerados pelo GWT para o propeto grails (em último caso, basta copiar e colar de um lado para o outro). Mas em desenvolvimento é preciso lidar com SOP de uma maneira mais produtiva do que ter que ficar copiando e colando de um lado para outro. A maneira mais simples que encontrei foi usando uma &lt;a href="http://edwardstx.net/wiki/attach/HttpProxyServlet/ProxyServlet.java"&gt;ProxyServlet&lt;/a&gt;, originalmente criada por Jason Edward, e depois evoluída por Matt Raible. O código fonte desta classe eu peguei no projeto Grails OAuth Plugin criado pelo M Raible. É simples de usar, e resolve o problema facilmente. O que ela faz neste nosso contexto é: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;a aplicações GWT no cliente faz uma requisição para o servidor; &lt;/li&gt;
&lt;li&gt;a aplicações GWT no servidor recebe esta requisição e repassa para a aplicação Grails&lt;/li&gt;
&lt;li&gt;a aplicação Grails recebe esta requisição e responde JSON&lt;/li&gt;
&lt;li&gt;a aplicação GWT recebe esta resposta JSON e repassa para o cliente GWT&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Desta forma não precisamos nos preocupar com SOP.&lt;br /&gt;
&lt;br /&gt;
O que se ganha em fazer isso? Para que, afinal, quero ter duas aplicações separadas (uma GWT e outra Grails). Bom, isso acaba sendo uma decisão pessoal de cada um, ok? Mas para mim, comecei a achar mais interessante seguir os padrões de cada projeto. Um projeto GWT, segundo as recomendações, deve ser organizado de uma maneira, com determinada árvore de diretórios, etc. Pode não ser seguido, mas é um padrão recomendado. Então, porque não seguir e falar a mesma lingua em chats, fóruns de discussão, novos desenvolvedores na equipe, etc?&lt;br /&gt;
&lt;br /&gt;
Além disso, separar os dois projetos provoca uma reflexão conceitual interessante sobre arquitetura de aplicações ricas para a web (RIA - Rich Internet Applications). Ao separar, você está literalmente, fisicamente, implementando a arquitetura SOFEA (Service Oriented Front-End Architecture). SOFEA foi muito bem apresentado no artigo &lt;a href="http://wisdomofganesh.blogspot.com/2007/10/life-above-service-tier.html"&gt;Life Above the Service Tier&lt;/a&gt;&amp;nbsp;(vale a leitura. Este pessoa hoje em dia criou um grupo sobre este assunto e tem um site em: &lt;a href="http://www.thinserverarchitecture.com/"&gt;ThinServerArchitecture.com&lt;/a&gt; ).&lt;br /&gt;
&lt;br /&gt;
Numa arquiteturea SOFEA, toda a lógica de interface com usuário está sendo rodada no cliente, no nosso caso, no browser. Aqui então, as camadas View e Contoller da aplicação terão um projeto só pra elas (o projeto GWT). Ou seja, o desacoplamento é total. Você simplesmente desacopla o máximo que pode o tal do Front-End. Isso é interessante na minha opinião, pois aí a sua aplicação servidora, que roda no servidor, ela acaba por ter a responsabilidade apenas de prover serviços para a aplicação de Front-End (User Interface - UI). Parece até que estamos voltando para o conceito Cliente x Servidor, e de certa forma, estamos sim, mas um pouco diferente, pois é um Thin Client, onde apenas as regras de interface e controle de fluxo de navegação estão no cliente. Todas as demais regras de negócio, estão e devem estar no servidor.&lt;br /&gt;
&lt;br /&gt;
Outras duas justificativas para esta separação em duas aplicações são:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Pode ficar mais simples equipes diferentes trabalharem cada uma em um projeto diferente&lt;/li&gt;
&lt;li&gt;Cada projeto pode ser versionado independentemente&lt;/li&gt;
&lt;/ul&gt;Bom, depois de todas essas justificativas, o fato é: criei uma nova aplicação que é composta por um projeto GWT responsável pelo Front-End, e por outro projeto Grails responsável pelo Back-End (provendo serviços, lembra SOA?). Veja que as coisas começam até a ficar mais coesas e desacopladas. Interessante resultado....&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Comunicação entre GWT e Grails com JSON&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Para a comunicação entre o Front-End e o Back-End, escolhi usar JSON. A aplicação &lt;a href="http://grails.org/doc/latest/ref/Controllers/render.html"&gt;grails pode facilmente gerar uma resposta JSON&lt;/a&gt;, enquanto que a aplicação &lt;a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/json/client/JSONParser.html"&gt;GWT pode facilmente consumir JSON&lt;/a&gt;. Então, sendo o JSON um formato leve para troca de dados, e sendo ele facilmente servido e consumido pelo Grails e GWT respectivamente, acho que JSON é uma boa escolha. Mas, se você preferir trabalhar com XML, ou outro formato proprietário, a decisão é sua.&lt;br /&gt;
&lt;br /&gt;
Portanto, para criarmos esta nova aplicação, basta criar um novo projeto GWT, e outro Grails. &lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Aplicação Front-End (GWT)&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Eu estou usando o Eclipse com o plugin do GWT, portanto, para criar um novo projeto basta clicar na opção de criar novo projeto GWT do Eclipse. Criei este projeto GWT chamado rockgwtfront, com o pacote com.rockgwt.front&lt;br /&gt;
&lt;br /&gt;
O wizard do Eclipse já cria uma classe EntryPoint, o arquivo XML de configuração do Module, e também cria um Serviço RPC de exemplo. Mas não precisaremos deste serviço para este exemplo, portanto, pode apagar o pacote com.rockgwt.front.server e o pacote com.rockgwt.front.shared, e também pode apagar os arquivos GreetingService.java e GreetingServiceAsync.java do pacote com.rockgwt.front.client.&amp;nbsp;Depois altere a classe&amp;nbsp;Rockgwtfront.java para não usar mais este Serviço RPC. No final das contas, fiquei com a classe de EntryPoint abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border-bottom: #999999 1px dashed; border-left: #999999 1px dashed; border-right: #999999 1px dashed; border-top: #999999 1px dashed; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; padding-top: 5px; width: 100%;"&gt;&lt;code&gt;package com.rockgwt.front.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;

public class Rockgwtfront implements EntryPoint {

    public void onModuleLoad() {
        final Button sendButton = new Button("Get Hendrix songs");
        final FlexTable songsTable = new FlexTable();

        // We can add style names to widgets
        sendButton.addStyleName("sendButton");
        
        sendButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                String hendrixSongsServiceUrl = GWT.getHostPageBaseURL();
                if(!GWT.getHostPageBaseURL().contains("rockgwt"))
                    hendrixSongsServiceUrl += "rockgwt/";
                    
                hendrixSongsServiceUrl += "hendrix/songs";
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, hendrixSongsServiceUrl);
                builder.setTimeoutMillis(10000);
                builder.setCallback(new RequestCallback() {
                    
                    @Override
                    public void onResponseReceived(Request request, Response response) {
                        if (response.getStatusCode() == 200) {
                            
                            JSONValue v = JSONParser.parse(response.getText());
                            JSONArray songs = v.isArray();
                            if(songs != null){
                                updateBacklogItemsTable(songsTable, songs);
                            }
                            else{
                                throw new JSONException("O retorno nao veio como um objeto de Projeto"); 
                            }
                        } else {
                            onError(request, new RequestException(response.getText()));
                        }
                    }
                    
                    @Override
                    public void onError(Request request, Throwable exception) {
                        Window.alert(exception.getLocalizedMessage());
                    }
                });
                try {
                    builder.send();
                } catch (RequestException e) {
                    Window.alert(e.getLocalizedMessage());
                }
            }
        });

        RootPanel.get("sendButtonContainer").add(sendButton);
        RootPanel.get("songsTableContainer").add(songsTable);

    }
    
    private void updateBacklogItemsTable(FlexTable songsTable, JSONArray songs) {
        songsTable.clear();
        for (int i=0; i&amp;lt;songs.size(); i++) {
            JSONObject item = songs.get(i).isObject();
            songsTable.setWidget(i, 0, new Label(item.get("name").isString().stringValue()));
            songsTable.setWidget(i, 1, new Label(item.get("album").isString().stringValue()));
        }
                    
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Veja que a classe acima utiliza um RequestBuilder para realizar a requisição no servidor. Este RequestBuilder é uma classe do GWT que pode ser usada para fazer requisições remotas. Com ela, as requisições são sempre assíncronas, SEMPRE. Veja que passei um objeto Callback que será chamado quando esta requisição voltar do servidor. Assim, neste callback posso fazer o que for preciso com a resposta recebida. Neste caso, devo fazer o parse do JSON para poder trabalhar com os dados retornados. No fim de tudo, pego esses dados e os apresento numa tabela, só isso. &lt;br /&gt;
&lt;br /&gt;
Veja que a aplicação GWT espera um retorno JSON no seguinte formato:&lt;br /&gt;
[{"name":"Hey Joe", "album":"Are You Experienced"},&lt;br /&gt;
{"name":"Bold as Love", "album":"Axis: Bold as Love"}]&lt;br /&gt;
&lt;br /&gt;
Portanto, é preciso que a aplicação Grails retorne um JSON exatamente neste formato acima.&lt;br /&gt;
&lt;br /&gt;
É preciso adicionar ao ~/rockgwtfront/war/WEB-INF/lib&amp;nbsp; do projeto os JARs necessários para a ProxyServlet citada acima. Portanto, adicione commons-fileupload-1.2.1.jar, httpclient-4.0.1.jar, e httpmime-4.0.1.jar ao lib. Crie a classe ProxyServlet. Você pode baixar o OAuth 1.3 e pegar o ProxyServlet de lá. Em seguida, é preciso configurar o web.xml para que ele saiba que o ProxyServlet existe. Vou mapear este proxyServlet para ele ser chamado para toda requisição que tenha o padrão /rockgwtback/*. Veja abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;web-app&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;servlet&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;servlet-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;RockServlet&lt;span style="color: #c40000;"&gt;&lt;/span&gt;servlet-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;servlet-class&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;com.rockgwt.front.servlet.ProxyServlet&lt;span style="color: #c40000;"&gt;&lt;/span&gt;servlet-class&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;init-param&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;param-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;proxyHost&lt;span style="color: #c40000;"&gt;&lt;/span&gt;param-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;param-value&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;localhost&lt;span style="color: #c40000;"&gt;&lt;/span&gt;param-value&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&lt;/span&gt;init-param&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;init-param&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;param-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;proxyPort&lt;span style="color: #c40000;"&gt;&lt;/span&gt;param-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;param-value&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #1700ff;"&gt;8080&lt;/span&gt;&lt;span style="color: #c40000;"&gt;&lt;/span&gt;param-value&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&lt;/span&gt;init-param&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;init-param&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;param-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;secure&lt;span style="color: #c40000;"&gt;&lt;/span&gt;param-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;param-value&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;false&lt;span style="color: #c40000;"&gt;&lt;/span&gt;param-value&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&lt;/span&gt;init-param&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&lt;/span&gt;servlet&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 15.0px;"&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #c40000;"&gt;&lt;span class="Apple-style-span" style="color: black;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&amp;lt;&lt;/span&gt;servlet-mapping&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;servlet-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;RockServlet&lt;span style="color: #c40000;"&gt;&lt;/span&gt;servlet-name&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;url-pattern&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;/rockgwt/*&lt;span style="color: #c40000;"&gt;&lt;/span&gt;url-pattern&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&lt;/span&gt;servlet-mapping&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 15.0px;"&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style="color: #00852e; font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;welcome-file-list&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color: #c40000;"&gt;&amp;lt;&lt;/span&gt;welcome-file&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;Rockgwtfront.html&lt;span style="color: #c40000;"&gt;&lt;/span&gt;welcome-file&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &lt;span style="color: #c40000;"&gt;&lt;/span&gt;welcome-file-list&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 15.0px;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace, 'Lucida Console', Monaco, fixed, monospace; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 12px; line-height: 14px;"&gt;&lt;span class="Apple-style-span" style="font-family: Monaco, 'Lucida Console', Monaco, fixed, monospace; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 11px; line-height: normal;"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font: 11.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #c40000;"&gt;&lt;/span&gt;web-app&lt;span style="color: #c40000;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Veja que o servlet-mapping mostra como deverá ser a url a ser chamada pelo cliente GWT para o servidor Grails. ( /rockgwtback/* ).&lt;br /&gt;
&lt;strong&gt;Aplicação Back-End (Grails)&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Para o projeto Grails, ou você cria normalmente por linha de comando, ou pode até criar pelo Eclipse mesmo se estiver usando o STS (SpringSource Tool Suite). Criei este projeto Grails chamando-o de rockgwtback. Para este projeto, criei um controller chamado HendrixController que possui a action "musics". Esta action retorna uma lista de músicas do Hendrix. Veja abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;package com.rockgwt.back.controller

class HendrixController {
    def index = { }

    def songs = {
        println "chegou"
        render(builder: 'json') {
                songs = array {
                       song name: '1) Hey Joe', album: 'Are You Experienced'
                       song name: '2) Bold as Love', album: 'Axis: Bold as Love'
                   }
        }
    }

}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Alterei também o nome da aplicação dentro do application.properties, colocando app.name=rockgwt, pois foi assim que eu coloquei a URL da requisição lá em cima, na aplicação GWT, e também no servlet-mappging do web.xml&lt;br /&gt;
&lt;br /&gt;
É isso!&lt;br /&gt;
&lt;br /&gt;
Assim, temos um sistema rodando com Grails e GWT, independentes um do outro, mas juntos formando a nossa aplicação. Faltaria aqui neste exemplo uma forma de juntar as duas aplicações para produção. Provavelmente faria isso com o Maven. Em produção, então, seria uma única aplicação mesmo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-4890746680279334568?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ie133NbR7crhrVJFHNTPYO7q7QY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ie133NbR7crhrVJFHNTPYO7q7QY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ie133NbR7crhrVJFHNTPYO7q7QY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ie133NbR7crhrVJFHNTPYO7q7QY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/j3JttQuETVg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/4890746680279334568/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=4890746680279334568" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4890746680279334568?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4890746680279334568?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/j3JttQuETVg/gwt-grails-rock-n-roll-parte-2.html" title="GWT + Grails = Rock n Roll: Parte 2 - Separados e falando com RequestBuiler e JSON" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/03/gwt-grails-rock-n-roll-parte-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04GRXk6fip7ImA9WxBbEEQ.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-7955608269137749916</id><published>2010-03-07T22:48:00.006-03:00</published><updated>2010-03-08T21:52:04.716-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-08T21:52:04.716-03:00</app:edited><title>Grails + GWT = Rock n Roll: Parte 1 - Desbravando um novo mundo</title><content type="html">Meus amigos leitores (quantos devem ser estes leitores? deixe uma mensagem dizendo que vc é meu leitor! rs...) ... Bem vindos ao maravilhoso mundo do Rock n Roll. As bandas de rock muitas vezes são mal vistas por pessoas mais tradicionais. Outras vezes são veneradas por jovens rebeldes. Não importa. As boas bandas no final das contas só fazem uma coisa: dão um show de Rock n Roll. Mas o que é isso afinal? Sem dúvida a música é o principal produto desta fábrica rebelde. Por trás de pessoas tatuadas, cheias de brincos e roupa rasgada, por vezes alcoólatras e drogadas, bem no fundo há músicos que juntos ( e aqui está o mais importante: JUNTOS) conseguem tocar almas sedentas de Rock puro e simples. Já ouviu um &lt;a href="http://skynyrd.com/v/CkTQUtx818w,lynyrd-skynyrdfree-birdbbc-1975"&gt;bom Lynyrd Skynyrd&lt;/a&gt; com suas 3 guitarras, piano, batera, etc? É brincadeira o que esses caras tinham de musicalidade. Juntos eles deixam os fãs de rock embasbacados até hoje em dia.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Depois desta introdução metafórica, vou iniciar hoje uma série de posts a respeito de GWT e Grails, duas tecnologias que juntas, para mim, estão despontando como a maior banda de Rock dos últimos tempos. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sobre o Grails todos sabem que eu acho que é simplesmente o melhor framework para desenvolvimento web na plataforma java (pelo menos daqueles que eu conheço).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sobre o GWT (Google Web Toolkit), eu sou um mero iniciante, ou melhor, curioso. Para ser sincero, tenho ficado um pouco cansado de lidar diretamente com HTML, CSS e Javascript, principalmente com a montanha de Javascript que se lida ao desenvolver aplicações AJAX. Mesmo usando bibliotecas como jQuery, ou Prototype, mesmo assim, é muito Javascript para se lidar. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Por conta disso (e outros motivos), acho que o GWT pode ser de grande ajuda, de grande ajuda MESMO. Um dos grandes motivos também é a crença que eu estou ficando de que o GWT pode ajudar muito a se ter uma arquitetura decente também na camada View, e não apenas no model, no controller, na DAO, etc. Se formos olhando uma arquitetura de uma aplicação Grails  tradicional de baixo para cima, podemos ver que:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;- a DAO está bem resolvida, &lt;/li&gt;&lt;li&gt;- os Serviços estão lá e cumprem seu papel (de controle transacional, por exemplo), &lt;/li&gt;&lt;li&gt;- os Controllers também tem seu papel de fronteira entre o mundo HTTP e nossas regras de negócio, &lt;/li&gt;&lt;li&gt;- mas aí chega na View e facilmente a gente começa a se perder e fazer uma bagunça com HTMLs, CSSs, Styles, Javascript em arquivos .js, Javascript inline, e por aí vai.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Andei estudando um pouco de GWT para entender mais a fundo e estou começando a acreditar que ele pode ser usado para, mais facilmente, arquitetar decentemente a camada View. Por exemplo, pode-se usar um MVP (Model View Presenter) com o GWT. Alguém aí pode dizer que pode-se fazer isso também com o Javascript diretamente. Sim, até pode, mas que o GWT facilita as coisas, ah facilita. Primeiro: É JAVA! Você ganha ferramentas, refactorings, debugging, e muito mais. Ganha também o fato de que o GWT abstrai você de preocupações mundanas, como por exemplo a ofuscação e minimização do Javascript. Ele faz isso pra gente.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Então é isso galera. Vamos começar.... Vou escrever os posts de acordo com a aventura que eu mesmo estou passando. Nunca desenvolvi uma aplicação real com GWT + Grails. Então vamos desenvolver uma juntos. Será pequena, mas vamos nessa!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Entendendo o GWT&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Para começar eu instalei o &lt;a href="http://code.google.com/intl/en/eclipse/docs/download.html"&gt;plugin do GWT para Eclipse&lt;/a&gt;. Baixei também o &lt;a href="http://google-web-toolkit.googlecode.com/files/gwt-2.0.3.zip"&gt;SDK do GWT&lt;/a&gt; (neste momento estou usando a versão 2.0.3 do GWT). A página que uso para download de tudo é essa: &lt;a href="http://code.google.com/intl/en/webtoolkit/download.html"&gt;http://code.google.com/intl/en/webtoolkit/download.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fiz uma pequena experiência com o GWT sozinho, sem o Grails ainda. Para isso, pelo Eclipse eu criei um projeto GWT novo, usando os wizards que o plugin me dá. Ele cria um projeto já sendo executado de dentro do eclipse, tudo bonito. E esse novo projeto já tem uma pequena página de exemplo, com um diálogo modal, uma requisição Ajax e tudo mais. Tudo para você começar a entender o tal do EntryPoint, entender os Modules, os Widgets e tudo mais.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Portanto, a primeira sugestão que eu dou é essa: brincar com a aplicação nova gerada pelo plugin do Eclipse.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A primeira coisa que percebi com aplicações GWT é que tudo é AJAX. Toda a comunicação com o servidor é assíncrona. Aí, vi que a aplicação gerada pelo plugin do Eclipse tem um "layout" diferente da aplicação Grails. Então surgiu o primeiro problema: como juntar os dois mundos?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Bom, em último caso, o GWT no fundo só serve para gerar os HTMLs e Javascript. Então você pode compilar seu projeto GWT, pegar o HTML e Javascript gerado, e copiar para seu projeto Grails para a parte de web-app. Simples assim! Mas isso não seria nada produtivo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Aí me veio a dúvida: como que as pessoas por aí juntam o Grails com o GWT? Elas fazem um projeto GWT e outro Grails, e depois juntam de alguma forma (com maven por exemplo)? Ou vai tudo num projeto só?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E mais: se forem dois projetos distintos, como lidar com a &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;Same Origin Policy&lt;/a&gt; (SOP)?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E vi que realmente tem gente que usa a primeira forma, e gente que usa a segunda. E tudo gente de respeito por aí. Por exemplo, eu gosto muito o Matt Raible. Desde meus tempos de &lt;a href="http://appfuse.org/"&gt;AppFuse&lt;/a&gt; eu sou fã dele. Aprendi muito com a estrutura que ele montou para o AppFuse. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E não é que o Matt Raible usa a primeira forma? Ele tem dois projetos, um GWT e outro Grails. Aí, em desenvolvimento ele deixa assim mesmo, como duas aplicações web rodando simultaneamente. E simplesmente lida com a SOP através de um Proxy espertinho na aplicação GWT. Este proxy recebe as requisições no servidor do cliente GWT, repassa para a aplicação Grails, recebe de volta a resposta desta, e repassa a mesma para o browser  que tem o cliente GWT. Muito doido, mas funciona. &lt;/div&gt;&lt;div&gt;E em produção ele na verdade junta tudo. Ele tem lá um Maven bem esperto que faz tudo isso pra ele automaticamente, gerando um único WAR que tem a aplicação Grails e o cliente GWT. Aí simplesmente o problema do SOP desaparece.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A outra alternativa é juntar tudo desde o início numa única aplicação. Para facilitar esta tarefa, um tal de &lt;a href="http://www.cacoethes.co.uk/blog/"&gt;Peter Ledbrook&lt;/a&gt; fez o &lt;a href="http://www.grails.org/plugin/gwt"&gt;GWT Plugin para Grails&lt;/a&gt; (não se deixe enganar por esta página. O plugin já está na versão 0.5 e suporta GWT 2.0).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Eu, por enquanto, vou seguir este caminho mais simples (sempre gosto da simplicidade): vou usar o GWT Plugin para Grails. Parece tão simples agora......mas eu fiquei umas duas semanas até chegar a esta conclusão. E até agora queria entender porque o Matt Raible não usa o plugin. Talvez ele seja ruim por algum motivo. Se for isso, eu ainda não descobri.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Então amigo, aí vão os passos iniciais:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;- Instalar o SDK do GWT&lt;/li&gt;&lt;li&gt;- Criar a variável de ambiente GWT_HOME apontando para a raiz do SDK do GWT&lt;/li&gt;&lt;li&gt;- Instalar o Plugin de Eclipse do GWT&lt;/li&gt;&lt;li&gt;- Criar uma aplicação pura e simples GWT usando o plugin do eclipse.&lt;/li&gt;&lt;li&gt;- Abrir a aplicação no browser usando a URL apresentada pelo Eclipse (com o parâmetro gwt.codesrv na URL - este parâmetro é que permite você alterar o código Java e imediatamente dar um refresh no browser e ver sua mudança lá).&lt;/li&gt;&lt;li&gt;- Garantir que o browser instalou o plugin de execução do GWT.&lt;/li&gt;&lt;li&gt;- Executar esta aplicação e brincar um pouco com os &lt;a href="http://code.google.com/intl/pt-BR/webtoolkit/doc/1.6/DevGuideUserInterface.html#DevGuideUnderstandingLayout"&gt;diferentes Layouts de GWT&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Pronto. Agora que você brincou o GWT um pouco, vamos juntar os dois ( GWT + Grails ):&lt;/div&gt;&lt;ul&gt;&lt;li&gt;- Criar uma nova aplicação Grails com o comando &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails create-app rockgwt&lt;/span&gt;&lt;/li&gt;&lt;li&gt;- Vai pra dentro dela ( &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;cd rockgwt&lt;/span&gt; )&lt;/li&gt;&lt;li&gt;- Instalar o plugin GWT do Grails (usando o comando &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails install-plugin gwt&lt;/span&gt; ). Eu estou usando o grails 1.2.x e o plugin 0.5&lt;/li&gt;&lt;li&gt;- Criar um GWT Module com o comando do plugin &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails create-gwt-module com.rockgwt.RockNRoll&lt;/span&gt;&lt;/li&gt;&lt;li&gt;- Criar a página principal do GWT para o seu Module. Eu fiz isso criando um controller do grails e uma Page index.gsp para este controller. Esta page é que irá hospedar o GWT:&lt;/li&gt;&lt;li&gt;1) &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails create-controller com.rockgwt.controller.Principal&lt;/span&gt;&lt;/li&gt;&lt;li&gt;2) &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails create-gwt-page principal/index.gsp com.rockgwt.RockNRoll &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;(quando este comando te perguntar se você quer criar o Controller, diga que não, pois você acabou de criá-lo no passo anterior --- acho que o plugin não reconhece o Controller criado com package, sei lá).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;- Compilar o seu módulo com o comando &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails compile-gwt-modules &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;(demora um pouquinho mesmo)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;- Executar o Development Mode com o comando &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails run-gwt-client &lt;span class="Apple-style-span"  style="font-family:Georgia,serif;"&gt;Perceba que vai se abrir a janela da aplicação &lt;b&gt;Development Mode&lt;/b&gt; do GWT&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;- Abra outro Terminal , vá para o seu projeto rockgwt e execute a aplicação grails (é isso mesmo, você terá duas coisas rodando: o &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails run-app&lt;/span&gt; da aplicação, e o grails run-gwt-client anterior, do GWT).&lt;/li&gt;&lt;li&gt;- Abra o browser e vá para a Home da sua aplicação GWT + Grails em: http://localhost:8080/rockgwt?gwt.codesvr=127.0.0.1:9997&lt;/li&gt;&lt;li&gt;- Na verdade, pode ser que na sua máquina a porta final seja outra, não sei. Para ganrantir sucesso, basta clicar no botão Launch Default Browser existente na janela do Development Mode.&lt;/li&gt;&lt;li&gt;- O endereço que você quer acessar no final de tudo será o seu controler Principal, ou seja:&lt;br /&gt;http://localhost:8080/rockgwt/principal/index?gwt.codesvr=127.0.0.1:9997&lt;/li&gt;&lt;li&gt;- Não deixe de colocar este parâmetro maluco. Ele é o responsável por permitir que você altere o código Java e dê um refresh no browser para ver as modificações imediatamente.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Agora, abra a sua classe RockNRoll e deixe ela assim:&lt;/div&gt;&lt;div&gt;(esta classe se encontra no seu projeto rockgwt em src/gwt/com/rockgwt/client)&lt;/div&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;package com.rockgwt.client;&lt;br /&gt;&lt;br /&gt;import com.google.gwt.core.client.EntryPoint;&lt;br /&gt;import com.google.gwt.user.client.ui.Button;&lt;br /&gt;import com.google.gwt.user.client.ui.RootPanel;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Entry point classes define &amp;lt;code&amp;gt;onModuleLoad()&amp;lt;/code&amp;gt;.&lt;br /&gt;*/&lt;br /&gt;public class RockNRoll implements EntryPoint {&lt;br /&gt;/**&lt;br /&gt; * This is the entry point method.&lt;br /&gt; */&lt;br /&gt;public void onModuleLoad() {&lt;br /&gt;&lt;br /&gt;    final Button sendButton = new Button("Rock n Roll");&lt;br /&gt;&lt;br /&gt;    RootPanel.get().add(sendButton);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Pronto. Dê um refresh no seu browser, e o botão "Rock n Roll" estará lá.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;UPDATE (8/3/2010):&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;- Apenas para completar, para poder usra o Eclipse com tudo redondo, clique no botao direito do mouse em cima de src/gwt e selecione a opção Build Path &gt; Use As Source Folder&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;- E por último clique com o direito do mouse em cima do projeto rockgwt e selecione a opção Google &gt; Webtoolkit Settings, lá dentro do wizard que se abre, selecione o primeiro checkbox que aprece lá em cima "Use Google Web Toolkit". Assim você terá tudo que precisa no classpath da aplicação no Eclipse.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Até a Parte 2 desta série... Aguardo Comentários para saber se estou agradando com este tema. Abcs&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-7955608269137749916?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/21gPeFM9xhi9hojmKoNsDqEH0fM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/21gPeFM9xhi9hojmKoNsDqEH0fM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/21gPeFM9xhi9hojmKoNsDqEH0fM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/21gPeFM9xhi9hojmKoNsDqEH0fM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/gau5jTFABZ8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/7955608269137749916/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=7955608269137749916" title="8 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/7955608269137749916?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/7955608269137749916?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/gau5jTFABZ8/grails-gwt-rock-n-roll-parte-1.html" title="Grails + GWT = Rock n Roll: Parte 1 - Desbravando um novo mundo" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>8</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/03/grails-gwt-rock-n-roll-parte-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QDRXc9eCp7ImA9WxBUGE4.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-3897390253522567522</id><published>2010-03-05T22:24:00.003-03:00</published><updated>2010-03-05T22:36:14.960-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-05T22:36:14.960-03:00</app:edited><title>Executando códigos diferentes em Desenvolvimento e Produção</title><content type="html">Há vezes em que queremos executar códigos diferentes dependendo do ambiente que a aplicação está sendo executada. Por exemplo, integrações com sistemas externos algumas vezes são simuladas em Desenvolvimento, e são executadas pra valer em Produção.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Aí vai uma maneira simples de executar uma coisa em Desenvolvimento e outra em Produção (ou para quantos ambientes você tiver...).&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;import grails.util.Environment;&lt;br /&gt;&lt;br /&gt;class MeuController{&lt;br /&gt;   Environment.executeForCurrentEnvironment {&lt;br /&gt;       production {&lt;br /&gt;           // AQUI vai o código que deve ser executado em produção&lt;br /&gt;       }&lt;br /&gt;       development {&lt;br /&gt;           // AQUI vai o código a ser executado em desenvolvimento.&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-3897390253522567522?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pdEnVAsnnr5cxcV3BvzZdSf1WG8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pdEnVAsnnr5cxcV3BvzZdSf1WG8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pdEnVAsnnr5cxcV3BvzZdSf1WG8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pdEnVAsnnr5cxcV3BvzZdSf1WG8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/9daQ6_mNbBg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/3897390253522567522/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=3897390253522567522" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3897390253522567522?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3897390253522567522?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/9daQ6_mNbBg/executando-codigos-diferentes-em.html" title="Executando códigos diferentes em Desenvolvimento e Produção" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/03/executando-codigos-diferentes-em.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8CSXwycSp7ImA9WxBUF08.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-9070832304410859279</id><published>2010-03-04T14:42:00.002-03:00</published><updated>2010-03-04T14:47:48.299-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-04T14:47:48.299-03:00</app:edited><title>Boas informações sobre grails em português</title><content type="html">Pessoal&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;para quem ainda não conhece, foi lançado o &lt;a href="http://www.grailsbrasil.com/blogs/"&gt;Grailsbrasil Blogs&lt;/a&gt; que é um agregador de &lt;a href="http://www.grailsbrasil.com/blogs/"&gt;blogs em português sobre o Grails&lt;/a&gt;. Lá você poderá ver diversos posts de diversas pessoas que escrevem sobre Grails e afins. Vale conhecer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs&lt;/div&gt;&lt;div&gt;Felipe&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-9070832304410859279?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GYlSJi7WlnF5BQb7SDeVXMqlOFA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GYlSJi7WlnF5BQb7SDeVXMqlOFA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GYlSJi7WlnF5BQb7SDeVXMqlOFA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GYlSJi7WlnF5BQb7SDeVXMqlOFA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/jy1JhmmNuEE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/9070832304410859279/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=9070832304410859279" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/9070832304410859279?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/9070832304410859279?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/jy1JhmmNuEE/boas-informacoes-sobre-grails-em.html" title="Boas informações sobre grails em português" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/03/boas-informacoes-sobre-grails-em.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQGR3o_eyp7ImA9WxBUFko.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-4242227979705862565</id><published>2010-03-04T00:47:00.006-03:00</published><updated>2010-03-04T01:18:46.443-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-04T01:18:46.443-03:00</app:edited><title>Grails e datas: Bind automático de atributo do tipo Date com formato customizado</title><content type="html">Segue uma pequena receita de bolo para quem não está usando o &lt;a href="http://grails.org/doc/latest/ref/Tags/datePicker.html"&gt;datePicker padrão do Grails&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;O Grails vem com uma tag que é a g:datePicker.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ela serve para gerar listboxes (comboboxes) de dia, mês, ano, hora, minuto e segundo. Você pode até escolher quais desses comboboxes você quer que apareçam.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Mas há vezes que não queremos usar estes combos, e simplesmente queremos um campo texto onde o usuário pode digitar a data num formato qualquer, como por exemplo, dd/MM/yyyy, ou dd/MM/yy, ou yyyyMMdd, ou...ou...ou...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E ainda, se você tiver uma aplicação com internacionalização, aí pode ser que para usuários com Locale em português, o formato de entrada deste texto de data é dd/MM/yyyy , porém, se for em inglês, aí é MM/dd/yyyy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Bom, o objetivo aqui é mostrar como dizer para o Grails para usar este formato de entrada de datas para que ele faça o parse automaticamente toda vez que encontrar um atributo do tipo Date em um objeto de domínio (ou um objeto Command) que ele precisa fazer o bind dos parâmetros recebidos num POST (ou GET).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Então:&lt;/div&gt;&lt;div&gt;1) O usuário preenche um campo input type="text", com uma data num formato que você determina, ex: MM/dd/yyyy&lt;/div&gt;&lt;div&gt;2) Ele envia este POST, que chega no seu Controller disponível no atributo params &lt;/div&gt;&lt;div&gt;3) você quer fazer o bind automático usando (digamos que meu objeto de domínio seja Pessoa, e nele haja um atributo &lt;b&gt;Date dtAniversario&lt;/b&gt;):&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Pessoa tx = new Pessoa(params)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Para isso acontecer de forma correta, e o seu atributo dtAniversario estar preenchido corretamente com um valor do tipo Date, é preciso criar um PropertyEditorRegistrar customizado para você. Crie um pacote em src/groovy , digamos com.meusistema.editor , e crie lá o seu PropertyEditorRegistrar:&lt;div&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;package com.meusistema.editor;&lt;br /&gt;&lt;br /&gt;import java.text.SimpleDateFormat;&lt;br /&gt;import java.util.Date;&lt;br /&gt;&lt;br /&gt;import org.springframework.beans.PropertyEditorRegistrar;&lt;br /&gt;import org.springframework.beans.PropertyEditorRegistry;&lt;br /&gt;import org.springframework.beans.propertyeditors.CustomDateEditor;&lt;br /&gt;import org.springframework.context.i18n.LocaleContextHolder;&lt;br /&gt;&lt;br /&gt;public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {&lt;br /&gt;&lt;br /&gt;  def messageSource;&lt;br /&gt;&lt;br /&gt;  public void registerCustomEditors(PropertyEditorRegistry registry) {&lt;br /&gt;    registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(messageSource.getMessage("dateFormat4y",null,'dd/MM/yyyy',LocaleContextHolder.locale )),true));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Perceba que para funcionar corretamente, você precisa editar os seus grails-app/i18n/messages.properties  (messages_en_US.properties, messages_pt_BR.properties)  para que tenham cada uma a sua configuração correta. Ex para o pt_BR:&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;dateFormat4y=dd/MM/yyyy&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;O passo seguinte é registrar este PropertyEditorRegistrar no arquivo grails-app/conf/spring/resources.groovy:&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;beans = {&lt;br /&gt;&lt;br /&gt;  customPropertyEditorRegistrar(com.manubia.propertyeditor.CustomPropertyEditorRegistrar) {&lt;br /&gt;     messageSource = ref('messageSource')&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;Pronto. É isso!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs a todos&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-4242227979705862565?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fuYkJaMxTNp1jR9b7YdDwr_DQnI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fuYkJaMxTNp1jR9b7YdDwr_DQnI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fuYkJaMxTNp1jR9b7YdDwr_DQnI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fuYkJaMxTNp1jR9b7YdDwr_DQnI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/uEV4eZ_8k7o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/4242227979705862565/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=4242227979705862565" title="7 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4242227979705862565?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4242227979705862565?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/uEV4eZ_8k7o/grails-e-datas-bind-automatico-de.html" title="Grails e datas: Bind automático de atributo do tipo Date com formato customizado" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>7</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2010/03/grails-e-datas-bind-automatico-de.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIESXs-eip7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-5277992270727628985</id><published>2009-12-30T12:53:00.002-02:00</published><updated>2010-01-02T00:15:08.552-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:15:08.552-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="scrum" /><title>Como iniciar com Scrum - Bate papo com um futuro Scrum Master</title><content type="html">&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;&lt;div&gt;Oi pessoal,&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;eu comecei a orientar uma pequena empresa parceira em como iniciar a implantação do Scrum. Abaixo reproduzo meu e-mail para o membro da equipe q será o Scrum Master. Comentários? Aguardo contribuições....tenho muito interesse em conhecer diferentes realidades....&lt;/div&gt;&lt;div&gt;Um abraço&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;--------------------&lt;/div&gt;&lt;div&gt;Minhas sugestões:&lt;/div&gt;&lt;div&gt;1) Você deve ser o Scrum Master da equipe&lt;/div&gt;&lt;div&gt;2) Estudar um pouco de scrum para entender o linguajar, e os conceitos.&lt;/div&gt;&lt;div&gt;  a) o que é e qual é o papel do Scrum Master ( &lt;a href="http://blog.eof.com.br/2008/03/06/qual-e-o-papel-do-scrum-master/" target="_blank"&gt;http://blog.eof.com.br/2008/&lt;wbr&gt;03/06/qual-e-o-papel-do-scrum-&lt;wbr&gt;master/&lt;/a&gt; )&lt;/div&gt;&lt;div&gt;  b) entender os principais conceitos: Product Backlog, Sprint Backlog. Sprint Planning Meeting, Sprint Review, Planning Pocker&lt;/div&gt;&lt;div&gt;   (  &lt;a href="http://laguiar.wordpress.com/2008/06/30/introducao-scrum/" target="_blank"&gt;http://laguiar.wordpress.com/&lt;wbr&gt;2008/06/30/introducao-scrum/&lt;/a&gt; )&lt;wbr&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3) Criar o Product Backlog. Para isso, você deve interagir com o cliente. Ele é o Product Owner, e é ele quem sabe como gerar o Product Backlog, e é ele quem sabe priorizar este backlog. Sugiro, se necessário, criar um product backlog para cada produto do projeto ( Admin, Carrinho de Compras, Barramento SOA, etc). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4) Criar um release Backlog para o release 1. Definir releases, junto com o cliente. Pegue o Product Backlog e quebre ele em dois ou três releases. Esses passos 3 e 4 são trabalhosos, e depende do seu esforço e do esforço do cliente. Você provavelmente vai ter umas 3 reuniões DE TRABALHO com ele, cada uma de umas 4 horas de trabalho. Diga a ele que é isso que você quer, que a empresa precisa: de uns 3 dias, de 4 hs, de trabalho conjunto seu e dele para gerar Product Backlogs e Releases Backlogs.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5) Crie um conjunto de cartas de baralho para cada integrante da equipe. Cada um tem que ter um jogo completo dessas cartas. Sugiro comprar uma cartolina mais grossa e fazer as cartas. Tipo isso aqui:   &lt;a href="http://www.flickr.com/photos/tlaukkanen/488795952/sizes/m/"&gt;http://www.flickr.com/photos/tlaukkanen/488795952/sizes/m/&lt;/a&gt;    ......  os números das cartas são esses mesmos: 0, 1/2, 1, 2, 3, 5, 8, 13, 20, 40, 100, e ?.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6) Junte toda a equipe e, juntos, façam um Planning Pocker, usando as cartas. Estimem cada item do backlog do Release 1. Como funciona este pocker:&lt;/div&gt;&lt;div&gt;  - coloca-se no meio da mesa o item de backlog (ou fala-se o item).&lt;/div&gt;&lt;div&gt;  - quem tiver dúvidas a respeito do item, pergunta, e as duvidas devem ser tiradas ali na hora. Todos devem entender o item de backlog.&lt;/div&gt;&lt;div&gt;  - cada desenvolvedor escolhe uma carta. A carta representa os pontos de dificuldade de implementar o item de backlog. Um item muito facil de fazer é a carta 2. Um item dificílimo é a carta 40. As cartas menores que 2 e maior que 40 são para as exceções. Um item já feito recebe a carta ZERO.&lt;/div&gt;&lt;div&gt;  - Após todos escolherem suas cartas, sem mostrar aos demais, todos juntos abrem suas cartas. &lt;/div&gt;&lt;div&gt;  - Geralmente tem uma pessoa que escolhe uma carta de menor valor, e um outro que escolhe uma carta de valor mais alto. Por exemplo, um escolhe a carta 5 e outr escolhe a carta 20.&lt;/div&gt;&lt;div&gt;  - O que escolheu o menor valor deve justificar porque escolheu um valor tao baixo. O que escolheu o maior valor deve fazer o mesmo: justificar.&lt;/div&gt;&lt;div&gt;  - Após as justificativas, todos recolhem suas cartas e escolhem novamente outra carta (ou a mesma). &lt;/div&gt;&lt;div&gt;  - Todos abrem suas novas cartas. Desta vez deve haver um consenso maior entre os participantes. &lt;/div&gt;&lt;div&gt;  - Determine, finalmente, o valor de pontos deste item de backlog. O consenso é que determina. Se 4 escolheram a carta 13 e 1 escolheu a carta 20, 13 é o vencedor.&lt;/div&gt;&lt;div&gt;  - E assim vai para todos os itens do backlog da Release 1. Faça na ordem de prioridade do backlog.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7) Marque um Sprint Meeting. Uma reunião com todos da equipe, você e o Product Owner (cliente). &lt;/div&gt;&lt;div&gt;  a) a reunião é de 4hs de duração. Não mais do que isso. Se ela começar a passar de 4hs, interrompa a reunião. Uma das características do Scrum é o conceito de janela de tempo. O tempo é fixo. O que der pra fazer é feito, o que não der, não deu. Tanto para as reuniões, quanto para o tempo do Sprint (2 semanas).&lt;/div&gt;&lt;div&gt;  b) O cliente pode repriorizar os itens do backlog, pois esses agora já estão estimados, e o cliente pode mudar a prioridade. O cliente deve determinar a ordem de prioridade dos itens deste backlog.&lt;/div&gt;&lt;div&gt;  c) Nesta reunião apresenta-se a lista de itens do Release 1 Backlog para todos. Caso haja alguma dúvida por parte dos desenvolvedores, este é o momento de perguntar as dúvidas ao Owner. Pode-se até mudar as estimativas de pontos do item devido ao melhor entendimento do item. É importante a equipe perguntar TUDO: testes de aceitação, comportamento de tela, requisitos técnicos, etc). Você como Scrum Master tem o papel de provocar a equipe para perguntar e ter certeza de que a equipe está entendendo.&lt;/div&gt;&lt;div&gt;  d) A partir desses, que já estão priorizados, a EQUIPE escolhe os itens que conseguirá se comprometer para a entrega ao final do Sprint. Quem diz o quanto consegue entregar é a equipe. Neste momento a equipe está se comprometendo a entregar aqueles itens de backlog. Com isso, criou-se o Sprint Backlog. A equipe deve considerar a completude da entrega: implementação, testes, documentação.&lt;/div&gt;&lt;div&gt;  e) Pronto. Aqui então a equipe tem o Sprint Backlog. São os items que serão desenvolvidos no Sprint que se inicia.&lt;/div&gt;&lt;div&gt;  f) Outro ponto importate é você, Scrum Master, não permitir que o cliente induza a equipe a aceitar mais itens do que conseguiria.&lt;/div&gt;&lt;div&gt;  g) E finalmente: o Product Owner tem que se comprometer a não alterar o Sprint Backlog durante o sprint. Nessas 2 semanas que se iniciam, o Sprint Backlog NÃO muda.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;8) Iniciar o Sprint de 2 semanas. Durante este período, seria bom a visita do Product Owner (cliente) regularmente. De 3 em 3 dias, ou algo assim. Desta forma a equipe tem a oportunidade de tirar dúvidas.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;9) O Sprint se inicia com uma reunião da EQUIPE, sem cliente. Nesta reunião, o objetivo é quebrar cada item de backlog em Tarefas técnicas: &lt;/div&gt;&lt;div&gt;  a) Modelagem &lt;/div&gt;&lt;div&gt;  b) Criação de scripts de Banco de Dados&lt;/div&gt;&lt;div&gt;  c) Implementação de Regras de Negócio&lt;/div&gt;&lt;div&gt;  d) Estudo e avaliação de tecnologia&lt;/div&gt;&lt;div&gt;  e) Implementação de testes unitários&lt;/div&gt;&lt;div&gt;  f)  Implementação de testes de integração&lt;/div&gt;&lt;div&gt;  g) documentação&lt;/div&gt;&lt;div&gt;  h) Implementação de Telas (html, css, javascript)&lt;br /&gt;&lt;div&gt;  etc&lt;/div&gt;&lt;div&gt;  - Cada item do Sprint Backlog deve ser quebrado em Tarefas.&lt;/div&gt;&lt;div&gt;  - esta reunião pode ser logo em seguida da reunião de Sprint Planning Meeting que ocorreu com o Owner. Pode marcar o Meeting de manhã, e a reunião da equipe para quebrar em tarefas a tarde.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;10) Primeiro dia do Sprint: &lt;/div&gt;&lt;div&gt;  a) Você, Scrum Master, promove o Daily Meeting, que é a reunião diária de 15 min, em pé! Tem que ser rápida. Aqui, cada um diz o que fez ontem, os problemas que está enfrentando, e o que fará hoje (ou amanhã). A própria equipe se organiza em dizer quem fará quais tarefas. Sempre em ordem de prioridade dos itens do backlog.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;11) Você, Scrum Master, deve deixar visível o Burn Down Chart. Desenhe ele no quadro para todos verem. Atualize diariamente, assim todos acompanharão o andamento do Sprint. Veja um exemplo aqui &lt;a href="http://www.mountaingoatsoftware.com/system/hidden_asset/file/53/BurndownBarchart.xls"&gt;http://www.mountaingoatsoftware.com/system/hidden_asset/file/53/BurndownBarchart.xls&lt;/a&gt;  &lt;/div&gt;&lt;div&gt;  - Neste gráfico, a barra representa o total de pontos que ainda faltam no Sprint. &lt;/div&gt;&lt;div&gt;  - É importante diferenciar entre os pontos planejados do Sprint (que foram escolhidos pela equipe para formar o Sprint backlog), e os pontos que surgiram ao longo do Sprint. Coisas imprevistas que apareceram e tiveram que ser feitas. Essas, devem entrar como tarefas extras, e devem ficar evidente, para que o cliente entenda qualquer atraso ou não entrega do que foi acordado.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;12) Diariamente faça o Daily meeting, com todos da equipe, em pé. 15 min. Se houver algum problema, algum impedimento, que esteja causando paralisia da equipe, você como Scrum Master deve solucionar isso. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;13) Durante o Sprint de duas semanas, você poderia atuar como um projetista de Protótipo de Telas. Sente com o cliente, entenda os itens do backlog do Release 1 que não fazem parte do Sprint 1 (ou seja, vc estará planejando o sprint seguinte, enquanto a equipe trabalha no sprint atual). Você poderia ir criando protótipo de telas que seriam aceitos pelo cliente, e direcionariam o desenvolvimento da equipe. Power point é uma ferramenta simples e eficiente para isso. Mando um exemplo em anexo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-5277992270727628985?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UHCqQuj49s8aoGouPL9HE4ede1o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UHCqQuj49s8aoGouPL9HE4ede1o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UHCqQuj49s8aoGouPL9HE4ede1o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UHCqQuj49s8aoGouPL9HE4ede1o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/qKa7Gs_-fp4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/5277992270727628985/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=5277992270727628985" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/5277992270727628985?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/5277992270727628985?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/qKa7Gs_-fp4/como-iniciar-com-scrum-bate-papo-com-um.html" title="Como iniciar com Scrum - Bate papo com um futuro Scrum Master" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/12/como-iniciar-com-scrum-bate-papo-com-um.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIASH4zeCp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-575494862839360441</id><published>2009-12-17T11:55:00.002-02:00</published><updated>2010-01-02T00:15:49.080-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:15:49.080-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mysql" /><category scheme="http://www.blogger.com/atom/ns#" term="banco de dados" /><title>O que todos deveriam saber sobre Mysql</title><content type="html">Nestes tempos de desenvolvimento com frameworks que tentam (e conseguem) facilitar muito nossa vida abstraindo detalhes de baixo nível, muitas vezes deixamos de nos preocupar com o que se passa lá por baixo.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Mas, em aplicações que tendem a crescer, que com o tempo vão deteriorando em performance, muitas vezes os problemas estão no banco de dados, na forma como acessamos o banco, em como construímos nossas queries...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Esta apresentação aqui, apresentada no Sun Tech Days 2009, é &lt;b&gt;muito boa&lt;/b&gt; para quem usa Mysql.&lt;/div&gt;&lt;div&gt;&lt;a href="http://developers.sun.com/events/techdays/presentations/2009/pdfs/TD_SP_MySQL_Karlsson.pdf"&gt;http://developers.sun.com/events/techdays/presentations/2009/pdfs/TD_SP_MySQL_Karlsson.pdf&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-575494862839360441?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kLhwqr7LEmrvH2dIcHz834wy5os/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kLhwqr7LEmrvH2dIcHz834wy5os/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kLhwqr7LEmrvH2dIcHz834wy5os/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kLhwqr7LEmrvH2dIcHz834wy5os/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/IfLNODpBG_U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/575494862839360441/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=575494862839360441" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/575494862839360441?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/575494862839360441?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/IfLNODpBG_U/o-que-todos-deveriam-saber-sobre-mysql.html" title="O que todos deveriam saber sobre Mysql" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/12/o-que-todos-deveriam-saber-sobre-mysql.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkECQ3g9fSp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-4225474111416626936</id><published>2009-12-05T13:32:00.003-02:00</published><updated>2010-01-02T00:17:42.665-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:17:42.665-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="cloud" /><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Grails e Cloud: desenvolvimento, deploy, execução e monitoramento. Ciclo completo com Grails na Nuvem.</title><content type="html">No início havia muitas dúvidas se o Grails iria ser útil para aplicações grandes, ou de grande porte. Mas peraí, o que é uma aplicação grande? eBay é gigante. Se considerarmos uma medida, aí acho que podemos definir grande. Page-views por mês, por exemplo, pode ser uma medida, já que é fácil de saber, de monitorar, etc.&lt;br /&gt;&lt;br /&gt;Um eBay tem algo em torno de 15 bilhões de page-views por mês. A globo.com tem uns 2 bilhões de page-views/mês. Um Peladeiro.com.br tem 1,2 milhão de page-views/mês. O Peladeiro é pequeno, Globo.com é grande, eBay é gigante. Pelo menos na minha opinião, sem muito exercício científico.&lt;br /&gt;&lt;br /&gt;Além da medida de grande número de acessos, há também: grande volume de dados, necessidade de alta disponibilidade e redundância, escalabilidade, hot swap, cluster failover, etc, etc....&lt;br /&gt;&lt;br /&gt;Aí voltamos a pergunta original: o Grails é bom para isso? Dá pra confiar que uma aplicação grails serve para uma demanda de uma aplicação de grande porte? &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Alguns casos reais confirmam que a resposta é sim. Por exemplo, o &lt;a href="http://www.linkedin.com/"&gt;Linkedin.com&lt;/a&gt; usa Grails para algumas partes. Este site tem as &lt;a href="http://www.slideshare.net/glaforge/grails-at-linkedin-455651"&gt;seguintes características&lt;/a&gt;: 22 milhões de membros, 1,2 milhão de novos membros por mês. Acho que o site mesmo, quando vc acessa linkedin.com, não é em grails, apesar de ser em java. Mas há partes feitas em Grails.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Onde eu quero chegar afinal? Meu ponto é que acho que atualmente o Grails chegou aonde queríamos que ele chegasse: está maduro o suficiente, estável, performance boa o suficiente, há ferramentas para desenvolvimento, e agora há serviços prestados por fornecedores que dão suporte ao deploy, execução e monitoramento de uma aplicação grails na Nuvem (Cloud).  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Um grande player neste mundo de Cloud é a Amazon, com seu &lt;a href="http://aws.amazon.com/"&gt;AWS&lt;/a&gt; . Mas como desenvolver uma aplicação Grails para rodar neste ambiente virtual? A nuvem está lá, mas você não vê. Tem &lt;a href="http://aws.amazon.com/ec2/"&gt;solução poder computacional escalável&lt;/a&gt;, &lt;a href="http://aws.amazon.com/s3/"&gt;solução de storage&lt;/a&gt;, de &lt;a href="http://aws.amazon.com/rds/"&gt;banco de dados relacional&lt;/a&gt; na nuvem, e muito mais....&lt;/div&gt;&lt;div&gt;Mas como usar isso tudo? Como fazer uma aplicação Grails rodar nesta infra poderosa, mas complexa?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Aí que eu acho que a SpringSource está dando um show! Primeiro os caras inventam o &lt;a href="http://www.springsource.com/products/enterprise"&gt;Spring&lt;/a&gt;, que é solução para DESENVOLVIMENTO. Depois começam a expandir &lt;a href="http://www.springsource.com/products/run"&gt;para servidores&lt;/a&gt;, que é solução para EXECUÇÃO. Depois fornecem solução para  &lt;a href="http://www.springsource.com/products/sts"&gt;ferramentas&lt;/a&gt; ajudando mais ainda no quesito DESENVOLVIMENTO. Aí lançam produtos para &lt;a href="http://www.springsource.com/products/manage"&gt;gerenciar e monitorar&lt;/a&gt; (MONITORAMENTO).  Por último, lançam um serviço que te ajuda &lt;a href="http://www.springsource.com/products/cloudfoundry"&gt;executar aplicações java na infra de Cloud&lt;/a&gt; da Amazon: &lt;a href="http://www.cloudfoundry.com/"&gt;Cloud Foundry&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;E por último, os caras compraram a G2One, que era a empresa responsável por Groovy e Grails. O resultado é: Grails tá pronto para rodar em tudo isso citado aí em cima. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Portanto, no momento presente, você pode desenvolver uma aplicação Grails usando tudo que este excelente framework oferece, pode usar os plugins de eclipse para Groovy e Grails que a SpringSource está desenvolvendo, pode fazer deploy, execução e monitoramento da applicação na nuvem da Amazon usando o CloudFoundry (ou o &lt;a href="http://www.grails.org/blog/chasylee/Cloud+Foundry+plugin+released"&gt;Cloud Foundry Plugin&lt;/a&gt; pra grails).  Isso é excelente!!! Sua aplicação grails fica escalável, podendo usar instâncias com balanceamento de carga (load-balance) em diferentes zonas de disponibilidade, pode usar replicação master-slave para seu Mysql, pode usar SSL no apache, monitoramento e restart automático de servidores que falham, auto-escala de instâncias do EC2 da Amazon (pagando apenas pelo o que usa), pode usar backup automático de dados com snapshots.......... tudo isso para uma aplicação grails rodando na nuvem, e você gerenciando via Web. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Na teoria é lindo. Temos que ver na prática agora.&lt;/div&gt;&lt;div&gt;t+&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-4225474111416626936?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jAfYe8V0855x5gSCZWpydBjJuQY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jAfYe8V0855x5gSCZWpydBjJuQY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jAfYe8V0855x5gSCZWpydBjJuQY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jAfYe8V0855x5gSCZWpydBjJuQY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/5lawfh4h1dM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/4225474111416626936/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=4225474111416626936" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4225474111416626936?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4225474111416626936?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/5lawfh4h1dM/grails-e-cloud-desenvolvimento-deploy.html" title="Grails e Cloud: desenvolvimento, deploy, execução e monitoramento. Ciclo completo com Grails na Nuvem." /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/12/grails-e-cloud-desenvolvimento-deploy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIDRXY9eCp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-3486168861050999214</id><published>2009-10-14T16:13:00.003-03:00</published><updated>2010-01-02T00:16:14.860-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:16:14.860-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Enviando emails formatados com Html e CSS - será que vai certinho?</title><content type="html">Muito bom esta tabela que mostra o que cada cliente de email consegue mostrar corretamente em termos de CSS nos emails Html que vc envia.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.campaignmonitor.com/css/"&gt;http://www.campaignmonitor.com/css/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ou seja, não adianta referenciar um arquivo CSS na tag link lá no header, pois nem todos os clientes levam isso em consideração. E nem tag style no header, e nem..... olhe o link acima.&lt;br /&gt;&lt;br /&gt;Abcs&lt;br /&gt;Felipe&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-3486168861050999214?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JyKEaRmQpz3SR6Tu6p0lgNg4Jt0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JyKEaRmQpz3SR6Tu6p0lgNg4Jt0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JyKEaRmQpz3SR6Tu6p0lgNg4Jt0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JyKEaRmQpz3SR6Tu6p0lgNg4Jt0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/RcfURr48-6M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/3486168861050999214/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=3486168861050999214" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3486168861050999214?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3486168861050999214?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/RcfURr48-6M/enviando-emails-formatados-com-html-e.html" title="Enviando emails formatados com Html e CSS - será que vai certinho?" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/10/enviando-emails-formatados-com-html-e.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIDRXY9eCp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-1214415313039264968</id><published>2009-09-29T11:18:00.002-03:00</published><updated>2010-01-02T00:16:14.860-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:16:14.860-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Serviços do Grails, Transações e Rollback automático</title><content type="html">Comprei o livro recente que saiu do Glen Smith, o &lt;a href="http://www.manning.com/gsmith/"&gt;Grails in Action&lt;/a&gt;. E, claro, comecei a ler. Ainda não terminei. Mas já valeu a compra e a dedicação de ler só pelo fato que eu descobri e não sabia:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nos serviços do grails ( classes *Service.groovy, dentro do diretório services), que possuem &lt;a href="http://grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html#8.1 Declarative Transactions"&gt;Transação Declarativa&lt;/a&gt; , o default é cada método ser transacional. Isso significa que uma transação será iniciada antes do método do serviço começar a ser executado, e será finalizada (commit ou rollback) ao final.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;O rollback acontece automaticamente quando uma Exception é lançada. O que eu não sabia era que apenas Runtime Exceptions fazem o rollback acontecer. Checked Exceptions não. Isso mudou minha vida!  :-)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Eu fazia um try catch no controller, às vezes, pegando o tipo Exception no catch. Grave erro conceitual de cara né, mas pior ainda, pois eu estava contando com o rollback que poderia não acontecer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Então amigos: apenas classes derivadas de RuntimeException fazem o rollback acontecer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-1214415313039264968?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JGrI_Jqq6CLxFsAhiPj0hIieIbI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JGrI_Jqq6CLxFsAhiPj0hIieIbI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JGrI_Jqq6CLxFsAhiPj0hIieIbI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JGrI_Jqq6CLxFsAhiPj0hIieIbI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/qWIknvKBwac" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/1214415313039264968/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=1214415313039264968" title="3 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/1214415313039264968?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/1214415313039264968?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/qWIknvKBwac/servicos-do-grails-transacoes-e.html" title="Serviços do Grails, Transações e Rollback automático" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/09/servicos-do-grails-transacoes-e.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIDRXY9eSp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-4846831199940544084</id><published>2009-09-29T10:55:00.003-03:00</published><updated>2010-01-02T00:16:14.861-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:16:14.861-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Manubia.com.br - Controle Financeiro com Grails e, agora, com jQuery</title><content type="html">É pessoal....&lt;div&gt;depois de algum tempo, tempão mesmo, usando a dupla Prototype + Scriptaculous.....depois de saber usar bem esta dupla, de &lt;a href="http://www.amazon.com/Prototype-Scriptaculous-Action-Ajax-Crane/dp/1933988037"&gt;ler livro&lt;/a&gt; e tudo..... resolvi abandonar totalmente a dupla e me render ao jQuery.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Deu um trabalho danado migrar o &lt;a href="http://www.manubia.com.br"&gt;Manubia.com.br&lt;/a&gt; (site de &lt;a href="http://www.manubia.com.br"&gt;controle financeiro&lt;/a&gt;) para o jQuery. Tem muita coisinha diferente. Mas no final das contas, estou gostando muito.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Alguns dos motivos de ter feito a migração:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;jQuery tem um mundo plugins que resolvem diversos problemas que a gente precisa ficar catando pela web quando usamos Prototype + Scriptaculous. &lt;/li&gt;&lt;li&gt;o jQuery tem um projeto inteiro dedicado a interface gráfica: &lt;a href="http://www.jqueryui.com/"&gt;jQuery UI&lt;/a&gt;&lt;/li&gt;&lt;li&gt;formatação de campos de um formulário (formatar valor numérico com pontos e vírgulas, de forma internacionalizada): &lt;a href="http://digitalbush.com/projects/masked-input-plugin/"&gt;Masked Input Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Calendário tipo Date Picker para campos de datas: &lt;a href="http://www.jqueryui.com/demos/datepicker/"&gt;jQuery UI DatePicker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Plugin para manipulação de comboboxes (&lt;a href="http://www.texotela.co.uk/code/jquery/select/"&gt;select boxes&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;No final das contas, a gente escreve menos código JavaScript do que com Prototype. Parece que fica mais limpo o código.&lt;/li&gt;&lt;li&gt;Tem um &lt;a href="http://plugins.jquery.com/"&gt;site dedicado aos plugins&lt;/a&gt;&lt;/li&gt;&lt;li&gt;De acordo com alguns benchmarks (&lt;a href="http://www.webdevelopment2.com/jquery-prototype-mootools-benchmark-slickspeed/"&gt;um aqui&lt;/a&gt;, &lt;a href="http://blog.creonfx.com/javascript/mootools-vs-jquery-vs-prototype-vs-yui-vs-dojo-comparison-revised"&gt;outro aqui&lt;/a&gt;), o jQuery tem uma performance melhor do que o Prototype (ou seja, os usuários é que ganham).&lt;/li&gt;&lt;li&gt;Eu tenho tudo que preciso em uma biblioteca só, não preciso usar parte de uma, parte de outra, etc... (pelo menos por enquanto, vamos ver até quando).&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;É isso. Acho que o Manubia ganhou com este investimento que fiz... No fundo mesmo, eu precisava era do formatador numérico para campos input. Aí achei o plugin de jQuery...isso foi a gota d'água pra eu migrar. (Eu já tava p da vida por estar usando o date picker do &lt;a href="http://openrico.org/"&gt;Open Rico&lt;/a&gt;)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs&lt;/div&gt;&lt;div&gt;Felipe&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-4846831199940544084?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Rpck80kqqKiV8m1K_5_1FdUN21c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rpck80kqqKiV8m1K_5_1FdUN21c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Rpck80kqqKiV8m1K_5_1FdUN21c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rpck80kqqKiV8m1K_5_1FdUN21c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/F2zUM9mQTgg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/4846831199940544084/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=4846831199940544084" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4846831199940544084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4846831199940544084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/F2zUM9mQTgg/manubiacombr-controle-financeiro-com.html" title="Manubia.com.br - Controle Financeiro com Grails e, agora, com jQuery" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/09/manubiacombr-controle-financeiro-com.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIDRXY9eSp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-3560268410082139059</id><published>2009-09-09T23:48:00.003-03:00</published><updated>2010-01-02T00:16:14.861-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:16:14.861-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Filtro do Grails para impor SSL (https) a determinadas páginas</title><content type="html">Olá pessoal,&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;hoje andei pesquisando a respeito de uso de certificados SSL com uma aplicação grails. Afinal, está chegando a hora de impor o uso de SSL (https) meu novo site de &lt;a href="http://www.manubia.com.br"&gt;controle financeiro&lt;/a&gt;, o &lt;a href="http://www.manubia.com.br"&gt;Manubia.com.br&lt;/a&gt; .&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Então ao pesquisar o assunto, encontrei uma classe de um grails Filter que pode me ajudar muito em forçar determinadas URLs a usarem SSL e outras não. Por exemplo, uma página que mostra dados não confidenciais, não precisa usar SSL (https). Já uma página que mostra ou recebe um formulário confidencial DEVE usar SSL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Aí vai o Filter. Ainda não testei, mas parece certinho.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt;* Created by IntelliJ IDEA.&lt;br /&gt;* User: danielhonig&lt;br /&gt;* Date: Jan 23, 2009&lt;br /&gt;* Time: 4:27:10 PM&lt;br /&gt;* To change this template use File | Settings | File Templates.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;import org.codehaus.groovy.grails.commons.ConfigurationHolder&lt;br /&gt;&lt;br /&gt;class SSLFilters {&lt;br /&gt;   // Set these to your HTTP/HTTPS ports&lt;br /&gt;   def defaultPortHTTP = 80&lt;br /&gt;   def defaultPortHTTPS = 443&lt;br /&gt;&lt;br /&gt;   static def SSLRequiredMap = ConfigurationHolder.config.SSLRequiredMap&lt;br /&gt;&lt;br /&gt;   def shouldUseSSL(controllerName, actionName) {&lt;br /&gt;       // User actions use SSL&lt;br /&gt;       if (SSLRequiredMap[controllerName]!=null) {&lt;br /&gt;&lt;br /&gt;           //If * then all actions are secured&lt;br /&gt;           if (SSLRequiredMap[controllerName][0] == '*')&lt;br /&gt;               return true&lt;br /&gt;&lt;br /&gt;           //else look for specific action&lt;br /&gt;           if (SSLRequiredMap[controllerName].contains(actionName))&lt;br /&gt;               return true&lt;br /&gt;       }&lt;br /&gt;       false&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def filters = {&lt;br /&gt;       sslFilter(controller: "*", action: "*"){&lt;br /&gt;                   before =  {&lt;br /&gt;                           def controller = controllerName&lt;br /&gt;                           def action = actionName&lt;br /&gt;                           log.debug("SSLFilter: ${params?.controller}.${params?.action}")&lt;br /&gt;                           def url = null&lt;br /&gt;&lt;br /&gt;                           // SSL off by default&lt;br /&gt;                           def useSSL = shouldUseSSL(controllerName,actionName)&lt;br /&gt;&lt;br /&gt;                           log.debug("${controller}.${action}, useSSL:$useSSL")&lt;br /&gt;&lt;br /&gt;                           // Get redirected url&lt;br /&gt;                           url = getRedirectURL(request, params, useSSL);&lt;br /&gt;&lt;br /&gt;                           // If redirect url returned, redirect to it&lt;br /&gt;                           if (url) {&lt;br /&gt;                               redirect(url: url)&lt;br /&gt;                               return false;&lt;br /&gt;                           }&lt;br /&gt;&lt;br /&gt;                           return true;&lt;br /&gt;                       }&lt;br /&gt;               }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def getRedirectURL =  {request, params, ssl -&amp;gt;&lt;br /&gt;       log.debug("getRedirectURL: $ssl")&lt;br /&gt;&lt;br /&gt;       // Are we there already?&lt;br /&gt;       if (request.isSecure() == ssl)&lt;br /&gt;           return null;&lt;br /&gt;&lt;br /&gt;       def protocol&lt;br /&gt;       def port&lt;br /&gt;&lt;br /&gt;       // Otherwise we need to flip&lt;br /&gt;       if (ssl) {&lt;br /&gt;           protocol = 'https'&lt;br /&gt;&lt;br /&gt;           // If using the standard ports, don't include them on the URL&lt;br /&gt;           port = defaultPortHTTPS&lt;br /&gt;           if (port == "443")&lt;br /&gt;               port = ""&lt;br /&gt;           else&lt;br /&gt;               port = ":${port}"&lt;br /&gt;       }&lt;br /&gt;       else {&lt;br /&gt;           protocol = 'http'&lt;br /&gt;           // If using the standard ports, don't include them on the URL&lt;br /&gt;           port = defaultPortHTTP&lt;br /&gt;           if (port == "80")&lt;br /&gt;               port = ""&lt;br /&gt;           else&lt;br /&gt;               port = ":${port}"&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       log.debug("Flip protocol to $protocol")&lt;br /&gt;&lt;br /&gt;       def url = request.forwardURI&lt;br /&gt;       def server = request.serverName&lt;br /&gt;       def args = paramsAsUrl(params)&lt;br /&gt;       url = "$protocol://$server$port$url$args"&lt;br /&gt;&lt;br /&gt;       log.debug("getRedirectURL - redirect to $url")&lt;br /&gt;&lt;br /&gt;       return url;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def paramsAsUrl =  {params -&amp;gt;&lt;br /&gt;       int ii = 0&lt;br /&gt;       String args = ""&lt;br /&gt;       params.each&lt;br /&gt;       {k, v -&amp;gt;&lt;br /&gt;           if (['controller', 'action', 'id'].find {k == it})&lt;br /&gt;               return;&lt;br /&gt;&lt;br /&gt;           if (ii)&lt;br /&gt;               args += "&amp;amp;"&lt;br /&gt;           else&lt;br /&gt;               args += "?"&lt;br /&gt;&lt;br /&gt;           args += "$k=$v"&lt;br /&gt;           ii++&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       return args&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-3560268410082139059?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mI9BAm3L06iWHO4HaasP4VK7RSs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mI9BAm3L06iWHO4HaasP4VK7RSs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mI9BAm3L06iWHO4HaasP4VK7RSs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mI9BAm3L06iWHO4HaasP4VK7RSs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/SkeOEXNr5kg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/3560268410082139059/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=3560268410082139059" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3560268410082139059?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/3560268410082139059?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/SkeOEXNr5kg/filtro-do-grails-para-impor-ssl-https.html" title="Filtro do Grails para impor SSL (https) a determinadas páginas" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/09/filtro-do-grails-para-impor-ssl-https.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIDRXY9eSp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-4390267126103804576</id><published>2009-09-06T13:32:00.003-03:00</published><updated>2010-01-02T00:16:14.861-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:16:14.861-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Controle Financeiro e Planejamento Financeiro com Grails e Prototype</title><content type="html">Mês passado eu e um grande amigo, e meu sócio neste projeto, lançamos um site para &lt;b&gt;&lt;a href="http://www.manubia.com.br"&gt;controle financeiro&lt;/a&gt;&lt;/b&gt; pessoal: &lt;a href="http://www.manubia.com.br"&gt;www.manubia.com.br&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; O site foi todo desenvolvido com Grails e a dupla Prototype/Scriptaculous.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tenho me questionado se não deveria mudar para jQuery. Eu vi um &lt;a href="http://blog.creonfx.com/javascript/mootools-vs-jquery-vs-prototype-vs-yui-vs-dojo-comparison-revised"&gt;benchmark&lt;/a&gt; e acabo ficando na dúvida. Alguém prefere o jQuery ao invés do Prototype?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Em fim..... o sistema do Manubia foi ótimo de ser feito com o Grails. É incrível a produtividade do Grails, todos os plugins (estou usando authentication plugin, mail plugin e o mail-confirmation plugin). E bastante efeito visual e ajax com o Prototype e o Scriptaculous. Tá ficando legal. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sobre o sistema em si, é um sistema de &lt;a href="http://www.manubia.com.br"&gt;controle financeiro&lt;/a&gt;, onde você pode inserir suas transações, ou importar arquivo do seu banco, e em seguida pode categorizar todos os seus gastos. Feito isso, o sistema apresenta gráficos muito interessantes comparando seus gastos ao longo dos meses, resumo de suas contas , entre outros. É muito interessante pois assim você tem visibilidade dos seus gastos, e pode, portanto, fazer um &lt;a href="http://www.manubia.com.br"&gt;planejamento financeiro&lt;/a&gt; para a sua família. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Eu importei meus dados dos últimos 4 meses, e foi ótimo pois consegui, junto com minha esposa, descobrir nossos  ralos financeiros. Assim poderemos fechar esses ralos e poupar um pouco mais...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Abcs&lt;/div&gt;&lt;div&gt;Felipe&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-4390267126103804576?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/r1fe6KKCfGxuzYkO8wzDkAG2fjE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/r1fe6KKCfGxuzYkO8wzDkAG2fjE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/r1fe6KKCfGxuzYkO8wzDkAG2fjE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/r1fe6KKCfGxuzYkO8wzDkAG2fjE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/N-lMMlJ72bk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/4390267126103804576/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=4390267126103804576" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4390267126103804576?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/4390267126103804576?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/N-lMMlJ72bk/controle-financeiro-e-planejamento.html" title="Controle Financeiro e Planejamento Financeiro com Grails e Prototype" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/09/controle-financeiro-e-planejamento.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMBRXc5eyp7ImA9WxJbGE4.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-8304634787066803971</id><published>2009-07-28T23:07:00.006-03:00</published><updated>2009-07-28T23:10:54.923-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-28T23:10:54.923-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><title>Instalador para Mac de uma aplicação Java</title><content type="html">&lt;span class="Apple-style-span"   style="  border-collapse: collapse; color: rgb(51, 51, 51); -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family:'trebuchet ms', sans-serif;font-size:14px;"&gt;&lt;div style="text-align: center; "&gt;&lt;h2 style="color: gray; font-size: 16px; font-weight: normal; font-family: 'comic sans ms', 'american typewriter', sans-serif; "&gt;Excelente artigo de como criar um installer para Mac de uma aplicação Java. Como esse artigo me salvou legal, copio ele aqui, só pra não perder.&lt;/h2&gt;&lt;div&gt;Original em: &lt;a href="http://www.centerkey.com/mac/java/"&gt;http://www.centerkey.com/mac/java/&lt;/a&gt;&lt;/div&gt;&lt;h2 style="color: gray; font-size: 16px; font-weight: normal; font-family: 'comic sans ms', 'american typewriter', sans-serif; "&gt;How to Create a Mac OS X Installer for a Java Application&lt;br /&gt;&lt;small&gt;(Updated for Mac OS X 10.5 — Leopard)&lt;/small&gt;&lt;/h2&gt;&lt;/div&gt;&lt;br /&gt;With some simple steps you can turn your Java Swing program (.jar) into a proper Mac OS X application with a native installer.  The instructions below step you through the process from scratch with a sample program called &lt;div  style="float: right;  font-weight: bold; text-align: right; text-transform: uppercase; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 15px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; font-size:10px;"&gt;SCREENSHOT&lt;br /&gt;ICONS&lt;br /&gt;&lt;span style=" ;font-size:25px;"&gt;↓ &lt;/span&gt;&lt;/div&gt;"It's Showtime!" which simply displays the current time.  Once you have successfully completed the tutorial with the sample Java program, modify the steps to work for your Java program.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;1) Install Xcode&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-xcode.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-xcode-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Apple's Xcode suite includes development tools you'll need to bundle and package a Java program.  First, download &lt;a href="http://developer.apple.com/tools/download/" title="Apple Developer Connection" style="color: rgb(169, 169, 169); font-weight: bold; text-decoration: none; "&gt;Xcode for Mac Development&lt;/a&gt; (version 3.1.1 or later) and open the downloaded &lt;i&gt;.dmg&lt;/i&gt;file.  Now run the "XcodeTools.mpkg" file and complete the Xcode installation with all the default options.&lt;br /&gt;&lt;br /&gt;Before continuing to the next step, it's a good idea to &lt;a href="http://www.apple.com/softwareupdate/" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;perform a "Software Update..."&lt;/a&gt; to make sure your OS files are current.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;2) Launch Unix Terminal&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-terminal.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-terminal-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Using "Finder" go into "Applications" and then open the "Utilities" folder.  Scroll down until you see "Terminal".  Open "Terminal" and you're now at the Unix prompt.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;3) Make Project Folder&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-mkdir.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-mkdir-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;At the Unix prompt, enter these two commands:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;mkdir ItsShowtime&lt;br /&gt;cd ItsShowtime&lt;/div&gt;The first command creates a folder called "ItsShowtime", and the second command moves you into the new folder.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;4) Write Some Java Code&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-pico.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-pico-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Mac OS X comes with a simple but effective text editor called Pico.  Use the following command to create and edit a new Java file:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;pico ShowTime.java&lt;/div&gt;Enter the following code:&lt;br /&gt;&lt;div class="code" style="float: left; white-space: pre; background-color: rgb(176, 196, 222); font-weight: bold; font-family: monospace; padding-top: 0px; padding-right: 15px; padding-bottom: 15px; padding-left: 15px; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;&lt;p style="text-align: center; color: white; background-color: rgb(65, 105, 225); font-weight: bold; font-family: sans-serif; padding-top: 2px; padding-right: 2px; padding-bottom: 2px; padding-left: 2px; margin-top: 0px; margin-right: -15px; margin-bottom: 0px; margin-left: -15px; "&gt;ShowTime.java&lt;/p&gt; import java.util.Calendar; import javax.swing.*; public class ShowTime {    public static void main(String[] args) {       JFrame f = new JFrame();       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       f.setTitle("It's Showtime!");       f.getContentPane().add(new JLabel(          Calendar.getInstance().getTime().toString()));       f.pack();       f.setVisible(true);       }    } &lt;/div&gt;&lt;br /&gt;&lt;div class="legend" style="text-align: center; font-size: 12px; "&gt;&lt;a href="http://www.centerkey.com/mac/java/ItsShowtime/ShowTime.java" onclick="window.open('ItsShowtime/ShowTime.java', '', 'width=600,height=300'); return false;" title="ShowTime.java" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;view/download code&lt;/a&gt;&lt;/div&gt;Use &lt;em style="font-weight: bold; "&gt;&lt;ctrl-x&gt;&lt;/ctrl-x&gt;&lt;/em&gt; to exit Pico.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;5) Compile Java Program&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-javac.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-javac-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Back at the Unix prompt, compile your Java program into a class file:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;javac ShowTime.java&lt;br /&gt;ls -la&lt;/div&gt;We could run the class file directly, but a class file is cumbersome.  Instead we will create an executable JAR file.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;6) Make Executable JAR&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-showtime.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-showtime-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Before we make an executable JAR file, we need a manifest file to indicate which class contains the "main" function.  We'll use Pico again:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;pico MainClass.txt&lt;/div&gt;Our manifest file will only have one line:&lt;br /&gt;&lt;div class="code" style="float: left; white-space: pre; background-color: rgb(176, 196, 222); font-weight: bold; font-family: monospace; padding-top: 0px; padding-right: 15px; padding-bottom: 15px; padding-left: 15px; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;&lt;p style="text-align: center; color: white; background-color: rgb(65, 105, 225); font-weight: bold; font-family: sans-serif; padding-top: 2px; padding-right: 2px; padding-bottom: 2px; padding-left: 2px; margin-top: 0px; margin-right: -15px; margin-bottom: 0px; margin-left: -15px; "&gt;MainClass.txt&lt;/p&gt; Main-Class: ShowTime &lt;/div&gt;&lt;br /&gt;Exit Pico and use the following "jar" command to create the "ShowTime.jar" file:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;jar cmf MainClass.txt ShowTime.jar *.class&lt;br /&gt;ls -la&lt;/div&gt;Now test your executable JAR with the following command:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;java -jar ShowTime.jar&lt;br /&gt;&lt;/div&gt;The "It's Showtime!" window with the current time should display in the upper left corner of the screen.  Click the red dot to exit the program.&lt;br /&gt;&lt;br /&gt;While the manual commands for steps #5 and #6 above work fine, you can automate them using &lt;a href="http://ant.apache.org/manual/tutorial-HelloWorldWithAnt.html" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;Ant&lt;/a&gt; with this &lt;a onclick="window.open('build.xml.php', '', 'width=550,height=530'); return false;" href="http://www.centerkey.com/mac/java/build.xml.php" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;build.xml&lt;/a&gt; file.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;7) Create Application Icon&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-composer.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-composer-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;The default icon for an executable JAR is a coffee cup.  To add a custom icon, we need to use the "Icon Composer".&lt;br /&gt;&lt;br /&gt;Download and save (&lt;em style="font-weight: bold; "&gt;&lt;ctrl-click&gt;&lt;/ctrl-click&gt;&lt;/em&gt;) this sample PNG image to the "Desktop":  &lt;a href="http://www.centerkey.com/mac/java/ShowTime.png" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;ShowTime.png&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then move the file into the "ItsShowtime" folder with the following command:&lt;div class="command" style="color: rgb(105, 105, 105); font-family: monospace; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; margin-left: 30px; "&gt;mv ../Desktop/ShowTime.png .&lt;br /&gt;&lt;/div&gt;Now we can create the icon file.&lt;br /&gt;&lt;br /&gt;Steps:&lt;ol style="list-style-type: lower-alpha; font-size: 12px; margin-top: 3px; "&gt;&lt;li&gt;Use "Finder" to navigate into the "Developer:Applications:Utilities" folder and double-click "Icon Composer".&lt;/li&gt;&lt;li&gt;Go back to "Finder" and navigate to your "ItsShowtime" folder (which is in your home folder).&lt;/li&gt;&lt;li&gt;Drag the "ShowTime.png" image file into the "128" box on the "Icon Composer" screen.  When prompted about sizes, choose "Copy to all smaller sizes" and then click the "Import" button.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Go into the "File" menu and select the "Save" option.  Then deselect the "Hide extension" option and save as "ShowTime.icns".&lt;/li&gt;&lt;li&gt;Quit "IconComposer".&lt;/li&gt;&lt;/ol&gt;Next we'll create a Mac application (with your new icon).&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;8) Bundle the JAR&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-bundler.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-bundler-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Using "Finder", navigate into the "Developer:Applications:Utilities" folder and double-click "Jar Bundler".&lt;br /&gt;&lt;br /&gt;Steps:&lt;ol style="list-style-type: lower-alpha; font-size: 12px; margin-top: 3px; "&gt;&lt;li&gt;For the "Main Class:", use the "Choose..." button and go to and choose "ShowTime.jar".&lt;/li&gt;&lt;li&gt;Check the "Use Macintosh Menu Bar" option.&lt;/li&gt;&lt;li&gt;Use the "Choose Icon..." button to choose the "SnapBackup.icns" file (you'll need to navigate to the very top-level folder and then into the "Users" folder and your home folder to eventually find the "ItsShowtime" folder).&lt;/li&gt;&lt;li&gt;Click the "Properties" tab and enter "1.0" into the "Version:" field.&lt;/li&gt;&lt;li&gt;Also enter "1.0" into the "Get-Info String:" filed.&lt;/li&gt;&lt;li&gt;Click the "Create Application..." button.&lt;/li&gt;&lt;li&gt;Navigate into the "ItsShowtime" folder.&lt;/li&gt;&lt;li&gt;In the "File:" field, enter "Show Time".&lt;/li&gt;&lt;li&gt;Click the "Create" button.&lt;/li&gt;&lt;li&gt;Quit "Jar Bundler".&lt;/li&gt;&lt;/ol&gt;You now have a proper Mac application.  Next we'll create an installer for your application.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;9) Create Mac Installer&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-packager.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-packager-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Using "Finder", navigate into the "Developer:Applications:Utilities" folder and double-click "PackageMaker".&lt;br /&gt;&lt;br /&gt;Steps:&lt;ol style="list-style-type: lower-alpha; font-size: 12px; margin-top: 3px; "&gt;&lt;li&gt;In the "Organization:" field on the "Install Properties" window, enter "com.centerkey".  Then click "OK".&lt;/li&gt;&lt;li&gt;In the "Title:" field enter "Show Time".&lt;/li&gt;&lt;li&gt;Go to the "Project" menu and select "Add Contents...".  Navigate to "ItsShowtime" folder and select "Show Time".&lt;/li&gt;&lt;li&gt;Click on the "Contents" tab.  Check the "Include root in package" option and click the "Apply Recommendations" button.&lt;/li&gt;&lt;li&gt;Now click the "Build" (hammer) button.  In the "Save As:" field, enter "ShowTimeInstaller.pkg".  Click the "Save" button and then the "Return" button.&lt;/li&gt;&lt;li&gt;Go to the "File" menu and select "Save".  In the "Save As:" field, enter "ShowTime.pmdoc" and then click "Save".&lt;/li&gt;&lt;li&gt;Quit "PackageMaker".&lt;/li&gt;&lt;/ol&gt;Your installer is done, but it's not yet download friendly.&lt;br /&gt;&lt;br /&gt;&lt;h3 style="color: rgb(0, 0, 139); font-size: 16px; margin-bottom: 5px; "&gt;10) Put Installer on a Web Page&lt;/h3&gt;&lt;a href="javascript:popupImage('graphics/step-web.png')" style="color: rgb(112, 128, 144); font-weight: bold; text-decoration: none; "&gt;&lt;img src="http://www.centerkey.com/mac/java/graphics/step-web-icon.png" class="stage_right" title="Screenshot" alt="Screen" style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; float: right; margin-top: 0px; margin-right: 0px; margin-bottom: 15px; margin-left: 15px; " /&gt;&lt;/a&gt;Before putting the installer on the web, we need to zip it up into a single file.  Use "Finder" to navigate to the "ItsShowtime" folder.  Create a zip of "ShowTimeInstaller.pkg" using the "Compress" option on the &lt;em style="font-weight: bold; "&gt;&lt;ctrl-click&gt;&lt;/ctrl-click&gt;&lt;/em&gt; menu.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-8304634787066803971?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/y3E1_g1LwYc-qKZZQ1WU2UxGOF0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/y3E1_g1LwYc-qKZZQ1WU2UxGOF0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/y3E1_g1LwYc-qKZZQ1WU2UxGOF0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/y3E1_g1LwYc-qKZZQ1WU2UxGOF0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/OqZcCyLaOZE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/8304634787066803971/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=8304634787066803971" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/8304634787066803971?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/8304634787066803971?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/OqZcCyLaOZE/instalador-para-mac-de-uma-aplicacao.html" title="Instalador para Mac de uma aplicação Java" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/07/instalador-para-mac-de-uma-aplicacao.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIDRXY9eSp7ImA9WxBRE0Q.&quot;"><id>tag:blogger.com,1999:blog-4447358400792645990.post-6743448887256830246</id><published>2009-06-29T22:50:00.003-03:00</published><updated>2010-01-02T00:16:14.861-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-02T00:16:14.861-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="grails" /><title>Logging com Grails 1.1</title><content type="html">Hoje fiquei tentando entender a configuração do Logging no grails 1.1...pois mudou um pouco.&lt;br /&gt;&lt;br /&gt;Tem um bom exemplo &lt;a href="http://ericbweimer.blogspot.com/2009/06/grails-logging.html"&gt;aqui&lt;/a&gt;, que eu reproduzo abaixo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;log4j = {&lt;br /&gt;&lt;br /&gt;  appenders {&lt;br /&gt;     console name:'console', threshold:Level.ERROR,&lt;br /&gt;        layout:pattern(conversionPattern: '%p %d{ISO8601} %c{4} %m%n')&lt;br /&gt;     rollingFile name:"rollingFileTrace", threshold:Level।TRACE, maxFileSize:1048576,&lt;br /&gt;        file:logFile+'Trace।log', layout:pattern(conversionPattern: '%p %d{ISO8601} %c{5} %m%n')&lt;br /&gt;     rollingFile name:"rollingFileDebug", threshold:Level।DEBUG, maxFileSize:1048576,&lt;br /&gt;        file:logFile+'Debug.log', layout:pattern(conversionPattern: '%p %d{ISO8601} %c{5} %m%n')&lt;br /&gt;     rollingFile name:"rollingFileError", threshold:Level.ERROR, maxFileSize:1048576,&lt;br /&gt;        file:logFile+'Error.log', layout:pattern(conversionPattern: '%p %d{ISO8601} %c{5} %m%n')&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;  error console, rollingFileDebug, rollingFileError, rollingFileTrace:&lt;br /&gt;     'org.codehaus.groovy.grails.web.servlet',  //  controllers&lt;br /&gt;     'org.codehaus.groovy.grails.web.pages', //  GSP&lt;br /&gt;     'org.codehaus.groovy.grails.web.sitemesh', //  layouts&lt;br /&gt;     'org.codehaus.groovy.grails."web.mapping.filter', // URL mapping&lt;br /&gt;     'org.codehaus.groovy.grails."web.mapping', // URL mapping&lt;br /&gt;     'org.codehaus.groovy.grails.commons', // core / classloading&lt;br /&gt;     'org.codehaus.groovy.grails.plugins', // plugins&lt;br /&gt;     'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration&lt;br /&gt;     'org.springframework'&lt;br /&gt;&lt;br /&gt; debug rollingFileDebug, rollingFileTrace:'org.hibernate',&lt;br /&gt;     'com.britetab',&lt;br /&gt;     'BootStrap',&lt;br /&gt;     'org.apache.ddlutils'&lt;br /&gt;&lt;br /&gt; trace rollingFileTrace:'org.hibernate.SQL',&lt;br /&gt;    'org.hibernate.type',&lt;br /&gt;    'flex.messaging.services'&lt;br /&gt;&lt;br /&gt; warn  console,rollingFileDebug,rollingFileTrace:'org.mortbay.log',&lt;br /&gt;     'org.hibernate.tool.hbm2ddl'&lt;br /&gt;&lt;br /&gt; root {&lt;br /&gt;    trace 'rollingFileTrace'&lt;br /&gt;    debug 'rollingFileDebug','rollingFileTrace'&lt;br /&gt;    error 'console','rollingFileError','rollingFileDebug','rollingFileTrace'&lt;br /&gt;    additivity = true&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4447358400792645990-6743448887256830246?l=felipenasc.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3GWhcts95CZ1MxYIy3Zaae754Qw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3GWhcts95CZ1MxYIy3Zaae754Qw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3GWhcts95CZ1MxYIy3Zaae754Qw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3GWhcts95CZ1MxYIy3Zaae754Qw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/WHRf/~4/r27_vs4mEZ0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://felipenasc.blogspot.com/feeds/6743448887256830246/comments/default" title="Postar comentários" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4447358400792645990&amp;postID=6743448887256830246" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/6743448887256830246?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4447358400792645990/posts/default/6743448887256830246?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/WHRf/~3/r27_vs4mEZ0/logging-com-grails-11.html" title="Logging com Grails 1.1" /><author><name>Felipe Nascimento</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://felipenasc.blogspot.com/2009/06/logging-com-grails-11.html</feedburner:origLink></entry></feed>

