Desenvolvimento Java 2.0: REST com CouchDB e o RESTClient do Groovy

Os conceitos de RESTful e um banco de dados orientada a documentos em ação

Uma explosão de inovação no mundo de software livre nos últimos anos levou a um aumento ™ na produtividade do desenvolvedor Java. Ferramentas, estruturas e soluções gratuitamente disponíveis resolvem as perdas de tempo anteriormente comuns. Uma nova promissora aparição em cena é o Apache CouchDB, aclamado por alguns como o banco de dados para a Web 2.0. A visão global do CouchDB é fácil de entender e usá-lo é tão simples quanto usar um navegador da Web. Esta coluna de desenvolvimento Java 2.0 introduz o CouchDB e mostra como o RESTClient do Groovy pode ajudá-lo a tirar vantagem de seus pontos fortes.

Andrew Glover, Author and developer

Andrew GloverAndrew Glover é desenvolvedor, autor, palestrante e empresário com uma paixão por desenvolvimento orientado a comportamento, Integração Contínua e desenvolvimento de software Agile. É possível entrar em contato com ele em seu blog.



16/Dez/2009

Até aqui, a série desta coluna explorou a computação em nuvem com ambas as plataformas, Google e Amazon. Apesar de elas serem diferentes em implementação e estrutura, ambas as plataformas possibilitam a implementação rápida e escalável. Elas possibilitam, como nunca antes, a montagem, o teste, a execução e a manutenção de aplicativos Java de forma rápida e barata. Mas a nuvem não é o único fator que afeta a velocidade do desenvolvimento Java atualmente. Soluções de software livre também possibilitam montar aplicativos de software rapidamente porque não é mais necessário escrever tantos códigos. Já se foram os dias de escrever seu próprio mapeamento objeto-relacional (ORM), criação de log ou estrutura de teste. Esses problemas foram resolvidos várias vezes na área de software livre e — , admita, — essas soluções quase sempre são melhores que as suas.

Sobre esta série

O panorama do desenvolvimento Java mudou radicalmente desde que a tecnologia Java surgiu pela primeira vez. Graças às estruturas amadurecidas do software livre e às infraestruturas de desenvolvimento alugáveis confiáveis, 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 possível esse novo paradigma de desenvolvimento Java.

No espectro inteiro do desenvolvimento Java, a inovação do software livre está tornando os aplicativos mais fáceis de montar. O Apache CouchDB, um novo banco de dados de software livre (no release 0.10.0 quando este artigo foi escrito), não é uma exceção. É fácil começar com o CouchDB depois que ele está em funcionamento. E tudo o que você precisa para trabalhar com ele é de uma conexão HTTP; nenhum driver JDBC é necessário, nem você precisa de uma plataforma de gerenciamento administrativo de terceiros. Neste artigo, vou apresentar a você o CouchDB e mostrar como é possível alcançar velocidade usando-o. Para uma fácil instalação, você aproveitará a plataforma EC2 do Amazon. E se comunicará com o CouchDB via um prático módulo Groovy.

Um banco de dados orientado para documentos

Bancos de dados relacionais essencialmente dominam o mercado de banco de dados. Mas outros tipos de bancos de dados — incluindo bancos de dados orientados a objetos e orientados a documentos , ambos divergindo muito do mundo orientado ao relacional,— fazem muito sentido de tempos em tempos. O CouchDB é um banco de dados orientado a documento. Ele não tem esquemas e permite armazenar documentos na forma de uma cadeia de caracteres JavaScript Object Notation (JSON).

JSON

JSON é um formato de intercâmbio de dados leve e um formato alternativo para aplicativos da Web. Ele é similar ao XML, mas muito menos datalhado. Ele está se tornando a lingua franca da Web, graças à sua natureza leve. ConsulteRecursos para saber mais sobre o JSON.

Pense numa multa por estacionamento ilegal. Este pedaço de papel contém alguns itens, incluindo:

  • A data da infração
  • O horário
  • O local
  • A descrição do seu veículo
  • As informações da sua placa de licenciamento
  • A infração

O formato e os dados reunidos em uma multa podem variar de jurisdição para jurisdição. Mesmo com um formulário de multa por estacionamento ilegal padrão dentro de uma única jurisdição, o que é ou não é capturado em um bilhete muito provavelmente varia. Por exemplo, o guarda que emite a intimação pode não preencher o horário, ou pode omitir a marca e modelo do veículo, optando por inserir apenas os detalhes da placa de licenciamento. O local pode ser a combinação de duas ruas (como o cruzamento da Fourth com a Lexington) ou apenas um endereço fixo (como Rua Principal, 19993). Mas a semântica bruta do que é reunido é similar.

Os pontos dos dados de uma multa podem ser modelados em um banco de dados relacional, mas os detalhes são um pouco complicados. Por exemplo, como você captura uma interseção efetivamente em um banco de dados relacional? E em casos nos quais nenhum cruzamento de ruas existe, o banco de dados tem um campo em branco para o segundo endereço (supondo-se que você o modelou de tal forma a capturar nomes de rua distintos em colunas individuais)?

Nesses casos, a abstração de um banco de dados relacional pode ser demasiada. As informações necessárias já estão lá na forma de um documento (a multa). Por que não simplesmente modelar os dados como um documento, o que não necessariamente se ajusta em um modelo relacional rígido, mas, em linhas gerais, segue a semântica de um modelo de alto nível? É aqui que o CouchDB entra em ação. Ele permite modelar esses tipos de domínios de uma maneira flexível — como um documento autocontido que não contém nenhum esquema, mas, em vez disso, um projeto similar, em termos gerais, a outros documentos.

MapReduce

O MapReduce, cujo precursor foi o Google, é uma estrutura conceitual para processamento de imensos conjuntos de dados (consulte Recursos). Ele é altamente otimizado para solução de problema distribuível usando um grande número de computadores. O MapReduce é a combinação de duas funções: mapear e reduzir. A função mapear é projetada para obter uma grande entrada e dividi-la em pedaços menores (e entregar esses dados a outros processos que podem fazer alguma coisa com os dados). A função reduzir é destinada a produzir todas as respostas individuais do mapa em um formato final.

Com o CouchDB, é possível procurar por documentos, propriedades de documentos e mesmo documentos relacionados exatamente como no mundo relacional. Você faz isso usando visualizações, não SQL. As visualizações são essencialmente funções que você escreve (em JavaScript) no estilo de MapReduce; isto é, você acaba escrevendo uma função mapear e uma função reduzir. Essas funções trabalham juntas para filtrar ou extrair dados dos seus documentos ou explorar relacionamentos entre eles de maneira bem eficiente. De fato, o CouchDB é inteligente o suficiente para executar essas funções somente uma vez, desde que os documentos subjacentes não mudem, o que torna as visualizações bem rápidas.

O que é particularmente interessante sobre o CouchDB é seu design. O CouchDB incorpora os conceitos básicos (e altamente bem-sucedidos) da própria Web. Ele expõe uma API completamente RESTful que permite a criação, consulta, atualização e remoção de documentos, visualizações e bancos de dados. Isso torna o CouchDB muito fácil de selecionar e trabalhar. Você não precisa de drivers ou outras plataformas para iniciar o desenvolvimento: basta um navegador. Dito isso, um host de bibliotecas está disponível, o que torna o trabalho com o CouchDB ainda mais fácil — mas na verdade, essas bibliotecas simplesmente exploram os conceitos RESTful via HTTP.

O CouchDB, bem como a própria Web, foi construída para ser escalável. Ele é escrito em Erlang, uma linguagem de programação concorrente que suporta aplicativos com construção distribuída, tolerantes a falhas e ininterruptos (consulte Recursos). A linguagem (agora disponível como software livre foi desenvolvida pela Ericsson e foi amplamente otimizada em ambientes de telecomunicações.


Instalando o CouchDB, estilo nuvem

A instalação do CouchDB varia dependendo do seu sistema operacional. Se você estiver no Windows®, precisa instalar o Cygwin, o compilador C da Microsoft, e um punhado de outras dependências relacionadas. Se você estiver em um Mac, precisa usar o Macports. Se, porém, você estiver executando em uma plataforma Linux® , como a Ubuntu, a instalação é muito fácil. Mas nem todos possuem uma instância do Ubuntu em mãos. Ou você possui?

É claro que você tem uma instância do Ubuntu em mãos! O EC2 da Amazon é uma maneira relativamente barata de usar o Ubuntu on demand. Assim, com um pouco de mágica do EC2, você terá o CouchDB funcionando imediatamente; quando terminar, você pode desligá-lo.

Primeiro, você precisará localizar uma AMI do EC2 que funcionará como uma instância base. Eu acabei usando a AMI ami-ccf615a5, uma instância do Ubuntu 9.04, que foi a versão mais recente disponível quando escrevi este artigo. (Quando você ler isto, o 9.10 estará disponível com uma AMI mais nova, muito provavelmente.) Usando o Eclipse ou o AWS Management Console, ative uma instância da ami-ccf615a5. Certifique-se de configurar uma política de segurança que permita acesso via SSH. (Apesar do CouchDB usar HTTP, você irá se comunicar com ele através de um túnel SSH por questões de simplicidade.) Você também precisará usar um par de chaves. (Se precisar de instruções, consulte os dois artigos anteriores nesta série, "You can borrow EC2" e "Easy EC2.")

Depois de ter ativado uma instância EC2 do Ubuntu 9.04, você precisa do ssh para ele. (Lembre-se de que a instância pode levar 1 minuto ou mais para inicializar completamente, portanto, tenha paciência.) Por exemplo, eu posso abrir um terminal e conectar-me por meio de ssh à mais nova instância criada, dessa forma:

aglover#> ssh -i .ec2/agkey.pem root@ec2-174-129-157-167.compute-1.amazonaws.com

O nome DNS da minha AMI era ec2-174-129-157-167.compute-1.amazonaws.com, e eu estou referenciando um par de chaves chamado agkey. O seu nome DNS e o par de chaves indiscutivelmente serão diferentes.

No prompt de comandos na instância do Ubuntu em nuvem, digite:

apt-get update

Depois digite:

aptitude install couchdb

Esses comandos automaticamente instalarão o CouchDB. Porém, observe que eles não irão instalar a versão mais recente. Você precisa instalar o CouchDB a partir da origem se desejar a versão mais recente (consulte Recursos).

Depois que os comandos terminarem de executar, é possível verificar se o CouchDB está executando emitindo um comando ps -eaf . Procure alguns processos executando com o couchdb em seu caminho canalizando a saída ps para egrep. Você deve ver alguma coisa ao longo das linhas da saída mostrada na Lista 1:

Lista 1. O CouchDB está executando (linhas quebradas para se ajustarem à largura da página do artigo)
couchdb   1820     1  0 00:54 ?        00:00:00 /bin/sh -e /usr/bin/couchdb
   -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb   1827  1820  0 00:54 ?        00:00:00 /bin/sh -e /usr/bin/couchdb
   -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb   1828  1827  0 00:54 ?        00:00:00 /usr/lib/erlang/erts-5.6.5/bin/beam
   -Bd -- -root /usr/lib/erlang -progname erl -- -home /v
couchdb   1836  1828  0 00:54 ?        00:00:00 heart -pid 1828 -ht 11

A seguir, de volta à sua máquina local, você configurará um túnel SSH que permite que você acesse a instância CouchDB que está executando na nuvem, como se ela estivesse residindo na sua própria máquina. Para fazer isso, abra uma nova sessão de terminal na sua máquina local e digite:

ssh -i sua chave -L 5498:localhost:5984 root@seu DNS da AMI

Finalmente, abra um navegador na sua máquina local. Na barra de localidade, digite http://127.0.0.1:5498/. Você deve ver uma agradável mensagem de boas-vindas no JSON, como esta:

{"couchdb":"Welcome","version":"0.8.0-incubating"}

Agora que parece que as coisas estão funcionando, você está pronto para colocar o CouchDB à prova.


Trabalhando o RESTfully com o RESTClient do Groovy

REST

Representational state transfer (REST) é um estilo de design de aplicativos da Web fracamente acoplados que conta com recursos nomeados — na forma de Uniform Resource Locators (URLs), Uniform Resource Identifiers (URIs), e Uniform Resource Names (URNs), por exemplo— em vez de por mensagens. Engenhosamente, a REST flui dados com tráfego reverso na já validada e bem-sucedida infraestrutura HTTP da — Web. Isto é, a REST otimiza aspectos do protocolo HTTP como as solicitações GET e POST. Essas solicitações mapeiam bastante adequadamente para as necessidades de aplicativo de negócios padrão como criação, leitura, atualização e exclusão (CRUD).

Porque o CouchDB expõe dados via uma interface RESTful HTTP, trabalhar com o CouchDB (como você já viu via o seu navegador) é muito fácil. Praticamente tudo o que você deseja fazer pode ser feito via HTTP.

É possível escolher entre inúmeras ferramentas para interagir com o HTTP. Ao trabalhar com interfaces RESTful, uma das minhas favoritas é a extensão RESTClient para o HTTPBuilder do Groovy (consulte Recursos). HTTPBuilder — um wrapper para o popular HTTPClient do Apache Commons Project — inclui a linguagem inteligente do Groovy à sintaxe dos HTTP POSTs, GETs, PUTs e DELETEs. Porque o HTTPBuilder é construído com o Groovy e o otimiza, escrever scripts que otimizam conceitos RESTful (como se comunicar com o CouchDB) não poderia ser mais fácil.

O Grape torna o fácil ainda mais rápido

Ao manter os temas gerais do desenvolvimento Java 2.0 — rápidos, fáceis e gratuitos (ou baratos) — o prático recurso Grape do Groovy (Groovy Advanced Packaging Engine ou Groovy Adaptable Packaging Engine) é particularmente relevante quando se trata de interagir com uma biblioteca como a HTTPBuilder (consulte Recursos). O Grape é um gerenciador de dependência que permite que os scripts e classes do Groovy configurem automaticamente suas dependências particulares no tempo de execução. Isto torna o uso de várias bibliotecas de software livre muito fácil, porque você não precisa fazer o download de uma série de arquivos JAR somente para iniciar a codificação. Por exemplo, com o Grape, é possível escrever um script Groovy para usar o HTTPBuilder sem ter os JARs solicitados do HTTPBuilder antecipadamente. Com o Grape, eles serão transferidos por download (via Apache Ivy) no tempo de execução (ou tempo de compilação).

Você otimiza o Grape via anotações e chamadas de métodos. É possível, por exemplo, decorar um método ou declaração de classe com uma anotação @Grab . Nesta anotação, você especifica alguns metadados relevantes relacionados à dependência principal. (Através da magia do Ivy, todas as dependências transitivas também serão resolvidas). No tempo de execução ou no tempo de compilação (qual for o primeiro), o Grape faz o download dessas dependências e assegura que elas estejam no seu caminho de classe. Se as dependências já foram transferidas por downloaded (a partir de uma execução anterior, por exemplo), o Grape, todavia, ainda assegura que os arquivos JAR apropriados estão no seu caminho de classe.


RESTing com facilidade no CouchDB com o Groovy

Antes de poder criar quaisquer documentos no CouchDB, você deve criar um banco de dados. Para criar um banco de dados de multas por estacionar em local proibido, emita um HTTP PUT usando a domain-specific language (DSL) inteligente do HTTPBuilder usando seu RESTClient, como mostrado na Lista 2. (Todo o código Groovy para os exemplos deste artigo está disponível para download.)

Lista 2. Criando um banco de dados CouchDB
import static groovyx.net.http.ContentType.JSON
import groovyx.net.http.RESTClient

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder',
   version='0.5.0-RC2')
def getRESTClient(){
  return new RESTClient("http://localhost:5498/")
}

def client = getRESTClient()
def response = client.put(path: "parking_tickets",
        requestContentType: JSON, contentType: JSON)

assert response.data.ok == true : "response from server wasn't ok"

O CouchCB deve retornar a resposta {"ok":true}. Como você pode ver na Lista 2, em HTTPBuilder é simples analisar o JSON e garantir que o valor do elemento ok é, de fato, true.

A seguir, é hora de criar alguns documentos de acordo com o tema multas por estacionar em local proibido. Para modelar uma multa por estacionar em local proibido, lembre-se de que vários aspectos estão associados a uma multa. Também lembre-se de que como esses são formulários reais que os guardas preenchem, alguns campos podem não ser preenchidos ou mesmo seguir um padrão prescrito — pense em cruzamento versus local exato.

Ao usar o HTTPBuilder, é possível criar um documento no CouchDB via um HTTP PUT (exatamente como eu fiz na Lista 2 para criar o banco de dados). Pelo fato de o CouchDB funcionar com documentos JSON, você deve seguir o formato do valor do nome do JSON. Isso é feito criando uma estrutura de dados parecida com um mapa no Groovy (que o HTTPBuilder transformará em JSON válido). A Lista 3 mostra como:

Lista 3. Criando um documento CouchDB via RESTClient
response = client.put(path: "parking_tickets/1234334325", contentType: JSON,
        requestContentType:  JSON,
        body: [officer: "Kristen Ree",
                location: "199 Baldwin Dr",
                vehicle_plate: "Maryland 77777",
                offense: "Parked in no parking zone",
                date: "2009/01/31"])

assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "1234334325" : "the returned ID didn't match"

Poucas coisas estão acontecendo na Lista 3. Primeiro, ao emitir um PUT para um documento CouchDB, você deve designar um UUID. O CouchDB pode designá-los para você, ou você mesmo pode gerenciá-los. Na Lista 3, acabei de criar um (1234334325); este UUID é consequentemente anexado à URL. Se este UUID estiver disponível, o CouchDB designará o documento com PUT para ele. No aspecto body da minha chamada put , observe como cada nome tem um valor associado, quase como um mapa normal. Por exemplo, o nome do guarda de designação é Kristen Ree, e o local da multa é 199 Baldwin Dr.

A Lista 4 cria outra multa por estacionamento ilegal no CouchDB via a mesma técnica:

Lista 4. Outra multa por estacionamento ilegal
def id = new Date().time
response = client.put(path: "parking_tickets/${id}", contentType: JSON,
        requestContentType:  JSON,
        body: [officer: "Anthony Richards",
                location: "Walmart Parking lot",
                vehicle_plate: "Delaware 4433-OP",
                offense: "Parked in non-parking space",
                date: "2009/02/01"])


assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "${id}" : "the returned ID didn't match"

Sempre que eu emito um PUT via RESTClient, eu declaro que a resposta JSON contém um valor true para ok, e verifico se meu valor de id pretendido está presente. Observe como na Lista 4, em vez de criar a UUID, agora eu estou usando o horário atual — não uma técnica infalível, mas será suficiente para interações simples.

Quando você cria com êxito um novo documento no CouchDB, ele responde com o JSON que contém o UUID e um ID de revisão. Por exemplo, esta resposta representa o JSON que eu estou validando na Lista 4:

{"ok":true,"id":"12339892938945","rev":"12351463"}

Seus valores de id e rev serão indubitavelmente diferentes. Observe que eu posso capturar o valor de id emitindo uma chamada tal como response.data.id.

No CouchDB, os documentos são controlados via revisões, assim, você pode voltar para a versão de um documento anterior (via o ID de revisão), como você pode fazer no CVS ou Subversion.


Visualizações no CouchDB

Agora que eu criei algumas multas por estacionar em local proibido (ou documentos na linguagem do CouchDB), é hora de criar uma visualização no CouchDB. Lembre-se, as visualizações são apenas funções MapReduce em ação; assim, você deve defini-las. Em muitos casos, você não precisa da função reduzir; a função mapear pode lidar com a maioria das coisas para você. Ela faz exatamente o que diz fazer. É possível essencialmente mapear quais "coisas" ou aspectos você gostaria de filtrar ou localizar, por exemplo.

Eu defini duas multas: uma emitida pelo Guarda Ree e outra emitida pelo Guarda Richards. Para localizar todas as multas emitidas pelo Guarda Ree, por exemplo, você escreve uma função mapear que filtra a propriedade officer de acordo. Então, você passa os resultados para a função emit do CouchDB.

Usando a interface admin do CouchDB: Futon

É possível definir visualizações via a API RESTful do CouchDB ou via a interface administrativa do CouchDB, denominada Futon. Futon é simplesmente um aplicativo da Web disponível em http://localhost:5498/_utils/. Vá até lá agora, e (supondo que você criou o banco de dados e os documentos juntamente comigo) você deve ver uma interface simples para o banco de dados parking_tickets, como mostrado na Figura 1:

Figura 1. A interface Futon
A interface Futon

Se você selecionar o banco de dados parking_tickets, então é possível ver uma lista suspensa no lado direito (denominadaSelect view:). Você começa a definir uma visualização customizada selecionando Custom query..., como mostrado na Figura 2:

Figura 2. Interface de seleção de visualização do Futon
Interface de seleção de visualização do Futon

Agora o Futon apresenta uma interface que permite definir ambas as funções, mapear e reduzir. (Você pode precisar clicar no link View code ). Na caixa de texto Mapear , defina a função mapear simples mostrada na Lista 5:

Lista 5. Uma função mapear simples no CouchDB
function(doc) {
  if(doc.officer == "Kristen Ree"){
    emit(null, doc);
  }
}

Como você pode ver, a função mapear na Lista 5 é definida em JavaScript. Tudo o que ela faz é filtrar os documentos no banco de dados CouchDB por uma propriedade officer . Especificamente, a função passa um documento para o emit somente se o nome do guarda for Kristen Ree. A Figura 3 mostra onde eu defini esta função no Futon:

Figura 3. Criando uma função MapReduce
Criando uma função MapReduce

A seguir, você será solicitado a fornecer um nome de documento de estrutura (digite by_name) e um nome de visualização (digite officer_ree). Esses nomes servirão como um meio para construir uma URL para invocar esta visualização posteriormente (isto é, http://localhost:5498/parking_tickets/_view/by_name/officer_ree).

Agora é possível usar esta visualização via HTTPBuilder, como mostrado na Lista 6:

Lista 6. Invocando sua nova visualização
response = client.get(path: "parking_tickets/_view/by_name/officer_ree",
        contentType: JSON,  requestContentType:  JSON)

assert response.data.total_rows == 1

response.data.rows.each{
   assert it.value.officer == "Kristen Ree"
}

Esta visualização retorna corretamente uma resposta JSON que contém somente um documento: a multa emitida pelo Guarda Ree em 31 de janeiro. O objeto response na Lista 6 oculta a resposta HTTP não-processada analisando o JSON de acordo. É possível visualizar a resposta JSON não-processada chamando o método toString na propriedade data do objeto response . A resposta não-processada se parece com a Lista 7:

Lista 7. O resultado não-processado da visualização
{"total_rows":1,"offset":0,"rows":[
  {"id":"1234334325","key":null,
   "value":{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree",
       "location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
       "offense":"Parked in no parking zone","date":"2009/01/31"}}]}

Como você pode ver pelo documento JSON não-processado retornado, a habilidade do HTTPBuilder para analisar o JSON sem esforço é bastante prática, porque ele possibilita que um mecanismo parecido com gráfico do objeto analise vários atributos e seus valores correspondentes.

Para propósitos de demonstração, vou incluir mais alguns documentos ao banco de dados. Para continuar a trabalhar através dos exemplos, você deve fazer a mesma coisa usando o download de código.

A função emit do CouchDB funciona como um organizador de classificações. Se você não colocar uma restrição na sua função mapear (como eu fiz na Lista 5), então o emit essencialmente classificará os documentos passados. Por exemplo, se você deseja obter todas as multas classificadas por data (pense na cláusula ORDER BY do SQL aqui), é possível simplesmente emitir pelos campos date do documento, como mostrado na Lista 8:

Lista 8. Um função mapear mais simples
function(doc) {
  emit(doc.date, doc);
}

A Lista 9 emite um HTTP GET em relação a esta visualização (ao qual eu dei um nome de documento de estrutura de dates e um nome de visualização de by_date).

Lista 9. Outra visualização invocada
response = client.get(path: "parking_tickets/_view/dates/by_date", contentType: JSON,
        requestContentType:  JSON)
assert response.data.total_rows == 4

A consulta na Lista 9 retorna todos os documentos no banco de dados parking_tickets classificados por data. A instrução assert simplesmente verifica se a propriedade total_rows é igual a 4. Este é um ponto-chave. Visualizações retornam resultados como também um bit de metadados (como o número de documentos retornados); assim ajudam a ver a resposta não-processada antes que você inicie a análise. A Lista 10 mostra os resultados não-processados:

Lista 10. Documentos JSON não-processados classificados por data
{"total_rows":4,"offset":0,"rows":[
  {"id":"85d4dbf45747e45406e5695b4b5796fe","key":"2009/01/30",
   "value":
    {"_id":"85d4dbf45747e45406e5695b4b5796fe","_rev":"1318766781",
     "officer":"Anthony Richards",
     "location":"54th and Main","vehicle_plate":"Virginia FCD-4444",
     "offense":"Parked in no parking zone","date":"2009/01/30"}},
  {"id":"1234334325","key":"2009/01/31",
   "value":
    {"_id":"1234334325","_rev":"4205717256",
     "officer":"Kristen Ree",
     "location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
     "offense":"Parked in no parking zone",
     "date":"2009/01/31"}},
  {"id":"12345","key":"2009/01/31",
   "value":
    {"_id":"12345","_rev":"1479261876",
     "officer":"Anthony Richards","location":"1893 Main St",
     "vehicle_plate":"Maryland 4433-OP",
     "offense":"Parked in no parking zone","date":"2009/01/31"}},
  {"id":"12339892938945","key":"2009/02/01",
   "value":
    {"_id":"12339892938945","_rev":"12351463","officer":"Anthony Richards",
     "location":"Walmart Parking lot","vehicle_plate":"Maine 4433-OP",
     "offense":"Parked in non-parking space",
    "date":"2009/02/01"}}]}

O que é interessante sobre a definição das visualizações como essa é que você pode depois passar uma chave— , isto é, o que você gostaria que o primeiro valor da função emit representasse de verdade. Por exemplo, a visualização definida na Lista 8 essencialmente classifica por data. Eu gostaria de classificá-la por uma data específica , depois passar essa data para a consulta de visualização. Por exemplo, só por diversão, insira esta URL na caixa de localidade do seu navegador:

http://localhost:5498/parking_tickets/_view/dates/by_date?key="2009/01/31"

Esta visualização então retorna somente as multas emitidas em 31 de janeiro. Você deve ver um punhado de texto parecido com JSON na janela do seu navegador similar ao que você pode ver na Lista 11. Observe que usar o seu navegador como sua ferramenta de consulta local é uma maneira essencialmente fácil de visualizar a resposta JSON não-processada de uma solicitação HTTP.

Lista 11. Somente duas multas emitidas em 31 de janeiro
{"total_rows":4,"offset":1,"rows":[
   {"id":"1234334325","key":"2009/01/31",
    "value":
     {"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree",
       "location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
       "offense":"Parked in no parking zone",
       "date":"2009/01/31"}},
   {"id":"12345","key":"2009/01/31",
    "value":
     {"_id":"12345","_rev":"1479261876","officer":"Anthony Richards",
       "location":"1893 Main St","vehicle_plate":"Maryland 4433-OP",
       "offense":"Parked in handicap zone without permit",
        "date":"2009/01/31"}}]}

As visualizações podem ser tão específicas quanto você desejar. Por exemplo, com um pouco de manipulação de cadeia de caracteres JavaScript, eu posso escrever uma cadeia de caracteres que localize multas emitidas em qualquer ponta da Main Street, como mostrado na Lista 12:

Lista 12. Outra visualização com um pouco de mágica de cadeia de caracteres
function(doc) {
  if(doc.location.toLowerCase().indexOf('main') > 0){
   emit(doc.location, doc);
  }
}

Como você pode ver na Lista 12, se o elemento location de qualquer documento contiver main, então o documento é passado para a função emit . Lembre-se que esta procura é bem mais ampla. Se a location de um documento contiver uma cadeia de caracteres como Germaine Street, ela também será retornada. Para a pequena população de multas que eu defini, a visualização retornaria os resultados mostrados na Lista 13:

Lista 13. Resultados filtrados por Main Street
{"total_rows":2,"offset":0,"rows":[
  {"id":"123433432asdefasdf4325","key":"4th and Main",
   "value":
    {"_id":"123433432asdefasdf4325","_rev":"498239926",
    "officer":"Chris Smith","location":"4th and Main",
      "vehicle_plate":"VA FGA-JD33",
      "offense":"Parked in no parking zone","date":"2009/02/01"}},
 {"id":"123433432223e432325","key":"54 and Main",
   "value":
    {"_id":"123433432223e432325","_rev":"841089995",
    "officer":"Kristen Ree","location":"54 and Main Street",
      "vehicle_plate":"Maryland 77777",
      "offense":"Parked in no parking zone","date":"2009/02/02"}}]}

Observe que a resposta JSON contém um elemento key , que descreve porque um documento particular foi emitido. Este nível de informação é bastante útil. Também observe como desde o início, os dados localizados nas várias multas que eu defini são de certa forma inconsistentes: alguns locais são precisos, outros não. Ainda que esses dados possam ser armazenados em um banco de dados relacional, eles também se ajustam bem com um modelo orientado para documento, você não acha? Além disso, com o poder do Groovy e a habilidade do HTTPBuilder de analisar o JSON sem esforço, é bem fácil acessar os dados (muito mais fácil do que com o JDBC não-processado).


O CouchDB como o banco de dados para a Web

O CouchDB é especialmente interessante porque é muito fácil iniciar com ele. Bancos de dados relacionais são fáceis também, mas o que é bom sobre esse banco de dados é como você pode adotar sua API se já tiver alguma familiaridade com, digamos, o uso de um navegador da Web. Além disso, por causa da API RESTful do CouchDB, é possível se comunicar com ele via estruturas interessantes como o RESTClient do HTTPBuilder. Você também não está limitado ao HTTPBuilder; algumas bibliotecas Java tentam tornar mais fácil o trabalho com o CouchDB. Uma biblioteca que é especialmente promissora é a jcouchdb (consulte Recursos), que o isola dos aspectos RESTful e JSON de tudo isso e permite que você trabalhe programaticamente na linguagem Java com documentos e visualizações.

Fique sintonizado com a coluna do próximo mês, na qual eu voltarei ao Google App Engine. Fiel ao espírito da inovação aberta, novas estruturas estão surgindo que facilitam o desenvolvimento e a implementação do Google App Engine. Você verá como uma delas torna o desenvolvimento Java 2.0 na plataforma em nuvem do Google ainda mais fácil.


Download

DescriçãoNomeTamanho
Groovy source code for article examplesj-javadev2-5.zip2KB

Recursos

Aprender

Obter produtos e tecnologias

Discutir

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
ArticleID=453915
ArticleTitle=Desenvolvimento Java 2.0: REST com CouchDB e o RESTClient do Groovy
publish-date=12162009