Desenvolvimento em Java 2.0: Serviços da Web Java Ultraleves com o Gretty

O Gretty reduz a pilha da Web para o desenvolvimento de aplicativo real rápido

O Gretty é um dos novos métodos de estruturas ultraleves criadas para o desenvolvimento de serviços da Web. Desenvolvido sobre APIs Java™ NIO rápidas, o Gretty aproveita o Groovy como uma linguagem específica de domínio para terminais da Web e gerenciamento de dependência no estilo Maven do Grape. Neste artigo, inicie o uso do Gretty para desenvolver e implementar aplicativos de serviços da Web Java.

Andrew Glover, Author and developer, Beacon50

Andrew GloverAndrew 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.



31/Ago/2011

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).

Sobre esta série

O panorama de desenvolvimento em Java mudou radicalmente desde que a tecnologia Java emergiu. Graças a estruturas maduras de software livre e infraestruturas de implementação confiáveis de aluguel, agora é possível montar, testar, executar e manter aplicativos Java de forma rápida e barata. Nesta série, Andrew Glover explora o espectro de tecnologias e ferramentas que tornam este novo paradigma de desenvolvimento Java possível.

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.


Apoio o Gretty

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".

Gretty e NIO

O Gretty foi desenvolvido usando o Netty, uma estrutura cliente-servidor que usa de maneira completa as bibliotecas NIO do Java. O pacote NIO, ou New I/O, das bibliotecas de E/S foi introduzido há certo tempo, quando o Java 1.4 surgiu. O NIO chama a atenção por suas operações de E/S sem bloqueio, o que permite desenvolvimento de servidor escalável. Isso é útil com estruturas como Netty e Gretty.

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 Gretty não é somente Groovy

O Gretty não está limitado à linguagem do Groovy. Como tudo o que é executado na JVM, é possível tentar criar aplicativos Gretty na linguagem Java ou até mesmo Scala.

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.


O Gretty contra o Magnus

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.

Recursos

Aprender

Obter produtos e tecnologias

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.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Cloud computing, Software livre
ArticleID=754922
ArticleTitle=Desenvolvimento em Java 2.0: Serviços da Web Java Ultraleves com o Gretty
publish-date=08312011