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:
http://bristle.com/Tips/CloudComputing.htm#aws
Abcs a todos.
Dicas e passo a passo para iniciar com o Amazon Web Services - AWS (em inglês)
Grails: problema com uso de herança nos Controllers
Ao fazer uma revisão na performance de uma aplicação Grails, acabei me deparando com um problema muito esquisito.
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.
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....
Então criei uma action de teste simples no meu controller filho:
class FilhoController extends PaiController {
def teste = {
render "ola"
}
}
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.
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........
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:
beans = {
webHelper(com.minhaapp.web.WebHelper) { bean ->
bean.scope = 'prototype' // aqui pode ser singleton se vc preferir
bean.autowire = 'byName'
applicationTagLib = ref('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
}
}
E a classe WebHelper então ficou assim:
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
}
}
Abcs a todos.
Reportagens sobre Grails na revista Wide
Pessoal
a revista Wide 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 NoiteUniversitaria.com.br ( e comento um pouco sobre o caso do Manubia ).
A outra é uma entrevista com o Graeme Rocher, desenvolvedor líder do projeto Grails.
Interessante a revista. (não estou ganhando $$ com a revista não hein)....
Abcs a todos.
Grails e Roo: screencast de comparação ao gerar uma mesma aplicação
Olá pessoal,
venho dando uma olhada no Spring Roo. 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.
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.
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 é:
- Criar projeto
- Configurar persistência com Hibernate e Hypersonic DB in Memory (só Roo precisa deste passo)
- Criar entidade Project
- Criar atributos com validação: name, beginDate, active
- Criar 2 finders com os atributos active e beginDate (só Roo precisa deste passo)
- Configurar Log (só Roo precisa deste passo)
- Configurar arquivos Eclipse (só Roo precisa deste passo)
- Gerar Controller e views
- Executar a aplicação.
Aí vão os vídeos. 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 :-)
Abraços a todos.
Vídeo 1: Gerando com Roo
Vídeo 2: Gerando com Grails
Tudo sobre Grails GORM e as relações One-To-Many, Many-To-One e Many-To-Many
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?
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.
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.
Há um excelente resumo escrito por Peter Ledbrook no blog da SpringSource.
http://blog.springsource.com/2010/07/02/gorm-gotchas-part-2/
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 Parte 1.
Abcs
Felipe
Grails TagLib em qualquer classe
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:
def grailsTags = grailsApplication.mainContext.getBean( 'org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib' )
String msg = grailsTags.message(code:'exemplo.de.mensagem')
Abcs
Escalabilidade de aplicações Web: futuro vs presente = Cassandra vs Mysql+memcached
Muito interessante o post do Digg 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.
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.
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 Facebook possuía mais de 800 servidores de memcached para poder servir mais de 28 terabytes de cache. É mole? 28 Tera de cache! E isso, só para poder servir a leitura de dados em cache. Na hora de escrever os dados, aí usa-se uma solução de Mysql configurado com Master-Slave, e muitas vezes com particionamento vertical.
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 Cassandra.
Cassandra é um banco de dados distribuído, altamente escalável, baseado no conceito de BigTable.
É isso. E vem por aí uma nova era para as soluções de aplicações web de alto volume.
Vale a leitura do post do Digg.
Abcs
GWT + Grails = Rock n Roll: Parte 2 - Separados e falando com RequestBuiler e JSON
Este post é a Parte 2 da sequência de posts sobre o tema GWT + Grails = Rock n Roll. Você pode ver a Parte 1 aqui. Nesta primeira mostrei como criar uma aplicação baseada em GWT e Grails. Para juntar os dois, usei o plugin Grails-Gwt.
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.
Separando Grails e GWT em duas aplicações distintas
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 ProxyServlet, 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 é:
- a aplicações GWT no cliente faz uma requisição para o servidor;
- a aplicações GWT no servidor recebe esta requisição e repassa para a aplicação Grails
- a aplicação Grails recebe esta requisição e responde JSON
- a aplicação GWT recebe esta resposta JSON e repassa para o cliente GWT
Desta forma não precisamos nos preocupar com SOP.
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?
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 Life Above the Service Tier (vale a leitura. Este pessoa hoje em dia criou um grupo sobre este assunto e tem um site em: ThinServerArchitecture.com ).
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.
Outras duas justificativas para esta separação em duas aplicações são:
- Pode ficar mais simples equipes diferentes trabalharem cada uma em um projeto diferente
- Cada projeto pode ser versionado independentemente
Comunicação entre GWT e Grails com JSON
Para a comunicação entre o Front-End e o Back-End, escolhi usar JSON. A aplicação grails pode facilmente gerar uma resposta JSON, enquanto que a aplicação GWT pode facilmente consumir JSON. 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.
Portanto, para criarmos esta nova aplicação, basta criar um novo projeto GWT, e outro Grails.
Aplicação Front-End (GWT)
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
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. Depois altere a classe Rockgwtfront.java para não usar mais este Serviço RPC. No final das contas, fiquei com a classe de EntryPoint abaixo:
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<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()));
}
}
}
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.
Veja que a aplicação GWT espera um retorno JSON no seguinte formato:
[{"name":"Hey Joe", "album":"Are You Experienced"},
{"name":"Bold as Love", "album":"Axis: Bold as Love"}]
Portanto, é preciso que a aplicação Grails retorne um JSON exatamente neste formato acima.
É preciso adicionar ao ~/rockgwtfront/war/WEB-INF/lib 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:
<web-app> <servlet> <servlet-name>RockServletservlet-name> <servlet-class>com.rockgwt.front.servlet.ProxyServletservlet-class> <init-param> <param-name>proxyHostparam-name> <param-value>localhostparam-value> init-param> <init-param> <param-name>proxyPortparam-name> <param-value>8080param-value> init-param> <init-param> <param-name>secureparam-name> <param-value>falseparam-value> init-param> servlet> <servlet-mapping> <servlet-name>RockServletservlet-name> <url-pattern>/rockgwt/*url-pattern> servlet-mapping> <welcome-file-list> <welcome-file>Rockgwtfront.htmlwelcome-file> welcome-file-list>
web-app>
Veja que o servlet-mapping mostra como deverá ser a url a ser chamada pelo cliente GWT para o servidor Grails. ( /rockgwtback/* ).
Aplicação Back-End (Grails)
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:
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'
}
}
}
}
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
É isso!
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.
Grails + GWT = Rock n Roll: Parte 1 - Desbravando um novo mundo
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 bom Lynyrd Skynyrd 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.
- - a DAO está bem resolvida,
- - os Serviços estão lá e cumprem seu papel (de controle transacional, por exemplo),
- - os Controllers também tem seu papel de fronteira entre o mundo HTTP e nossas regras de negócio,
- - 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.
- - Instalar o SDK do GWT
- - Criar a variável de ambiente GWT_HOME apontando para a raiz do SDK do GWT
- - Instalar o Plugin de Eclipse do GWT
- - Criar uma aplicação pura e simples GWT usando o plugin do eclipse.
- - 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á).
- - Garantir que o browser instalou o plugin de execução do GWT.
- - Executar esta aplicação e brincar um pouco com os diferentes Layouts de GWT.
- - Criar uma nova aplicação Grails com o comando grails create-app rockgwt
- - Vai pra dentro dela ( cd rockgwt )
- - Instalar o plugin GWT do Grails (usando o comando grails install-plugin gwt ). Eu estou usando o grails 1.2.x e o plugin 0.5
- - Criar um GWT Module com o comando do plugin grails create-gwt-module com.rockgwt.RockNRoll
- - 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:
- 1) grails create-controller com.rockgwt.controller.Principal
- 2) grails create-gwt-page principal/index.gsp com.rockgwt.RockNRoll (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á).
- - Compilar o seu módulo com o comando grails compile-gwt-modules (demora um pouquinho mesmo)
- - Executar o Development Mode com o comando grails run-gwt-client Perceba que vai se abrir a janela da aplicação Development Mode do GWT
- - Abra outro Terminal , vá para o seu projeto rockgwt e execute a aplicação grails (é isso mesmo, você terá duas coisas rodando: o grails run-app da aplicação, e o grails run-gwt-client anterior, do GWT).
- - 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
- - 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.
- - O endereço que você quer acessar no final de tudo será o seu controler Principal, ou seja:
http://localhost:8080/rockgwt/principal/index?gwt.codesvr=127.0.0.1:9997 - - 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.
package com.rockgwt.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class RockNRoll implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
final Button sendButton = new Button("Rock n Roll");
RootPanel.get().add(sendButton);
}
}
UPDATE (8/3/2010):
- 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 > Use As Source Folder
- E por último clique com o direito do mouse em cima do projeto rockgwt e selecione a opção Google > 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.
Executando códigos diferentes em Desenvolvimento e Produção
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.
import grails.util.Environment;
class MeuController{
Environment.executeForCurrentEnvironment {
production {
// AQUI vai o código que deve ser executado em produção
}
development {
// AQUI vai o código a ser executado em desenvolvimento.
}
}
}
Boas informações sobre grails em português
Pessoal
Grails e datas: Bind automático de atributo do tipo Date com formato customizado
Segue uma pequena receita de bolo para quem não está usando o datePicker padrão do Grails.
Pessoa tx = new Pessoa(params)
package com.meusistema.editor;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.i18n.LocaleContextHolder;
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
def messageSource;
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(messageSource.getMessage("dateFormat4y",null,'dd/MM/yyyy',LocaleContextHolder.locale )),true));
}
}
dateFormat4y=dd/MM/yyyy
beans = {
customPropertyEditorRegistrar(com.manubia.propertyeditor.CustomPropertyEditorRegistrar) {
messageSource = ref('messageSource')
}
}