Você está na página 1de 25

1/25

Google Guice
Injeo de dependncias la Google
Conhea o framework de injeo de dependncias do Google e veja como ele pode facilitar o desenvolvimento e manuteno de uma aplicao Java PAULO CSAR COUTINHO J faz um bom tempo que o termo Google deixou de representar simplesmente o mecanismo de busca mais utilizado no planeta, que se parar por um instante, acaba com a produtividade da grande maioria dos desenvolvedores . Hoje em dia, temos uma soluo Google para quase todo tipo de necessidade. Na web temos, alm do buscador, claro, servios como GMail, Orkut, Google Docs, Youtube, Picasa Web Albums, Blogger, Wave, Buzz, Code Search, Groups, Calendar, Maps, Reader, Books, Finance, dentre diversos outros menos conhecidos. Tambm temos aplicaes desktop como: Google Desktop, Picasa, Google Earth, SketchUp, Talk, Chrome etc. Sem contar que, ainda este ano, devem ser lanadas as primeiras verses do Chrome OS, que ser um sistema operacional voltado a pessoas que passam a maioria do seu tempo na internet. E no apenas para os usurios comuns que o Google oferece servios. Para ns, desenvolvedores, tambm disponibilizado um considervel acervo de servios e ferramentas. Basta entrar em http://code.google.com/more/ que encontraremos mais de setenta ferramentas ou servios voltados a desenvolvedores J faz um bom tempo que o termo Injeo de dependncias vem sendo constantemente utilizado no contexto do desenvolvimento de software. So inmeros os frameworks que fazem uso desse princpio, a exemplo do Spring, em sua essncia, para facilitar a vida dos desenvolvedores. J mais que realidade, o paradigma de construo de aplicaes baseadas em servios. Nos dias atuais, a necessidade de integrar nossas aplicaes com servios e/ou outras aplicaes existentes, em algum momento, torna-se inevitvel. Como resultado, temos uma tendncia cada vez maior de criar e utilizar servios de software. As APIs de Dados Google (Google Data APIs) so um timo exemplo desse cenrio, uma vez que atuam como ponto de integrao entre os diversos servios Google e nossas aplicaes. Ao longo de diversos artigos1, temos explorado as vrias APIs de dados disponibilizadas, mostrando seus conceitos bsicos e seu uso de forma prtica em aplicaes Java. Neste artigo, iremos estudar mais uma dessas APIs. Dessa vez nosso foco ser a Picasa Web Albums Data API, que, como o prprio nome sugere, responsvel por fornecer um ponto de integrao entre nossas aplicaes e o Picasa Web Albums, que o servio de fotos do Google. No decorrer do artigo, veremos como manipular os lbuns e fotos do usurio. Alm disso, tambm aprenderemos a recuperar os comentrios das fotos, fazer buscas por tags, upload de fotos e vdeos, dentre outras possibilidades. Mantendo o foco prtico de sempre, como projeto final deste artigo, construiremos uma aplicao web que ser um visualizador de lbuns e fotos do Picasa Web Albums. Para isso, utilizaremos tambm duas outras tecnologias do prprio Google, o Google Web Toolkit e o Google App Engine. Um exemplo da aplicao em produo pode ser visto no endereo http://jm-picasa.appspot.com. Iniciaremos com uma pequena introduo ao Picasa Web Albums, em seguida aprenderemos a efetuar cada uma das operaes bsicas oferecidas pela API, utilizando a Java Client Library, e por fim, veremos o passo a passo da construo da aplicao exemplo.
O artigo Google Data APIs da Edio 64 da Java Magazine d uma viso geral sobre as APIs de dados Google e o protocolo utilizado por elas, o GData Protocol. Nas Edies 65, 67 e 73, possvel encontrar informaes especficas das APIs de Contatos, Google Calendar e Google Docs, respectivamente.
1

2/25

O Servio: Picasa Web Albums


Antes de falarmos da API de dados, vamos entender melhor como funciona o servio. O Picasa Web Albums, ou PWA (Figura 1), o servio de armazenamento e compartilhamento de fotos do Google, semelhante ao Flickr, do Yahoo!. Nele, o usurio pode criar lbuns e fazer upload de fotos e vdeos (Sim! O PWA tambm suporta vdeos). Podendo escolher o nvel de privacidade do lbum, possibilitando que o mesmo seja visto apenas pelo seu autor, apenas por convidados ou por qualquer usurio. Tambm possvel classificar suas fotos utilizando tags para facilitar a busca, bem como adicionar comentrios nas fotos de outros usurios. Alm disso, o servio oferece outras features como: slide show em flash para visualizao das fotos de um lbum, envio de fotos por email e revelao. O PWA oferece vrios planos em funo do limite de armazenamento desejado, que pode chegar a 16 TB (dezesseis terabytes). O plano grtis d direito a 1 GB de armazenamento, j por U$5 anuais, o limite aumenta para 20 GB (para ver os demais planos, veja a seo Links).

Figura 1. Tela inicial do Picasa Web Albums.

Vale salientar que alm do Picasa Web Albums, que o servio de armazenamento e compartilhamento de fotos, tambm existe o software Picasa, que um aplicativo desktop para visualizao, organizao e edio de fotos. Este, por sua vez, possui uma integrao com o Picasa Web Albums, como upload de fotos e vdeos a partir da prpria aplicao.

A API
A Picasa Web Albums Data API fornece uma interface que permite a nossas aplicaes interagirem com o PWA. Atravs dela, podemos efetuar operaes bsicas (CRUD) com os lbuns, fotos e vdeos, tags e comentrios do usurio, possibilitando a criao de aplicaes desktop, web ou mobile, capazes de fazer upload de fotos e vdeos e navegar nos lbuns e fotos do usurio. Alm

3/25 disso, tambm possvel utilizar a API para integrar o servio de fotos com outras aplicaes, como um blog ou agenda de contatos. A interao com a API se d atravs de requisies HTTP para URLs especficas, seguindo o paradigma dos servios RESTful. O contedo das requisies e suas respectivas respostas definido pelo protocolo GData, que utilizado por todas as APIs de dados Google. Os dados geralmente so trafegados nos formatos XML ou JSON, na forma de feeds e entries Atom. Entretanto, na maioria das vezes, no preciso conhecer todos os detalhes do protocolo GData de trs para frente, uma vez que o Google j disponibiliza um nvel de abstrao para lidar com essas questes. Estamos falando das bibliotecas clientes, fornecidas em Java e outras linguagens. Utilizando a biblioteca cliente Java (Java Client Library), a grande maioria das funcionalidades e tipos de dados utilizados nos servios, abstrada em mtodos e classes, deixando o desenvolvimento bem mais simples, como veremos nos exemplos deste artigo.
O quadro Google Data APIs Conceitos Bsicos apresenta um resumo de alguns dos conceitos que utilizaremos durante o artigo.

Para interagir com o PWA, que o nosso foco, a biblioteca j disponibiliza a classe PicasawebService. Um lbum do usurio representado pela classe AlbumEntry, uma foto pela classe PhotoEntry e assim por diante. Portanto, no precisamos em momento algum manipular diretamente XMLs ou conexes HTTP, j que as classes da biblioteca o fazem para ns.

Google Data APIs Conceitos Bsicos


Este quadro lista os principais conceitos relacionados s APIs de Dados do Google para ajudar no entendimento do artigo: Google Data APIs Conjunto de APIs responsveis por permitir a interao entre aplicativos de terceiros e os servios Google. Essas APIs so disponibilizadas na forma de web services RESTful; GData Protocol Protocolo utilizado pelas APIs de Dados Google. baseado principalmente no Atom e AtomPub. Atualmente os dados podem ser transmitidos nos formatos XML ou JSON, sendo XML o padro; Feed Representa uma fonte de dados frequentemente atualizada que geralmente utilizada para alimentar algum tipo de cliente. Tambm utilizamos o termo feed para nos referir URL onde o feed em si pode ser encontrado, por exemplo, http://picasaweb.google.com/data/feed/api/user/default a URL atravs da qual temos acesso ao feed dos lbuns do usurio; Entrada (Entry) Representa uma entrada de dados num determinado feed. Uma tag Entry corresponde a um registro na tabela de um banco de dados; Java Client Library Biblioteca Java disponibilizada pelo Google para facilitar o uso das APIs de dados. Tambm existem bibliotecas para outras linguagens, como PHP, Javascript, Objective-C, .NET, etc.; Client Login Tipo de autenticao recomendado para aplicaes desktop. O protocolo GData tambm suporta outros tipos de autenticao como AuthSub e OAuth, que so recomendados para aplicaes web.

Preparando o ambiente
Para configurar o nosso ambiente, primeiramente precisaremos baixar a verso mais recente da Java Client Library (ver Links). Uma vez concludo o download, vamos criar um projeto no Eclipse e ento adicionar os jars da biblioteca cliente no build path. Para os exemplos deste artigo, utilizaremos os seguintes jars: gdata-base-1.0.jar; gdata-core-1.0.jar;

4/25 gdata-media-1.0.jar; gdata-photos-2.0.jar; gdata-photos-meta-2.0.jar; google-collect-1.0-rc1.jar.

A Java Client Library composta por vrios jars, divididos por servio, para eliminar o overhead de se carregar toda a biblioteca para utilizar apenas um ou dois servios. Dessa forma, o desenvolvedor pode escolher apenas os recursos que deseja utilizar.

Autenticando o usurio
Antes de realizar qualquer operao envolvendo o servio, preciso autenticar o usurio no mesmo. Existem diversos mecanismos de autenticao suportados pelas APIs de dados. Nos nossos exemplos utilizaremos o tipo Client Login, por ser o mais simples. Para isso, basta chamar o mtodo PicasawebService.setUserCredentials(), informando o e-mail e a senha do usurio. Uma vez autenticado, gerado um token que ser armazenado no objeto PicasawebService e utilizado nas transaes subsequentes realizadas com esse objeto, evitando que as credenciais do usurio sejam trafegadas pela rede mais de uma vez. O cdigo para efetuar a autenticao do usurio no PWA deve se parecer com o seguinte:
PicasawebService service = new PicasawebService(JavaMagazine-PicasaWebClient-v1.0); service.setUserCredentials(pcmnac@gmail.com, *********);

Nos prximos exemplos deste artigo, omitiremos o cdigo que acabamos de ver, com o intuito de evitar a repetio do trecho de declarao e autenticao no servio, que igual para todos os casos. Assim, ficar implcito que temos um objeto service, do tipo DocsService, devidamente criado e autenticado.

Trabalhando com lbuns


Nesta seo, veremos pequenos exemplos para cada uma das operaes bsicas envolvendo os lbuns do usurio.
Listando os lbuns do usurio

Para listar os lbuns de um determinado usurio, uma vez autenticado no servio, basta utilizar o mtodo PicasawebService.getFeed() informando a URL do feed que representa a lista de lbuns do usurio, que dada por http://picasaweb.google.com/data/feed/api/user/<username>?kind=album, substituindo-se <username> pelo login2 do usurio em questo. O cdigo para listar os lbuns do usurio surukuku, por exemplo, deve se parecer com o seguinte:
URL feedUri = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku?kind=album"); UserFeed feed = service.getFeed(feedUri, UserFeed.class); for (AlbumEntry entry : feed.getAlbumEntries()) { System.out.println(entry.getTitle().getPlainText() + " [" + entry.getPhotosUsed() + "]"); }

O cdigo que acabamos de ver monta a URL do feed de lbuns do usurio e invoca o mtodo service.getFeed() informando a URL e o tipo de feed que desejamos receber de retorno, UserFeed nesse caso. Em seguida, com o objeto UserFeed em mos, iteramos sobre a coleo de objetos AlbumEntry presentes nesse feed e, para cada entry ou seja, cada lbum , imprimimos no console o ttulo e a quantidade de fotos do lbum.

Tambm possvel utilizar o valor default para representar o usurio autenticado.

5/25

Lembrando que estamos assumindo em nossos exemplos que service um objeto do tipo PicasawebService, devidamente criado e autenticado, como visto na seo Autenticando o usurio.
Criando novos lbuns

Para criar um lbum, basta utilizar o mtodo PicasawebService.insert(), passando a URL do feed de lbuns do usurio e um objeto AlbumEntry com as informaes do lbum a ser criado. A URL dada por http://picasaweb.google.com/data/feed/api/user/<username>, substituindo-se <username> pelo login do usurio autenticado ou por default. Vejamos um exemplo:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/default"); AlbumEntry myAlbum = new AlbumEntry(); myAlbum.setTitle(new PlainTextConstruct("Frias no Hawa")); myAlbum.setDescription(new PlainTextConstruct("Fotos das ltimas frias no Hawa")); AlbumEntry insertedEntry = service.insert(feedUrl, myAlbum);

O cdigo que vimos cria um novo objeto AlbumEntry, configura seu ttulo e descrio, e em seguida invoca o mtodo service.insert(), passando a URL do feed de lbuns do usurio e o objeto que representa o lbum a ser criado. Note que o mtodo insert() retorna outro objeto AlbumEntry. Este, por sua vez, uma verso atualizada do objeto que passamos como parmetro, contendo informaes adicionais, geradas pelo servidor no momento da criao, como o ID do lbum.
Editando um lbum

Editar um lbum uma tarefa extremamente simples. Uma vez com um objeto AlbumEntry vlido, recuperado do servidor conforme vimos na seo Listando os lbuns do usurio, basta editar os atributos desse objeto e invocar o mtodo AlbumEntry.update(). Vejamos um exemplo que altera o ttulo do lbum que acabamos de inserir no exemplo anterior:
insertedEntry.setTitle(new PlainTextConstruct("Hawa 2010")); insertedEntry.update(); Excluindo um lbum

Para excluir um lbum no servidor basta chamar o mtodo AlbumEntry.delete() num objeto AlbumEntry vlido. O exemplo a seguir mostra como seria o cdigo para excluir o lbum que acabamos de editar no exemplo anterior:
insertedEntry.delete();

Trabalhando com fotos e vdeos


Aqui veremos como realizar as operaes bsicas que envolvem as fotos e vdeos dos usurios. A API do Picasa Web Albums trata fotos e vdeos da mesma maneira, portanto, todos os exemplos demonstrados utilizando fotos tambm so vlidos para vdeos.
Listando as fotos de um lbum

Para listar as fotos, e vdeos, de um determinado lbum, basta utilizar o mtodo PicasawebService.getFeed() informando a URL do feed que representa a lista de fotos do lbum, que dada por http://picasaweb.google.com/data/feed/api/user/<username>/albumid/<albumId>, substituindo-se <username> pelo login do usurio proprietrio do lbum e <albumId> pelo ID do lbum desejado. Vejamos um exemplo:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku/albumid/123456"); AlbumFeed feed = service.getFeed(feedUrl, AlbumFeed.class); for (PhotoEntry entry : feed.getPhotoEntries()) {

6/25

System.out.println(entry.getTitle().getPlainText() + + entry.getMediaContents().get(0).getUrl()); }

O cdigo que acabamos de ver lista as fotos do lbum de ID 123456 do usurio surukuku. Note que dessa vez utilizamos o tipo AlbumFeed, que por sua vez possui uma coleo de objetos PhotoEntry, representando as fotos do lbum em questo. Para cada foto do lbum, imprimimos, no console, seu ttulo e a URL da imagem. Tambm podemos listar as ltimas fotos do usurio. Para isso, basta utilizar a URL http://picasaweb.google.com/data/feed/api/user/<username>?kind=photo na chamada do mtodo PicasawebService.getFeed(), substituindo <username> pelo login do usurio. Para listar as fotos mais recentes do usurio surukuku, por exemplo, teramos um cdigo como o seguinte:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku?kind=photo"); AlbumFeed feed = service.getFeed(feedUrl, AlbumFeed.class); for(PhotoEntry entry : feed.getPhotoEntries()) { System.out.println(entry.getTitle().getPlainText() + " " + entry.getMediaContents().get(0).getUrl()); } Buscando fotos da comunidade Listando as fotos mais recentes do usurio

Ainda possvel fazer uma busca nas fotos de lbuns pblicos de outros usurios. Basta utilizar a URL http://picasaweb.google.com/data/feed/api/all?kind=photo&q=<searchText>, substituindo <searchText> pelo texto que deve ser procurado nas fotos. O cdigo seguinte recupera as fotos pblicas contendo a palavra rosa no seu ttulo ou descrio:
URL searchUrl = new URL("http://picasaweb.google.com/data/feed/api/all?kind=photo&q=rosa"); AlbumFeed searchResultsFeed = service.getFeed(searchUrl, AlbumFeed.class); for (PhotoEntry entry : searchResultsFeed.getPhotoEntries()) { System.out.println(entry.getTitle().getPlainText() + " " + entry.getMediaContents().get(0).getUrl()); } Inserindo uma nova foto

Para enviar uma nova foto ou vdeo, basta utilizar o mtodo PicasawebService.insert() passando a URL do lbum de destino e o objeto PhotoEntry representando a foto ou vdeo. O exemplo a seguir faz o upload do arquivo foto01.jpg, com o ttulo Minha Foto para o lbum de ID 123456 do usurio autenticado:
URL postUrl = new URL("http://picasaweb.google.com/data/feed/api/user/default/albumid/123456"); PhotoEntry newPhoto = new PhotoEntry(); newPhoto.setTitle(new PlainTextConstruct("Minha Foto")); MediaFileSource media = new MediaFileSource(new File("/Users/PCMNAC/foto01.jpg"), "image/jpeg"); newPhoto.setMediaSource(media); PhotoEntry insertedPhoto = service.insert(postUrl, newPhoto);

Se quisssemos enviar apenas a foto, ou vdeo, sem o metadados (ttulo, descrio etc.), poderamos omitir a criao do objeto PhotoEntry e chamar o mtodo PicasawebService.insert() passando o MediaSource diretamente. Vejamos como ficaria o exemplo anterior:
URL postUrl = new URL("http://picasaweb.google.com/data/feed/api/user/default/albumid/123456"); MediaFileSource media = new MediaFileSource(new File("/Users/PCMNAC/foto01.jpg"), "image/jpeg");

7/25

PhotoEntry insertedPhoto = service.insert(postUrl, PhotoEntry.class, media);

Os formatos de imagem suportados so: image/bmp, image/gif, image/jpeg e image/png. J os formatos de vdeo suportados so: video/3gpp, video/avi, video/quicktime, video/mp4, video/mpeg, video/mpeg4, video/msvideo, video/xms-asf, video/x-ms-wmv, video/x-msvideo e vdeo/x-flv. No caso do upload de um vdeo, necessrio aguardar que o mesmo seja processado e disponibilizado para streaming. Para saber o status de processamento do vdeo, basta utilizar o mtodo PhotoEntry.getVideoStatus().

Da mesma forma que fizemos para editar lbuns, para editar uma foto ou vdeo, basta alterar os valores dos atributos desejados no PhotoEntry e invocar o mtodo update() no mesmo. Vejamos como ficaria o cdigo para alterar o ttulo da foto que fizemos upload no exemplo anterior:
insertedPhoto.setTitle(new PlainTextConstruct(Novo Ttulo)); insertedPhoto.update(); Removendo uma foto

Editando uma foto

Para remover uma foto ou vdeo do servidor, basta invocar o mtodo delete() no objeto PhotoEntry que representa a foto ou vdeo em questo. Vejamos um exemplo que remove a foto que editamos no exemplo anterior:
insertedPhoto.delete();

Trabalhando com tags


No contexto do Picasa Web Albums, tags so classificadores que ajudam na organizao de fotos e vdeos e facilitam o processo de busca. Nesta seo, veremos como realizar as principais operaes envolvendo tags.
Listando as tags de um usurio

Para listar as tags do usurio, basta utilizar mtodo PicasawebService.getFeed() passando a URL http://picasaweb.google.com/data/feed/api/user/<username>?kind=tag, substituindo <username> pelo login do usurio em questo. O cdigo a seguir lista as tags do usurio surukuku e imprime seus ttulos:
URL feedUri = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku?kind=tag"); AlbumFeed feed = service.getFeed(feedUri, AlbumFeed.class); for (TagEntry entry : feed.getTagEntries()) { System.out.println(entry.getTitle().getPlainText()); } Listando as tags de um lbum

Para listar as tags presentes nas fotos de um lbum especfico, temos um processo quase idntico ao de listar as tags do usurio. A nica diferena que nesse caso devemos utilizar a URL http://picasaweb.google.com/data/feed/api/user/<username>/albumid/<albumId>?kind=tag, que inclui o ID do lbum em questo. O cdigo a seguir lista as tags do lbum de ID 123456 do usurio surukuku e imprime seus ttulos:
URL feedUri = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku/albumid/123456?kind=tag"); AlbumFeed feed = service.getFeed(feedUri, AlbumFeed.class); for (TagEntry entry : feed.getTagEntries()) { System.out.println(entry.getTitle().getPlainText()); }

8/25

Listando as tags de uma foto

Para listar as tags presentes numa foto ou vdeo especfico, tambm temos um processo bem parecido, bastando apenas incluir o ID da foto na URL, que ficaria da seguinte forma: http://picasaweb.google.com/data/feed/api/user/<username>/albumid/<albumId>/photoid/<photoI d>?kind=tag. O cdigo a seguir lista as tags da foto ou vdeo de ID 654321, do lbum de ID 123456, do usurio surukuku e imprime seus ttulos:
URL feedUri = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku/albumid/123456/photoid/654321?kind=tag"); AlbumFeed feed = service.getFeed(feedUri, AlbumFeed.class); for (TagEntry entry : feed.getTagEntries()) { System.out.println(entry.getTitle().getPlainText()); } Buscando fotos com tags

Para fazer uma busca baseada em tags, basta utilizar a mesma URL que utilizamos para listar as fotos do usurio, acrescida do parmetro tag, cujo valor deve ser a tag que estamos procurando. Com isso, a URL resultante ficaria com o seguinte formato: http://picasaweb.google.com/data/feed/api/user/<username>?kind=photo&tag=<tag>. Vejamos ento um exemplo:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku"); Query myQuery = new Query(feedUrl); myQuery.setStringCustomParameter("kind", "photo"); myQuery.setStringCustomParameter("tag", "tag1 "); AlbumFeed searchResultsFeed = service.query(myQuery, AlbumFeed.class); for (PhotoEntry photo : searchResultsFeed.getPhotoEntries()) { System.out.println(photo.getTitle().getPlainText()); }

No cdigo que acabamos de ver, estamos listando todas as fotos do usurio surukuku que contm a tag tag1 e imprimindo seu ttulo. Note que utilizamos o objeto Query, que serve basicamente para facilitar a construo da URL. Poderamos ter construdo a URL manualmente, porm o objeto Query traz consigo algumas facilidades, como codificar as strings no formato de URL. Note tambm que quando utilizamos um objeto Query, devemos chamar o mtodo query(), ao invs do getFeed(), do nosso PicasawebService. O restante do cdigo idntico aos outros que vimos durante todo o artigo.
Para buscar as fotos com uma determinada tag num lbum especfico, basta incluir o ID do lbum na URL de busca, que ficaria no formato http://picasaweb.google.com/data/feed/api/user/<username>/albumid/<albumId>?kind=photo&tag=<tag>.
Adicionando uma tag numa foto

Para adicionar uma nova tag numa foto ou vdeo basta criar um objeto TagEntry com o valor da tag que desejamos criar e pass-lo para o mtodo PicasawebService.insert(), juntamente com a URL da foto ou vdeo para o qual estamos criando a tag. O exemplo a seguir cria a tag minha tag na foto de ID 654321:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/default/albumid/123456/photoid/654321"); TagEntry tag = new TagEntry(); tag.setTitle(new PlainTextConstruct("minha tag"));

9/25

service.insert(feedUrl, tag); Removendo uma tag

Para remover uma tag basta invocar o mtodo delete() no objeto TagEntry que representa a tag, como mostra o cdigo a seguir:
tag.delete()

Trabalhando com comentrios


O Picasa Web Albums tambm permite que usurios postem comentrios nas fotos de outros usurios. Nesta seo veremos como executar as operaes bsicas envolvendo comentrios.
Listando os comentrios do usurio

Para listar os ltimos comentrios postados por um usurio devemos chamar o mtodo PicasawebService.getFeed() com a URL que representa o feed de comentrios do usurio: http://picasaweb.google.com/data/feed/api/user/<username>?kind=comment. O exemplo a seguir lista os ltimos comentrios do usurio autenticado no servio:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/default?kind=comment"); UserFeed feed = service.getFeed(feedUrl, UserFeed.class); for(GphotoEntry<CommentEntry> entry : feed.getEntries()) { System.out.println(entry.getPlainTextContent()); } Listando os comentrios de uma foto

Para listar os comentrios de uma foto ou vdeo em particular, basta utilizar a URL da foto na chamada do mtodo PicasawebService.getFeed(), como mostra o cdigo a seguir:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku/albumid/123456/photoid/654321?kind=comment"); PhotoFeed feed = service.getFeed(feedUrl, PhotoFeed.class); for(CommentEntry entry : feed.getCommentEntries()) { System.out.println(entry.getPlainTextContent()); } Adicionando comentrios

Para adicionar um comentrio numa foto ou vdeo basta criar um objeto CommentEntry com o contedo do comentrio e chamar o mtodo PicasawebService.insert(), passando esse objeto juntamente com a URL da foto ou vdeo para o qual estamos adicionando o comentrio. Vejamos um exemplo:
URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/surukuku/albumid/123456/photoid/654321"); CommentEntry comment = new CommentEntry(); comment.setContent(new PlainTextConstruct("Bonita Foto")); service.insert(feedUrl, comment); Removendo um comentrio

Para remover um comentrio basta invocar o mtodo delete() no CommentEntry correspondente ao comentrio que desejamos excluir, de acordo com o cdigo:
comment.delete();

10/2

Aplicao Exemplo
Agora que j conhecemos as operaes bsicas oferecidas pela API para trabalhar com lbuns, fotos, vdeos, tags e comentrios, vamos construir um projeto exemplo. Como falamos no incio do artigo, nosso projeto trata-se de um cliente web para o Picasa Web Albums. Nossa aplicao ir permitir ao usurio: Listar seus lbuns ou os de outros usurios (neste segundo caso apenas os lbuns pblicos sero listados); Ver as fotos de cada lbum. Para isso sero oferecidas duas formas de apresentao: galeria ou slide-show; Ler e adicionar comentrios nas fotos. Nossa aplicao ser construda utilizando outras duas tecnologias oferecidas pelo Google, o Google Web Toolkit (GWT) e Google App Engine (GAE). Como no o foco deste artigo, no entraremos nos detalhes destas tecnologias, entretanto veremos o necessrio para o entendimento do exemplo. A Figura 2 mostra um screenshot da aplicao, que tambm pode ser vista em produo no endereo http://jm-picasa.appspot.com. O quadro Google Web Toolkit traz um pequeno resumo sobre o GWT. Alm disso, as Edies 38 e 39 da Java Magazine trazem os artigos AJAX com Google Web Toolkit e AJAX avanado com GWT. Para saber mais detalhes sobre o GAE, veja a Edio 71 da Java Magazine, que traz o artigo Java no Google App Engine.

Google Web Toolkit


O Google Web Toolkit (GWT), como o prprio nome sugere, consiste num kit de ferramentas para o desenvolvimento de aplicaes web. Kit esse que contm um SDK prprio, com compilador capaz de converter cdigo Java em Javascript e um servidor de aplicaes, alm de ferramentas para anlise de desempenho e um plugin para Eclipse. A ideia central do GWT prover uma forma de criar aplicaes web ricas, com AJAX, utilizando apenas Java. Dessa forma o desenvolvedor no precisa se preocupar com compatibilidade entre browsers, alm de tornar o desenvolvimento mais produtivo, visto que escrever e depurar cdigo Java com todas as facilidades do Eclipse (ou mesmo outras IDEs) bem mais prtico do que quando se trata de Javascript. Para tornar essa tarefa possvel, o GWT traz consigo um conjunto de bibliotecas e widgets (Ex.: botes, caixas de texto, etc.) que permitem ao desenvolvedor escrever toda lgica da sua aplicao, incluindo os componentes visuais HTML em cdigo Java puro. O compilador o responsvel por traduzir o cdigo Java em Javascript otimizado e compatvel com a maioria dos browsers do mercado. Alm disso, perfeitamente possvel criar aplicaes GWT que possuam um back-end que rode no servidor e no no cliente. Para isso so oferecidas as seguintes estratgias: GWT RPC Opo indicada para comunicao com back-end em Java. Consiste na criao de interfaces dos servios que sero oferecidos pelo servidor para que essas possam ser utilizadas de forma assncrona pelo cdigo front-end; JSON / XML Consiste na troca de dados com o servidor nos formatos JSON ou XML. Para isso o GWT oferece classes para manipulao dos dados nestes formatos; Cross-Site Utilizado por aplicaes que necessitam obter dados de servidores remotos de diferentes domnios.

11/2 Na aplicao exemplo deste artigo temos um exemplo prtico de uso do GWT RPC.

Figura 2. Screenshot da aplicao exemplo. Configurando o Eclipse

Para facilitar o uso do GWT e do GAE, utilizaremos o plugin do Google para Eclipse (veja a seo Links), pois dessa forma no teremos que nos preocupar com a criao da estrutura do projeto nem com arquivos de configurao. Baixe os SDKs do GWT e GAE3, e o Google Plugin. Com o eclipse devidamente configurado, crie um novo projeto do tipo Web Application Project, conforme mostra a Figura 3, com as opes Use Google Web Toolkit e Use Google App Engine marcadas, de acordo com a Figura 4. Lembre tambm de definir um pacote raiz para a aplicao, como br.com.jm.picasa por exemplo. Note que o plugin j cria a estrutura bsica de um projeto, contendo inclusive arquivos de um exemplo GWT funcional, como podemos observar na Figura 5. A Tabela 1 traz uma breve explicao da estrutura do projeto. Para ver o projeto em ao, basta clicar com o boto direito no mesmo e escolher a opo Run as>Web Application. Com isso o servidor do GAE ser carregado e a URL da aplicao exibida na aba Development Mode, de acordo com a Figura 6. Para testar a aplicao basta copiar essa URL e colar no browser4. Pasta / Pacote / Arquivo JavaMagazinePicasa.gwt.xml Explicao Arquivo de definio de mdulos do GWT. Especifica a lista de classes e recursos utilizados pelo mdulo, que representa simplesmente um conjunto de funcionalidades ou a prpria aplicao. Pacote que deve conter o cdigo cliente da aplicao, ou seja, as classes que sero traduzidas, pelo GWT, para o cdigo Javascript.

br.com.jm.picasa.client

Durante a escrita deste artigo foram utilizadas a seguintes verses: GWT 2.0.0 e GAE 1.3.0. necessrio que o browser tenha suporte ao plugin do GWT. Caso este ainda no esteja instalado, automaticamente ser solicitada a confirmao de instalao. No momento da escrita deste artigo os browsers compatveis com o plugin do GWT so Internet Explorer, Chrome e Firefox, para Windows. J para Mac OS X, o plugin suportado pelo Safari e Firefox.
4

12/2 Pacote que deve conter o cdigo servidor da nossa aplicao. As classes desse pacote no passam pelo processo de traduo para Javascript. Classe principal da nossa aplicao GWT. Contm o ponto de entrada da aplicao, semelhante ao mtodo main(). Pasta que contm os arquivos estticos que sero acessveis publicamente, como imagens, arquivos css, etc. Pasta com os arquivos de configurao de uma aplicao web Java.

br.com.jm.picasa.server

JavaMagazinePicasa.java war war/WEB-INF

Tabela 1. Pastas e arquivos criados pelo Google Plugin.

Com o esqueleto do nosso projeto criado e testado, vamos agora modific-lo para atender aos requisitos da nossa aplicao exemplo. Primeiro, exclua os arquivos GreetingService.java, GreetingServiceAsync.java e GreetingServerImpl.java, pois estes no sero necessrios e modifique o arquivo JavaMagazinePicasa.java para ficar igual Listagem 1.
Listagem 1. Esqueleto inicial da classe JavaMagazinePicasa.
package br.com.jm.picasa.client; import com.google.gwt.core.client.EntryPoint; public class JavaMagazinePicasa implements EntryPoint { public void onModuleLoad() { } }

Como iremos utilizar a Java Client Library, ser necessrio adicionar os jars da API do Picasa Web Albums (vistos na seo Preparando o ambiente) tanto no build path do projeto, quanto na pasta war/WEB-INF/lib. Alm disso, ser necessrio alterar o arquivo appengine-web.xml, localizado na pasta war/WEB-INF. Primeiro precisamos habilitar o uso de sesses HTTP, adicionando a tag <sessions-enabled> com o valor true. Em seguida preciso acrescentar a propriedade de sistema com.google.gdata.DisableCookieHandler com o valor true, para evitar erros de permisso durante a execuo. A Listagem 2 mostra o arquivo resultante. Feito isso, nosso ambiente est pronto para comearmos o desenvolvimento da aplicao exemplo.
Listagem 2. Arquivo appengine-web.xml com os ajustes necessrios para trabalhar com as APIs de dados google.
<?xml version="1.0" encoding="utf-8"?> <appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application></application> <version>1</version> <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" /> <property name="com.google.gdata.DisableCookieHandler" value="true" /> </system-properties> <sessions-enabled>true</sessions-enabled> </appengine-web-app>

As classes do subpacote client precisam respeitar certas restries, visto que esse cdigo ser traduzido para Javascript e que o GWT oferece apenas um pequeno subconjunto das bibliotecas oferecidas pela runtime do Java. Caso alguma classe que no suportada seja utilizada, o compilador do GWT ir apresentar um erro. A lista das classes e mtodos da JRE que so suportados pelo GWT pode ser vista em http://code.google.com/webtoolkit/doc/latest/RefJreEmulation.html. As classes do subpacote server no so traduzidas para Javascript e por isso no sofrem nenhuma restrio por parte do GWT.

13/2

Figura 3. Criao de um projeto do tipo Web Application Project.

Figura 4. Configuraes do projeto exemplo.

14/2

Figura 5. Estrutura inicial do projeto exemplo.

Figura 6. Aba Development Mode com a URL de testes da aplicao.

As Listagens 3, 4 e 5, mostram o cdigo das entidades que utilizaremos no nosso projeto. A classe Album, como o prprio nome sugere, representa um lbum do usurio. As classes Photo e PhotoComment, por sua vez, representam uma foto e um comentrio, respectivamente. Note que todas as classes devem estar sob o subpacote client e devem ser Serializable. Isso um requisito do GWT, visto que esses objetos sero traduzidos em objetos Javascript no processo de compilao.
Listagem 3. Classe Album Representa um lbum do usurio.
// Declarao de pacote e imports omitidos. public class Album implements Serializable { private String id; // ID do lbum private String title; // Ttulo do lbum private String description; // Descrio do lbum private String thumbnailUrl; // URL da capa do lbum private int photoCount; // Quantidade de fotos no lbum private String owner; // Login do usurio proprietrio do lbum private Photo[] photos; // Lista de fotos do lbum private String slideShowUrl; // URL do slide-show // Gets e Sets ... }

As entidades

Listagem 4. Classe Photo Representa uma foto do usurio.


// Declarao de pacote e imports omitidos. public class Photo implements Serializable { private String id; // ID da foto private String caption; // Caption (texto) da foto private String thumbnailUrl; // URL da minatura private String contentUrl; // URL da imagem no tamanho real private int width; // Largura da foto private int height; // Altura da foto private int commentsCount; // Quantidade de comentrios private Album album; // lbum ao qual a foto pertence

15/2
// Gets e Sets ... }

Listagem 5. Classe PhotoComment Representa um comentrio numa foto.


// Declarao de pacote e public class PhotoComment private String author; private Date date; private String text; private Photo photo; // Gets e Sets ... } imports omitidos. implements Serializable { // Autor do comentrio // Data do comentrio // Texto do comentrio // Foto a qual o comentrio pertence

Definindo a interface do servio

O GWT oferece diversas formas de implementar a integrao entre o front-end e o back-end de uma aplicao (Para mais informaes, consulte o quadro Google Web Toolkit). Para o nosso exemplo, utilizaremos a abordagem GWT RPC. Dessa forma, o cdigo cliente ir simplesmente fazer chamadas assncronas a mtodos no servidor, acessveis atravs da interface de servio que definiremos a seguir. Para isso, vamos criar uma interface Java, no subpacote client, com os mtodos do servidor que desejamos deixar visveis para o cdigo cliente. A Listagem 6 mostra a definio do nosso servio PicasaService.
Listagem 6. Interface PicasaService Representa a interface remota do servio que estamos disponibilizando ao cdigo cliente.
// Declarao de pacote e imports omitidos. @RemoteServiceRelativePath("picasa") public interface PicasaService extends RemoteService { void login(String username, String password); Album[] listAlbums(String user); Album getAlbumContents(Album album); PhotoComment[] getComments(Photo photo); void addComment(PhotoComment comment); }

O mtodo login() ser responsvel por autenticar o usurio, para que as demais operaes possam ser executadas. O mtodo listAlbums() responsvel por recuperar a lista de lbuns do usurio, cujo login deve ser passado como parmetro. Esse mtodo retorna um array de objetos do tipo Album, contendo as informaes bsicas de cada lbum. Entretanto, nem a lista de fotos nem a URL do modo slideshow so preenchidas na chamada desse mtodo, pois como estas requerem chamadas extras ao servio para serem recuperadas, deixaremos para recuper-las apenas quando solicitado. J o mtodo getAlbumContents() o responsvel por recuperar o contedo associado a um dado lbum. Esse mtodo recebe um objeto Album de parmetro e retorna um novo objeto Album, este com as mesmas informaes do objeto recebido, acrescido da lista de fotos do lbum e da URL do slide-show. O mtodo getComments() recupera a lista de comentrios de uma determinada foto. Para isso este mtodo recebe um objeto Photo como parmetro e retorna um objeto PhotoComment. Por fim, o mtodo addComment() adiciona um novo comentrio a uma foto. Como parmetro, ele recebe um objeto PhotoComment, que deve estar com os atributos text e photo devidamente preenchidos.
Criando a interface assncrona

Para utilizar o esquema de RPC do GWT, necessrio definir uma verso assncrona da nossa interface de servio. Para isso devemos criar uma segunda interface com os mesmos mtodos da

16/2 original, porm, com pequenas alteraes para atender o modelo de chamadas assncronas do GWT. As alteraes que devem ser feitas em cada mtodo so: Modificar o tipo de retorno para void; Acrescentar um ltimo parmetro do tipo AsyncCallback<T>, onde T deve ser o tipo de retorno do mtodo original (para void, o tipo Void deve ser utilizado). Dessa forma, se na interface original temos:
PhotoComment[] getComments(Photo photo);

Na verso assncrona teremos:


void getComments(Photo photo, AsyncCallback<PhotoComment[]> callback);

Fcil no? E para ficar ainda mais fcil, podemos deixar que o plugin crie a verso assncrona da nossa interface de forma automtica. Note que nossa interface de servio estende de RemoteService. Com isso, o plugin ir apresentar um erro, caso a verso assncrona no exista ou esteja incompatvel (o que geralmente acontece quando alteramos a interface original). Ento, basta clicar no cone de erro que mostrado no editor e escolher a opo Create asynchronous RemoteService interface 'PicasaServiceAsync' in pakage 'br.com.jm.picasa.client', como pode ser visto na Figura 7. Com isso a verso assncrona da interface criada de forma automtica. A Listagem 7 mostra o resultado.

Figura 7. Assistente para criao da interface assncrona para o servio.


Listagem 7. Interface PicasaServiceAsync Verso assncrona da interface do servio PicasaService.
// Declarao de pacote e imports omitidos. public interface PicasaServiceAsync { void login(String username, String password, AsyncCallback<Void> callback); void listAlbums(String user, AsyncCallback<Album[]> callback); void getAlbumContents(Album album, AsyncCallback<Album> callback); void getComments(Photo photo, AsyncCallback<PhotoComment[]> callback); void addComment(PhotoComment comment, AsyncCallback<Void> callback); }

Implementando o servio

Agora que j definimos as interfaces sncrona e assncrona do nosso servio, vamos prover a este uma implementao concreta. Essa implementao deve fazer parte do cdigo servidor da nossa aplicao e por isso deve fica sob o subpacote server. nessa classe que implementaremos toda a comunicao com o servio do Picasa Web Albums. A Listagem 8 mostra a classe PicasaServiceImpl, que a implementao do servio que definimos. Sendo assim, esta implementa os mtodo definidos em PicasaService. Note tambm que

17/2 nossa implementao deve estender de RemoteServiceServlet, que uma especializao do HttpServlet fornecida pelo GWT que serve de base para a criao de servios remotos. As constantes BASE_URL e APPLICATION_NAME correspondem URL base que utilizaremos para construir as URLs especficas nas chamadas ao servio do Picasa Web Albums e o nome da nossa aplicao, seguindo o padro NomeDaEmpresa-NomeDaAplicacao-versao, sugerido pelo Google. No mtodo login(), iniciamos criando um objeto PicasawebService, que faz parte da biblioteca cliente das APIs de dados, informando o nome da aplicao. Invocamos ento o mtodo service.setUserCredentials() para autenticar o usurio no servio. Para evitar que a cada nova requisio seja necessrio autenticar o usurio novamente, guardaremos o token de autenticao na sesso do usurio. Dessa forma, nas requisies subsequentes basta utilizar o valor desse token nas chamadas ao servio. Para fazer isso, recuperamos o valor do token atravs do mtodo UserToken.getValue() e salvamos esse valor na sesso do usurio que efetuou o login. O mtodo getSessionService() simplesmente cria um novo servio e o configura com o valor do token salvo na sesso. Assim, podemos utilizar esse objeto para fazer requisies ao servio do Picasa Web Albums sem nenhum problema. Os mtodos entryToAlbum(), entryToPhoto(), entryToComment() e commentToEntry(), so apenas mtodos de converso. Simplesmente fazem o mapeamento dos tipos definidos pela biblioteca cliente Java para os beans que definimos e vice-versa. No mtodo listAlbums(), montamos a URL do feed de lbuns do usurio e chamamos o mtodo PicasawebService.getFeed(), como vimos na seo Listando os lbuns do usurio. Em seguida criamos um array de objetos Album e para cada AlbumEntry no feed recuperado, criamos um novo objeto Album, configuramos seu owner e o adicionamos ao array. Por fim, retornamos o array com os lbuns recuperados. No mtodo getAlbumContents(), primeiramente recuperamos o feed de fotos do usurio utilizando o mtodo PicasawebService.getFeed(). Para recuperar a URL do slide-show com as fotos, utilizamos o mtodo AlbumFeed.getLink() passando o rel (relationship) Namespaces.SLIDESHOW. Em seguida, para cada PhotoEntry presente no feed, criamos um objeto Photo e adicionamos ao nosso array de fotos. Por fim, chamamos o mtodo setPhotos() no objeto Album que recebemos como parmetro e retornamos esse mesmo objeto5. No mtodo addComment(), simplesmente montamos a URL de destino seguindo o formato que vimos na seo Adicionando comentrios. Em seguida construmos um CommentEntry a partir do nosso parmetro e invocamos o mtodo PicasawebService.insert() para criar o novo comentrio. Por fim, no mtodo getComments(), recuperamos o feed de comentrios da foto recebida como parmetro. Em seguida criamos um array de objetos PhotoComment e o populamos com os comentrios extrados do feed. Para isso, iteramos sobre a coleo de objetos CommentEntry e convertemos cada entrada em um objeto PhotoComment. Finalmente, retornamos o array com os comentrios.
Listagem 8. Classe PicasaServiceImpl Implementao da interface PicasaService.
// Declarao de pacote e imports omitidos. public class PicasaServiceImpl extends RemoteServiceServlet implements PicasaService { private static final String BASE_URL = "http://picasaweb.google.com/data/feed/api/user/"; private static final String APPLICATION_NAME = "JavaMagazine-PicasaClient-1"; public void login(String username, String password) { try { PicasawebService service = new PicasawebService(APPLICATION_NAME); service.setUserCredentials(username, password); String token = ((UserToken) service.getAuthTokenFactory().getAuthToken()).getValue(); getThreadLocalRequest().getSession().setAttribute("token", token); } catch (AuthenticationException e) { e.printStackTrace(); } }
5 necessrio que retornemos o objeto Album porque as alteraes feitas no objeto original no so refletidas no cliente (cdigo Javascript) de forma automtica.

18/2

private PicasawebService getSessionService() { PicasawebService service = new PicasawebService(APPLICATION_NAME); service.setUserToken((String) getThreadLocalRequest().getSession().getAttribute("token")); return service; } private Album entryToAlbum(AlbumEntry entry) { Album album = new Album(); album.setId(entry.getGphotoId()); album.setTitle(entry.getTitle().getPlainText()); album.setDescription(entry.getDescription().getPlainText()); album.setPhotoCount(entry.getPhotosUsed()); album.setThumbnailUrl(entry.getMediaThumbnails().get(0).getUrl()); return album; } private Photo entryToPhoto(PhotoEntry entry) { Photo photo = new Photo(); photo.setId(entry.getGphotoId()); photo.setCaption(entry.getSummary().getPlainText()); photo.setThumbnailUrl(entry.getMediaThumbnails().get(0).getUrl()); MediaContent content = entry.getMediaContents().get(0); photo.setContentUrl(content.getUrl()); photo.setWidth(content.getWidth()); photo.setHeight(content.getHeight()); photo.setCommentsCount(entry.getCommentCountExt().getValue()); return photo; } private PhotoComment entryToComment(CommentEntry entry) { PhotoComment comment = new PhotoComment(); comment.setAuthor(entry.getAuthors().get(0).getName()); comment.setDate(new Date(entry.getPublished().getValue())); comment.setText(entry.getPlainTextContent()); return comment; } private CommentEntry commentToEntry(PhotoComment comment) { CommentEntry entry = new CommentEntry(); entry.setContent(new PlainTextConstruct(comment.getText())); return entry; } public Album[] listAlbums(String user) { Album[] result = null; try { URL userFeedUrl = new URL(BASE_URL + user + "?kind=album"); UserFeed feed = getSessionService().getFeed(userFeedUrl, UserFeed.class); if (feed.getTotalResults() > 0) { result = new Album[feed.getTotalResults()]; List<AlbumEntry> entries = feed.getAlbumEntries(); for (int i = 0; i < entries.size(); i++) { Album album = entryToAlbum(entries.get(i)); album.setOwner(user); result[i] = album; } } } catch (Exception e) { e.printStackTrace(); } return result; } @Override public Album getAlbumContents(Album album) { try { URL albumFeedUrl = new URL(BASE_URL + album.getOwner() + "/albumid/" + album.getId()); AlbumFeed albumFeed = getSessionService().getFeed(albumFeedUrl, AlbumFeed.class); album.setSlideShowUrl(albumFeed.getLink(Namespaces.SLIDESHOW_REL, null).getHref());

19/2
List<PhotoEntry> photoEntries = albumFeed.getPhotoEntries(); Photo[] photos = new Photo[photoEntries.size()]; for (int i = 0; i < photoEntries.size(); i++) { Photo photo = entryToPhoto(photoEntries.get(i)); photo.setAlbum(album); photos[i] = photo; } album.setPhotos(photos); } catch (Exception e) { e.printStackTrace(); } return album; } @Override public void addComment(PhotoComment comment) { try { URL commentsFeedUrl = new URL(BASE_URL + comment.getPhoto().getAlbum().getOwner() "/albumid/" + comment.getPhoto().getAlbum().getId() + "/photoid/" + comment.getPhoto().getId()); CommentEntry entry = commentToEntry(comment); getSessionService().insert(commentsFeedUrl, entry); } catch (Exception e) { e.printStackTrace(); } } @Override public PhotoComment[] getComments(Photo photo) { PhotoComment[] comments = null; try { URL commentsFeedUrl = new URL(BASE_URL + photo.getAlbum().getOwner() photo.getAlbum().getId() + "/photoid/" + photo.getId() + "?kind=comment");

"/albumid/"

PhotoFeed photoFeed = getSessionService().getFeed(commentsFeedUrl, PhotoFeed.class); List<CommentEntry> commentEntries = photoFeed.getCommentEntries(); comments = new PhotoComment[commentEntries.size()]; for (int i = 0; i < commentEntries.size(); i++) { PhotoComment comment = entryToComment(commentEntries.get(i)); comment.setPhoto(photo); comments[i] = comment; } } catch (Exception e) { e.printStackTrace(); } return comments; } }

Para concluir a implementao do nosso servio, necessrio configurar nosso servlet no arquivo web.xml, assim como fazemos numa aplicao web Java tradicional. A Listagem 9 mostra o resultado do nosso arquivo web.xml.
Listagem 9. Arquivo web.xml com as configuraes do nosso servio.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>picasaServlet</servlet-name> <servlet-class>br.com.jm.picasa.server.PicasaServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>picasaServlet</servlet-name> <url-pattern>/javamagazinepicasa/picasa</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>JavaMagazinePicasa.html</welcome-file> </welcome-file-list>

20/2
</web-app>

A camada de apresentao

Com nosso servio devidamente criado e configurado, resta implementar o cdigo da camada de apresentao da nossa aplicao. Como no o foco deste artigo mostrar em detalhes o GWT, no explicaremos linha por linha o cdigo da classe JavaMagazinePicasa, que pode ser visto, em parte, na Listagem 10 (o cdigo completo est disponvel para download no site da Java Magazine). Tambm no entraremos em detalhes a respeito do contedo dos arquivos JavaMagazinePicasa.html e JavaMagazinePicasa.css. Vejamos agora, apenas os pontos principais da classe JavaMagazinePicasa. Primeiro, temos o atributo picasaService do tipo PicasaServiceAsync, que criado atravs do mtodo GWT.create(), que recebe o tipo da interface de servio, PicasaService.class. Note que o cdigo cliente no deve acessar a interface de servio (e muito menos a implementao deste) diretamente. Todo acesso ao servio deve ser feito atravs da interface assncrona. O segundo ponto que merece ateno especial o mtodo onModuleLoad(). Este o ponto de entrada de uma aplicao GWT, assim como o main() de uma aplicao tradicional. Nesse mtodo, podemos construir as partes dinmicas da nossa interface grfica, inicializar variveis, bem como configurar tratadores de eventos para os componentes da aplicao, sejam esses visuais, como um Button, ou no, como um Timer. No nosso exemplo, criamos alguns elementos grficos e painis, que servem para organizar o layout. Observe o trecho RootPanel.get(loginPanel).add(pnlMain). Essa a forma com a qual o GWT permite que elementos declarados no HTML sejam acessados a partir do cdigo Java. Nesse caso estamos acessando o container com ID loginPanel. No mtodo listUserAlbums() podemos ver dois exemplos de chamadas assncronas ao nosso servio, PicasaService. Nele verificamos se o usurio est logado no servio: caso esteja, invocamos o mtodo listAlbums(); caso contrrio, primeiro chamamos o mtodo login() e na sua callback invocamos listAlbums(). O arquivo JavaMagazinePicasa.html (Listagem 11) um arquivo HTML simples que define a parte esttica da interface grfica. Observe a tag <script>, nela que inclumos o cdigo Javascript gerado pelo GWT. O elemento <iframe> opcional e serve para permitir que o GWT possa manipular o histrico. Em seguida temos uma tabela e uma div. Na tabela temos uma clula com o ID loginPanel, que exatamente o ID que referenciamos no mtodo onModuleLoad() da classe JavaMagazinePicasa. Do mesmo modo, estamos expondo a div com o ID contentArea para o cdigo Java. O arquivo JavaMagazinePicasa.css (Listagem 12) define os estilos utilizados pela aplicao.
importante lembrar que apesar do nosso exemplo ter sido uma aplicao web, podemos utilizar as APIs de dados em qualquer tipo de aplicao, seja web, desktop ou mobile. Lembramos tambm que o cdigo fonte dos exemplos que vimos neste artigo est disponvel para download no site da Java Magazine.
Listagem 10. Verso final da classe JavaMagazinePicasa.
// Declarao de pacote e imports omitidos... public class JavaMagazinePicasa implements EntryPoint { // declarao dos componentes grficos e constantes omitidos. private final PicasaServiceAsync picasaService = GWT.create(PicasaService.class); public void onModuleLoad() { final Button sendButton = new Button("Get Albums"); sendButton.addStyleName("sendButton"); txtPicasaUser.setFocus(true); txtPicasaUser.selectAll(); VerticalPanel pnlMain = new VerticalPanel(); pnlMain.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);

21/2
HorizontalPanel pnlLogin = new HorizontalPanel(); pnlLogin.setSpacing(5); Label lblUsername = new Label("Username: "); pnlLogin.add(lblUsername); pnlLogin.add(txtUsername); Label lblPassword = new Label("Password: "); pnlLogin.add(lblPassword); pnlLogin.add(txtPassword); HorizontalPanel pnlUser = new HorizontalPanel(); pnlUser.setSpacing(5); Label lblPicasaUser = new Label("Picasa User:"); pnlUser.add(lblPicasaUser); pnlUser.add(txtPicasaUser); pnlUser.add(sendButton); pnlMain.add(pnlLogin); pnlMain.add(pnlUser); RootPanel.get("loginPanel").add(pnlMain); class MyHandler implements ClickHandler, KeyUpHandler { public void onClick(ClickEvent event) { listUserAlbums(); } public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { listUserAlbums(); } } } MyHandler handler = new MyHandler(); sendButton.addClickHandler(handler); txtPicasaUser.addKeyUpHandler(handler); } private void buildAlbumList(Album[] albums) { // Monta a lista de lbuns na tela... } private void listUserAlbums() { final String user = !txtPicasaUser.getText().trim().equals("") ? txtPicasaUser.getText() : txtUsername.getText(); final AsyncCallback<Album[]> callback = new AsyncCallback<Album[]>() { @Override public void onFailure(Throwable caught) { Window.alert("Erro List!!!!"); } @Override public void onSuccess(Album[] result) { buildAlbumList(result); } }; if (!loggedIn) { picasaService.login(txtUsername.getText(), txtPassword.getText(), new AsyncCallback<Void>() { @Override public void onFailure(Throwable caught) { Window.alert("Erro Login!!!!"); } @Override public void onSuccess(Void result) { loggedIn = true; picasaService.listAlbums(user, callback); } }); } else { picasaService.listAlbums(user, callback); }

22/2
} private void getAlbumContent(final Album album) { picasaService.getAlbumContents(album, new AsyncCallback<Album>() { @Override public void onFailure(Throwable caught) { Window.alert("Error retrieving album content: " + caught.getMessage()); } @Override public void onSuccess(Album result) { showAlbumContents(result); } }); } private void showAlbumContents(final Album album) { // Exibe o contedo do lbum na tela... } private void showPhotoComments(final PhotoComment[] comments, Panel container) { // Exibe a lista de comentrios da foto atual... } }

Listagem 11. Arquivo JavaMagazinePicasa.html.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link type="text/css" rel="stylesheet" href="JavaMagazinePicasa.css"> <title>Java Magazine's Picasa Web Albums Client</title> <script type="text/javascript" language="javascript" src="javamagazinepicasa/javamagazinepicasa.nocache.js"></script> </head> <body> <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> <noscript> <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif"> Your web browser must have JavaScript enabled in order for this application to display correctly. </div> </noscript> <h1>Java Magazine's Picasa Web Albums Client</h1> <table align="center"> <tr> <td id="loginPanel"></td> </tr> </table> <div id="contentArea" align="center"></div> </body> </html>

Listagem 12. Arquivo JavaMagazinePicasa.css.


h1 { font-size: 2em; font-weight: bold; color: #777777; text-align: center; margin-bottom: 0; } h3 { font-size: 9px; font-weight: normal; margin-top: 0;

23/2
text-align: center; } .sendButton { display: block; font-size: 16pt; } .clickableImage { cursor: pointer; }

Para finalizar, veremos agora como publicar nossa aplicao no GAE, deixando-a pblica para ser acessada de qualquer lugar. Para isso, basta seguir os passos abaixo: 1. Acesse http://appengine.google.com e faa o login com seu usurio Google; 2. Escolha a opo Create an Application, preencha o ID e ttulo da sua aplicao, e clique em Save (Figura 8); 3. De volta ao projeto, edite o arquivo appengine-web.xml (que foi visto na Listagem 2) adicionando o ID da aplicao que acabou de criar na tag <application> (Ex.: <application>jm-picasa-test</application>); 4. Clique com o boto direito no projeto e escolha a opo Google>Deploy to App Engine, preencha os campos e-mail e password com os mesmos e-mail e senha utilizados no passo 1, e clique em Deploy (Figura 9). Com isso o plugin ir compilar sua aplicao utilizando o compilador do GWT e fazer o deploy da mesma no GAE. Encerrado o processo, sua aplicao estar disponvel no endereo http://<appId>.appspot.com (Ex.: http://jm-picasa-test.appspot.com).

Publicando a aplicao no GAE

Figura 8.Tela de criao de nova aplicao no GAE.

24/2

Figura 9. Tela de deploy do Google Plugin para o GAE.

Concluses
Neste artigo aprendemos como integrar uma aplicao Java com o servio de compartilhamento de fotos do Google, o Picasa Web Albums. Vimos pequenos exemplos do funcionamento da API e construmos um projeto completo utilizando a Biblioteca Cliente Java. Tambm utilizamos o GWT para facilitar a construo do nosso projeto web e o GAE para publicar o mesmo. Com isso, foi mostrado como possvel manipular lbuns, fotos, vdeos, tags e comentrios de forma fcil e prtica, por meio da Picasa Web Albums Data API. Alm disso, tambm aprendemos a utilizar o Google Plugin para Eclipse, que torna o desenvolvimento em GWT e o deploy no GAE tarefas extremamente simples.

De que se trata o artigo:

Neste artigo aprenderemos a integrar uma aplicao Java com o servio de fotos do Google, o Picasa Web Albums (PWA). Veremos como possvel manipular os lbuns, fotos, tags e comentrios do usurio. Tudo isso forma prtica, utilizando a biblioteca cliente Java, o Google Web Toolkit e o Google App Engine.
Para que serve:

Assim como as demais APIs de dados Google, a Picasa Web Albums Data API permite que nossas aplicaes possam se integrar com algum servio Google: neste caso, o PWA. Com ela, podemos construir, por exemplo, um cliente desktop para ver os lbuns e fotos do usurio, uma aplicao que grave e faa upload de vdeos direto do celular, dentre outras possibilidades.
Em que situao o tema til:

O tema til no contexto da criao e utilizao de servios, que visa promover o reuso e evitar o retrabalho. A ideia bsica poder construir software aproveitando ao mximo os diversos servios existentes. Assim, cada vez mais possvel concentrar esforos nas regras de negcio do software, reduzir o tempo de desenvolvimento e ter a garantia de um servio testado e confivel.
Google Documents List Data API:

A Picasa Web Albums Data API permite que nossas aplicaes possam interagir com o Picasa Web Albums, possibilitando a execuo de operaes bsicas como listar, criar, editar e excluir os lbuns, fotos, vdeos, tags e comentrios do usurio. Para utilizar essa API, a biblioteca do Google disponibiliza uma srie de classes que representam os servios, como a classe PicasawebService, e tipos de dados utilizados pelo PWA, tornando o desenvolvimento bastante simples.

25/2 O artigo tambm mostra como criar e publicar uma aplicao web com GWT e GAE, utilizando o Google Plugin para Eclipse, que deixa o processo de desenvolvimento e publicao extremamente prtico.

[EOS1] Comentrio: Paulo, reduzir um pouco mais esse trecho. Ele est repetindo muito o que foi comentado nas outras leads.

Links
http://picasaweb.google.com Site do Picasa Web Albums. https://www.google.com/accounts/PurchaseStorage?hl=en_US Lista dos planos de armazenamento oferecidos pelo Picasa Web Albums. http://code.google.com/apis/gdata/ Site oficial das Google Data APIs. http://googledataapis.blogspot.com/ Blog oficial das Google Data APIs. http://code.google.com/apis/picasaweb/ Site oficial da Google Picasa Web Albums Data API. http://code.google.com/apis/picasaweb/docs/2.0/developers_guide_java.html Guia da desenvolvimento da API do Picasa Web Albums para desenvolvedores Java. http://code.google.com/apis/picasaweb/docs/2.0/reference.html Guia da referncia da API do Picasa Web Albums. http://code.google.com/apis/picasaweb/docs/2.0/developers_guide_protocol.html Guia do protocolo da API do Picasa Web Albums. http://code.google.com/p/gdata-java-client/downloads/list Site para download da Java Client Library. http://code.google.com/eclipse/ Site oficial do Google Plugin para Eclipse. http://code.google.com/webtoolkit/ Site oficial do Google Web Toolkit (GWT). http://code.google.com/appengine/ Site oficial do Google App Engine. Paulo Csar M. N. A. Coutinho (pcmnac@gmail.com / www.pcmnac.com) mestrando em Engenharia de Software, com foco em modelagem de device drivers para sistemas embarcados, pela unidade educacional do Centro de Estudos e Sistemas Avanados do Recife (C.E.S.A.R), onde trabalha como Engenheiro de Sistemas, atualmente na implementao de APIs para impressoras bancrias. Tem experincia no desenvolvimento e projeto de aplicaes Java, C/C++ e Flex. Possui as certificaes SCJP 5 e SCWCD 1.4.

Você também pode gostar