Nos últimos artigos de Desenvolvimento em Java 2.0, eu desenvolvi sobre um aplicativo simples de nuvem para dispositivo móvel. Esse aplicativo, denominado Magnus, atua como um terminal HTTP que atende informações de localização de dispositivos móveis. Ele funciona recebendo solicitações HTTP PUT, cada uma contendo um documento JSON que indica um local de conta em determinado momento. Até agora, usei o Play na estrutura da Web para desenvolver e ampliar o Magnus (consulte Recursos).
O Play é muito parecido com o Grails, pois fornece uma pilha MVC. Com o Play, é possível definir facilmente os controladores (servlets) que alavancam visualizações (JSPs, GSPs, modelos, entre outros) que, de alguma forma, manipulam modelos. Os modelos são implementados usando POJOs (plain old Java objects) aprimorados com Hibernate, JPA ou outra tecnologia eficiente semelhante a ORM.
Embora o MVC seja um padrão antigo, muita coisa mudou com o advento de estruturas como Grails e Play. Lembrando do esforço necessário para manter uma simples interação de solicitação-reposta da Web — usando o Struts, por exemplo — é possível reconhecer o quanto avançamos rapidamente até os aplicativos da Web MVC desenvolvidos. Além disso, nem todos os aplicativos da Web necessitam da infraestrutura MVC para funcionar. Atualmente, alguns aplicativos da Web não necessitam de uma "pilha" MVC.
Antes de fechar seu navegador como protesto contra uma declaração tão absurda, lembre-se do Magnus. Embora seja desenvolvido estritamente com a finalidade de demonstração, meu aplicativo de nuvem para dispositivo móvel não contém nenhum componente de visualização tradicional e apresenta seu próprio modelo fora de serviços existentes bem-sucedidos. Como o Twitter ou o Foursquare, o Magnus recebe mensagens de dispositivos diferentes ao redor do mundo. De maneira abrangente, o Magnus é um serviço da Web, e nem todo serviço da Web precisa de uma estrutura de pilha MVC para fazer ou trabalho. Em alguns casos, é necessária somente uma estrutura leve da Web sem a pilha da Web.
Este mês, nossa atenção estará voltada para: uma estrutura de desenvolvimento rápida, tão nova, que ainda não possui sua própria página inicial e, talvez, nem precise de uma. A linhagem e as afiliações do Gretty (incluindo o Netty e o Groovy, respectivamente) são tão respeitáveis, que já fazem parte da família de desenvolvimento da Web Java 2.0. Ele preenche uma necessidade que muitos desenvolvedores não sabem que possuem (esse é o verdadeiro estilo da Web 2.0, não sabia?). E é estável o bastante para uso de produção — se você quiser enfrentar o desafio.
Um histórico de desenvolvimento Java rápido
Se você se lembra de quando a API de Servlets foi apresentada, tem motivos para estar incrédulo sobre o novo paradigma "leve", um simples servlet permite desenvolver um serviço da Web sem muitos códigos e, consequentemente, arquivos JAR, apesar de tudo. Estruturas de serviço da Web, como Restlet ou Jersey, adotam uma abordagem diferente para a velocidade de desenvolvimento, desenvolvendo extensões de classe, anotações e até mesmo JSRs padrão para criar serviços da Web RESTful. Ambos ainda são boas opções para alguns cenários.
No entanto, isso revela que algumas novas estruturas leves (ao contrário das antigas leves) estão criando serviços da Web ou simples terminais HTTP (também conhecidos como rotas), muito simples de serem definidos. Mais simples do que criar um servlet manualmente!
Essas estruturas surgiram primeiramente em outras plataformas, particularmente, para Ruby e Express para Node.js. Porém, projetos interessantes também surgiram para a plataforma Java. Um deles é o Gretty, criado para o Groovy e JVM.
O Greety possui pelo menos duas vantagens: a primeira é seu uso do Grape do Groovy (que descreverei a seguir, com mais detalhes) para facilitar o gerenciamento da dependência. A segunda é sua sintaxe simples, semelhante a DSL, para definir terminais. Com o Greety, é possível definir rapidamente (com apenas algumas linhas de código curtas) e implementar uma estrutura de roteamento da Web funcional que manipule a lógica de negócios real. Por exemplo, observe a preparação rápida do exemplo hello world ideal na Listagem 1:
Lista 1. Hello, World: It's Gretty!
import org.mbte.gretty.httpserver.*
@GrabResolver(name='gretty',
root='http://groovypp.artifactoryonline.com/groovypp/libs-releases-local')
@Grab('org.mbte.groovypp:gretty:0.4.279')
GrettyServer server = []
server.groovy = [
localAddress: new InetSocketAddress("localhost", 8080),
defaultHandler: {
response.redirect "/"
},
"/:name": {
get {
response.text = "Hello ${request.parameters['name']}"
}
}
]
server.start()
|
Na Listagem 1, foi criada uma listagem de servidores na porta 8080 e um terminal raiz simples foi criado, contendo o parâmetro name. Qualquer solicitação de outro terminal será roteada de volta para / por meio de defaultHandler. O manipulador basicamente envia ao cliente solicitante um código "movido permanentemente" HTTP 301, com a localização de /. Todas as solicitações receberão uma resposta (com o tipo de conteúdo configurado para texto/simples) contendo a cadeia de caractere "Hello" juntamente com o valor do parâmetro informado, por exemplo, /Andy geraria "Hello Andy".
Então, o que é interessante na Listagem 1? Primeiramente, o que está na listagem é todo o necessário para o aplicativo. Não há arquivos de configuração. Não foi necessário fazer download ou instalar nada diretamente (além do Groovy 1.8). Para criar este exemplo, simplesmente digitei groovy server.groovy.
Mas e se suas respostas precisarem de mais sofisticação do que um simples texto? Para isso, o Gretty possui diversas opções, duas das quais são muito fáceis. Primeiramente, é possível somente configurar o tipo de resposta para HTML, como na Listagem 2:
Lista 2. Respostas HTML no Gretty
"/:name": {
get {
response.html = "Hello ${request.parameters['name']}"
}
}
|
Nesse caso, o tipo de conteúdo da resposta seria configurado para text/html. Como alternativa, o Gretty possibilita alavancar modelos estáticos e dinâmicos. Por exemplo, é possível definir um modelo usando um desenvolvimento simples como JSP/GSP, como na Listagem 3:
Lista 3. Um modelo HTML no Gretty
<html>
<head>
<title>Hello!</title>
</head>
<body>
<p>${message}</p>
</body>
</html>
|
É possível referenciar um modelo no corpo de uma resposta:
Lista 4. Um modelo Groovy++ no Gretty
"/:name" {
get {
response.html = template("index.gpptl",
[message: "Hello ${request.parameters['name']}"])
}
}
|
Gerenciamento de dependência com o Gretty e o Grape
Parte do desenvolvimento rápido do Greety deve-se ao Grape (consulte Recursos), usado para fazer download automaticamente de dependências binárias ou arquivos JAR. Todos os arquivos são carregados com dependências transitivas no estilo Maven. Na Listagem 1, foi necessário somente digitar a anotação @Grab('org.mbte.groovypp:gretty:0.4.279'), e o arquivo JAR associado ao Gretty foi obtido, juntamente com as dependências do Gretty. A anotação @GrabResolver(name='gretty', root='http://groovypp.artifactoryonline.com/groovypp/libs-releases-local') indicou onde o Grape poderia localizar os arquivos necessários.
O Grape pode parecer simples, mas isso não significa que seja inadequado para a produção. Na verdade, o download automático das dependências necessárias do Grape não é diferente do download do Maven. Ele é apenas feito no tempo de execução, na primeira vez que um aplicativo é executado, enquanto que o Maven faz download das dependências necessárias no tempo de desenvolvimento. Se o Grape puder localizar as dependências necessárias localmente, não será preciso fazer download. Os JARs são colocados automaticamente no caminho de classe do aplicativo. Como resultado, o custo do desempenho é pago apenas na primeira vez em que um aplicativo configurado pelo Grape for executado. Além disso, sempre que a versão necessária de uma dependência especificada for alterada, será possível perceber uma ligeira melhora no desempenho.
Até agora, vimos que o Gretty é simples, o que facilita a execução do desenvolvimento com rapidez. Além disso, o Gretty (ou estruturas semelhantes a ele) está perfeitamente adaptado para aplicativos como o Magnus — Terminais HTTP que atendem dados. Veremos o que acontece quando uma estrutura leve, como o Play ou Grails, é substituída por um aplicativo ainda mais leve criado com o Gretty.
Para esse modelo do Magnus, serão usados o Morphia e o MongoHQ, dos quais é possível se recordar por meio do meu artigo Introdução ao Amazon Elastic Beanstalk. Para alavancar o utilitário Grape do Groovy com a nova configuração, será preciso incluir as anotações da Listagem 5 ao servidor:
Lista 5. Incluindo o Morphia e suas dependências
@GrabResolver(name='morphia', root='http://morphia.googlecode.com/svn/mavenrepo/') @Grab(group='com.google.code.morphia', artifactId='morphia', module="morphia", version='0.99') |
Minhas classes Morphia são as mesmas que usadas em versões anteriores do Magnus: possuo uma Account e uma Location. Neste terminal, estou somente atualizando um local para uma determinada conta. Como os clientes do Morphia enviarão documentos JSON para o terminal do Gretty, também usarei o Jackson, uma estrutura de manipulação de JSON eficiente, que já faz parte dos elementos internos do Gretty. Devido à manipulação do Grape de dependências transitivas, tenho acesso ao que é necessário para analisar o documento JSON recebido e transformá-lo em um simples Java Map.
Lista 6. Atualizando locais no Gretty
def server = new GrettyServer().localAddress(new InetSocketAddress("localhost", 8080)).
"/location/:account" {
put {
def jacksonMapper = new ObjectMapper()
def json = jacksonMapper.readValue(request.contentText, Map.class)
def formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm")
def dt = formatter.parse(json['timestamp'])
def res = [:]
try{
new Location(request.parameters['account'], dt, json['latitude'].doubleValue() ,
json['longitude'].doubleValue() ).save()
res['status'] = 'success'
}catch(exp){
res['status'] = "error ${exp.message}"
}
response.json = jacksonMapper.writeValueAsString(res)
}
}
server.start ()
|
Como é possível ver na Listagem 6, um elemento Map do documento JSON recebido é criado (json com dub efetuado) e inserido de forma correspondente no MongoDB por meio da classe Location
na Listagem 7:
Lista 7. Criando o documento de localização — Recorrência do Gretty
import com.google.code.morphia.annotations.Entity
@Entity(value = "locations", noClassnameStored = true)
class Location extends AbstractModel {
String accountId
double latitude
double longitude
Date timestamp
public Location(String accountId, Date timestamp, double lat, double lon) {
this.accountId = accountId
this.timestamp = timestamp
this.latitude = lat
this.longitude = lon
}
}
|
Além disso, minha Location possui uma superclasse Groovy, mostrada na Listagem 8:
Lista 8. Classe base do local
import com.google.code.morphia.Morphia
import com.google.code.morphia.annotations.Id
import com.mongodb.Mongo
import org.bson.types.ObjectId
abstract class AbstractModel {
@Id
private ObjectId id;
def save() throws Exception {
def mongo = new Mongo("fame.mongohq.com", 32422)
def datastore = new Morphia().createDatastore(mongo, "xxxx",
"xxxx", "xxxx".toCharArray())
datastore.save(this)
return this.id
}
}
|
É possível lembrar-se desse código da Listagem 3 de "Escale o Elastic Beanstalk." A única mudança feita para a implementação do Gretty foi renomear o arquivo real de Location.java para Location.groovy, o que significa que não é necessário compilá-lo antes de disparar o servidor. Também foi incluída uma classe base. O local está vinculado a uma conta por meio do parâmetro recebido account obtido do URI.
Uma resposta é enviada ao JSON indicando êxito. No caso de um erro, outra resposta é gerada.
Conclusão: o Gretty está pronto
O Gretty é tão leve quanto é possível. Não há estrutura ORM integrada. Não há estrutura de visualização robusta, à exceção do modelo simples, mas a conexão em outra estrutura é completamente realizável. Isso significa que o Gretty não está pronto para o uso diário? A falta de uma estrutura de teste implica no mesmo? A resposta é não: em primeiro lugar, o Gretty é desenvolvido com base no código bem conceituado do Netty, portanto, obtém-se alguma garantia logo no início. Em segundo lugar, é possível testar o Gretty do mesmo modo que em qualquer terminal da Web, automaticamente ou não. Na verdade, se quiser saber como o Gretty faz o teste, verifique seu código de origem — ele possui muitos testes!
O Gretty é a antítese da moderna estrutura da Web de pilha completa, precisamente porque, às vezes, não é necessária uma pilha completa. Se você estiver exigindo muito de uma estrutura como o Gretty, talvez tenha mais sucesso com uma das muitas bem documentadas estruturas da Web Java de pilha completa. Porém, se você acredita que não é necessária uma pilha completa para manipular solicitações e repostas de serviço da Web, o Gretty pode ser exatamente o que você precisa.
Aprender
- "Groovy++ in action: Gretty/GridGain/REST/Websockets" (Alex Tkachman, DZone, Maio de 2011): Pouco foi escrito até agora sobre o Gretty. Essa introdução oferece alguns aplicativos de exemplo implementados com o Groovy++.
- Desenvolvimento em Java 2.0: Esta série do dW explora tecnologias que estão redefinindo o cenário de desenvolvimento Java. Os tópicos incluem
Amazon Elastic Beanstalk (fevereiro de 2011), JavaScript para Desenvolvedores Java (Abril de 2011), MongoDB (Setembro de 2010) e NoSQL (maio de 2010).
- Guia do usuário do Grape: Curioso sobre o Grape? Acesse uma introdução rápida do guia do usuário do Codehaus.
- Página inicial do Netty: Saiba mais sobre a estrutura do soquete cliente-servidor do Java NIO.
- "Getting started with new I/O (NIO)" (Greg Travis, developerWorks, Julho de 2003): Este tutorial prático cobre a biblioteca NIO, incluindo buffers e canais, E/S assíncronas e buffers diretos.
- Knowledge path: Cloud computing fundamentals (março de 2011): Apresenta conceitos de computação em nuvem e os modelos de serviço IaaS, PaaS e SaaS.
- Guia do Scala para desenvolvedores de Java atarefados (Ted Neward, 2008-2009): Ted Neward mergulha na linguagem de programação Scala, fornecendo uma abordagem sobre seus recursos linguísticos em ação.
-
Navegue pela
livraria da tecnologia Java para ver livros sobre este e outros tópicos técnicos.
-
Zona tecnologia Java do developerWorks: Encontre centenas de artigos sobre quase todos os aspectos da programação Java.
Obter produtos e tecnologias
- O framework Play: Enfoca a produtividade do desenvolvedor e busca arquiteturas RESTful.
- Faça o download do Gretty: Tudo o que você precisa para começar é o Groovy 1.8.0.
- Faça o download das
versões de avaliação de produto IBM ou explore as versões de teste on-line no IBM SOA Sandbox e entre em contato com as ferramentas de desenvolvimento de aplicativos e produtos de middleware do DB2®, Lotus®, Rational®, Tivoli® e WebSphere®.
Discutir
- Participe da comunidade do developerWorks. Entre em contato com outros usuários do developerWorks, enquanto explora os blogs, fóruns, grupos e wikis orientados ao desenvolvedor.

Andrew Glover é desenvolvedor, autor, palestrante e empreendedor com uma paixão por desenvolvimento direcionado por comportamento, integração contínua e desenvolvimento de software Agile. Ele é o fundador da easyb, estrutura Behavior-Driven Development (BDD) e é coautor de três livros: Continuous Integration, Groovy in Action, e Java Testing Patterns. Você pode acompanhá-lo em seu blog e seguindo-o no Twitter.