INSTALAÇÃO E USO DO GOOGLE APP ENGINE PLUGIN utilizando o Eclipse Galileo Requisitos de Ambiente: Desenvolvido por: Fabrício Alves e Daniela Claro contato: fabufbc@dcc.ufba.br, dclaro@ufba.br Java 1.6 http://java.sun.com/javase/downloads/widget/jdk6.jsp Google App engine Plugin http://code.google.com/intl/pt-br/eclipse/docs/download.html Sumário: A partir da versão 1.4.2 do Google App Engine é possível utilizar java.soap.xml e JAX-B para desenvolver um servidor SOAP. Este tutorial visa construir uma simples aplicação que recebe como parâmetro uma temperatura medida em Farenheit e devolve se este tempo é considerado Frio ou Quente. 1. Abra o Wizard de Criação de novo projeto, clicando no botão Google Service and Development Tools que se encontra na Barra de Ferramentas. Figura 1: Criando um novo Projeto de Aplicação web do App Engine Dê ao projeto o nome WeatherSOAPServer e insira o valor com.example no campo Package. Desmarque a opção Use Google Web Toolkit. Figura 2: Nomeando o Serviço Perceba que a classe WeatherSOAPServerServlet.java foi criada automaticamente. Esta classe será importante futuramente, pois gerencia as requisições feitas ao servidor. 2. Crie dentro do pacote com.example a classe ClimaInfo, clicando com o botão direito sobre o pacote e escolhendo a opção New > Class.
Figura 3: Criação de Classe Nós vamos manter esta classe muito simples. Ela terá apenas o método comoestaotempo: public class ClimaInfo { public String comoestaotempo(int temperatura){ if(temperatura > 30){ return "Quente"; else if(temperatura < 15){ return "Frio"; else{ return "Agradavel"; 3. Adicione as anotações de WebService, presentes no pacote javax.jws.webmethod. Tais anotações serão levadas em consideração no momento de criação do WSDL. import javax.jws.webmethod; import javax.jws.webservice; @WebService public class ClimaInfo { @WebMethod public String comoestaotempo(int temperatura){ if(temperatura > 30){ return "Quente"; else if(temperatura < 15){ return "Frio"; else{ return "Agradavel";
Apesar do Google App Engine não suportar a utilização de JAX-WS no SOAP Server, iremos utilizá-lo para criar o arquivo wsdl automaticamente. 4. Vamos utilizar o wsgen, programa contigo no java JDK (à partir da versão 1.6), que gera wsdl a partir de anotações feitas no código. Além disso, o wsgen gera os POJOS, que são as classes que serão responsáveis pelo request e response. Entre na interface de comandos, acesse o diretório do projeto criado (workspace/weathersoapserver/) e cole o seguinte comando: wsgen -cp ".\war\web-inf\classes" -wsdl -keep -r ".\war" -d ".\war\web-inf\classes" -s ".\src" com.example.climainfo Este comando é explicado da seguinte forma: A opção -cp indica onde o wsgen irá encontrar o arquivo ClimaInfo.class para gerar o WSDL. A opção -r indica onde o wsdl será gerado. A opção -d indica onde serão colocados os arquivos.class gerados. A opção -s indica onde serão colocados os arquivos fontes dos POJOS gerados. Por fim, a última opção indica qual será a classe que será transformada em Serviço Web. Selecione o projeto e pressione a tecla f5, para que os arquivos gerados sejam vistos dentro do Eclipse. 5. Coloque a URL de request do serviço dentro do WSDL. Abra o WSDL gerado, dentro do diretório war, e veja que o campo location, possui o valor REPLACE_WITH_ACTUAL_URI. Tal URI é o ponto de acesso para o serviço, ou seja, a URI da sua aplicação no Google App Engine. Geralmente esta URI é formada por <application-id>.appspot.com. <service name="climainfoservice"> <port name="climainfoport" binding="tns:climainfoportbinding"> <soap:address location="http://<application-id>.appspot.com/weathersoapserver"/> </port> </service> 6. Codificar um Adapatador que faça a ligação entre os POJOS gerados e a o verdadeiro código do Serviço Web. Obs: arquivo fonte presente em http://homes.dcc.ufba.br/~fabufbc#tutorialowls import com.example.jaxws.comoestaotempo; import com.example.jaxws.comoestaotemporesponse; public class ClimaInfoAdaptador { private ClimaInfo climainfo = new ClimaInfo(); public ComoEstaOTempoResponse comoestaotempo(comoestaotempo request){ int temperatura = request.getarg0(); String comoestaotempo = climainfo.comoestaotempo(temperatura); ComoEstaOTempoResponse response = new ComoEstaOTempoResponse(); response.setreturn(comoestaotempo); return response;
7. Criar um Gerenciador entre a requisição e o Adaptador. Quando a requisição SOAP é feita para o servidor, a única coisa que é passada é um XML contendo o soapbody. Este soapbody informa quais os argumentos e seus valores. No entanto, é necessário que haja uma classe que recupere este XML e saiba qual serviço chamar. Caso o Google App Engine suportasse JAX-WS ou AXIS, este passo não seria necessário. Obs: arquivo fonte presente em http://homes.dcc.ufba.br/~fabufbc#tutorialowls import java.util.iterator; import javax.xml.bind.jaxb; import javax.xml.namespace.qname; import javax.xml.soap.messagefactory; import javax.xml.soap.saajresult; import javax.xml.soap.soapbody; import javax.xml.soap.soapelement; import javax.xml.soap.soapexception; import javax.xml.soap.soapfault; import javax.xml.soap.soapmessage; import javax.xml.transform.dom.domsource; import com.example.jaxws.comoestaotempo; public class ClimaInfoSoapHandler { private static final String NAMESPACE_URI = "http://example.com/"; private static final QName COMO_ESTA_O_TEMPO_QNAME = new QName(NAMESPACE_URI, "comoestaotempo"); private MessageFactory messagefactory; private ClimaInfoAdaptador climainfoadapter; public ClimaInfoSoapHandler() throws SOAPException { messagefactory = MessageFactory.newInstance(); climainfoadapter = new ClimaInfoAdaptador(); public SOAPMessage handlesoaprequest(soapmessage request) throws SOAPException { SOAPBody soapbody = request.getsoapbody(); Iterator iterator = soapbody.getchildelements(); Object responsepojo = null; while (iterator.hasnext()) { Object next = iterator.next(); if (next instanceof SOAPElement) { SOAPElement soapelement = (SOAPElement) next; QName qname = soapelement.getelementqname(); if (COMO_ESTA_O_TEMPO_QNAME.equals(qname)) { responsepojo = handlecomoestaotemporequest(soapelement); break; SOAPMessage soapresponse = messagefactory.createmessage(); soapbody = soapresponse.getsoapbody(); if (responsepojo!= null) { JAXB.marshal(responsePojo, new SAAJResult(soapBody)); else { SOAPFault fault = soapbody.addfault(); fault.setfaultstring("unrecognized SOAP request."); return soapresponse; private Object handlecomoestaotemporequest(soapelement soapelement) { ComoEstaOTempo comoestaotemporequest = JAXB.unmarshal(new DOMSource(soapElement), ComoEstaOTempo.class); return climainfoadapter.comoestaotempo(comoestaotemporequest); 8. Informar ao Servlet o que fazer quando for uma requisição SOAP. Todas as requisições feitas ao servidor são gerenciadas pelo Servlet. Logo, é necessário informá-lo que deverá chamar o handler quando a requisição for SOAP. Sendo assim, dentro do servlet vamos criar
uma função dopost() que realizará esta chamada. Obs: arquivo fonte presente em http://homes.dcc.ufba.br/~fabufbc#tutorialowls import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.util.enumeration; import java.util.stringtokenizer; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import javax.xml.soap.messagefactory; import javax.xml.soap.mimeheaders; import javax.xml.soap.soapexception; import javax.xml.soap.soapmessage; @SuppressWarnings("serial") public class WeatherSOAPServerServlet extends HttpServlet { static MessageFactory messagefactory; static ClimaInfoSoapHandler soaphandler; static { try { messagefactory = MessageFactory.newInstance(); soaphandler = new ClimaInfoSoapHandler(); catch (Exception ex) { throw new RuntimeException(ex); public void doget(httpservletrequest req, HttpServletResponse resp) throws IOException { resp.setcontenttype("text/plain"); resp.getwriter().println("hello, world"); @Override public void dopost(httpservletrequest req, HttpServletResponse resp) throws IOException { try { // Get all the headers from the HTTP request MimeHeaders headers = getheaders(req); // Construct a SOAPMessage from the XML in the request body InputStream is = req.getinputstream(); SOAPMessage soaprequest = messagefactory.createmessage(headers, is); // Handle soapreqest SOAPMessage soapresponse = soaphandler.handlesoaprequest(soaprequest); // Write to HttpServeltResponse resp.setstatus(httpservletresponse.sc_ok); resp.setcontenttype("text/xml;charset=\"utf-8\""); OutputStream os = resp.getoutputstream(); soapresponse.writeto(os); os.flush(); catch (SOAPException e) { throw new IOException("Exception while creating SOAP message.", e); @SuppressWarnings("unchecked") static MimeHeaders getheaders(httpservletrequest req) { Enumeration headernames = req.getheadernames(); MimeHeaders headers = new MimeHeaders(); while (headernames.hasmoreelements()) { String headername = (String) headernames.nextelement(); String headervalue = req.getheader(headername); StringTokenizer values = new StringTokenizer(headerValue, ","); while (values.hasmoretokens()) { headers.addheader(headername, values.nexttoken().trim());
return headers; 9. Por fim, realizar a publicação no Google App Engine. Clique com o botão direito sobre o projeto e escolha Google > App Engine Settings. No campo Application ID, vamos colocar o ID da aplicação, criada anteriormente. Referências: [1] HOW TO: Build a SOAP Server and a SOAP Client on Google App Engine, disponível em: http://code.google.com/intl/pt-br/appengine/articles/soap.html, último acesso em 23/11/2011