網頁

2011年12月8日 星期四

Gae Web Service (Java)

Last Update: 2011/12/09 13:33+08
Type: Note

Intro

這只是一篇學習筆記
若看倌們對這個標題有興趣
可參考最下面的 Reference~

根據官方文章說法, GAE 不支援使用JAX-WS, 因此要自己用 wsgen, wsimport 來實作 Web Service.

步驟
1. 建立 Web Application Project
2. 建立 WebMethod (Web Service API)
3. 使用 wsgen 產生所需檔案
4. 產生可執行的實例


Content


1. 建立 Web Application Project
基本的, 不贅述~
新增一個 GAE 的 Web Application Project
這裡跟官方文章一樣, 方便比對
Project Name: HelloSOAPServer
Package: com.example


2. 建立 WebMethod (Web Service API)
再來建立你要提供給別人使用的API
新增一個類別
Name: Greeter
Package: com.example
Code...
package com.example;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

@WebService
public class Greeter {
 @WebMethod
 public String sayHello(@WebParam(name = "name") String name) {
  return "Hello, " + name + "!";
 }
}


3. 使用 wsgen 產生所需檔案
在 cmd 執行
wsgen -cp "$clpth" -wsdl -keep -r "$resourcedir" -d "$outdir" -s "$outsourcedir"  $class
其中的
class=com.example.Greeter
  類別的完整名稱
clpth='./war/WEB-INF/classes'
  Greeter(來源類別)的輸出路徑
resourcedir='./war'
  存放 wsdl 檔的位置
outsourcedir='./src'
  Source Code 位置
outdir='./war/WEB-INF/classes'
  wsgen產生的類別輸出路徑

然後重整專案後, 您會看到 wsgen 產生的檔案


Note:
您需要到 GreeterService.wsdl 檔案底下去修改一個字串
REPLACE_WITH_ACTUAL_URL
如下所示:
<service name="GreeterService">
    <port name="GreeterPort" binding="tns:GreeterPortBinding">
      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
置換成您實際上要進入的點(路徑)
例如 http://application-id.appspot.com/hellosoapserver
我在本機測試就用 http://localhost:9999/hellosoapserver

4. 產生可呼叫的實例
OK, 再來就做出可以被執行的進入點和實體
由於 GAE 沒有提供這方面的東東
所以得自己寫~
這個範本大致上是解析SAOPMessage
然後派發到正確的Service Method
到這就不用多話了
三個檔案建立後再自己看怎麼改唄

GreeterAdapter.java
package com.example;

import com.example.jaxws.SayGoodbye;
import com.example.jaxws.SayGoodbyeResponse;
import com.example.jaxws.SayHello;
import com.example.jaxws.SayHelloResponse;

public class GreeterAdapter {
 private Greeter greeter = new Greeter();

 public SayHelloResponse sayHello(SayHello request) {
  String name = request.getName();
  String responseGreeting = greeter.sayHello(name);
  SayHelloResponse response = new SayHelloResponse();
  response.setReturn(responseGreeting);
  return response;
 }
}

GreeterSOAPHandler.java
package com.example;

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.SayGoodbye;
import com.example.jaxws.SayHello;

public class GreeterSOAPHandler {
 private static final String NAMESPACE_URI = "http://localhost:9999/";
 private static final QName SAY_HELLO_QNAME = new QName(NAMESPACE_URI,
   "sayHello");
 private static final QName SAY_GOODBYE_QNAME = new QName(NAMESPACE_URI,
   "sayGoodbye");
 private MessageFactory messageFactory;
 private GreeterAdapter greeterAdapter;

 public GreeterSOAPHandler() throws SOAPException {
  messageFactory = MessageFactory.newInstance();
  greeterAdapter = new GreeterAdapter();
 }

 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 (SAY_HELLO_QNAME.equals(qname)) {
     responsePojo = handleSayHelloRequest(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 handleSayHelloRequest(SOAPElement soapElement) {
  SayHello sayHelloRequest = JAXB.unmarshal(new DOMSource(soapElement),
    SayHello.class);
  return greeterAdapter.sayHello(sayHelloRequest);
 }

}

HelloSOAPServerServlet.java
就是一個srevice的進入點
package com.example;

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 HelloSOAPServerServlet extends HttpServlet {
 static MessageFactory messageFactory;
 static GreeterSOAPHandler soapHandler;
 static {
  try {
   messageFactory = MessageFactory.newInstance();
   soapHandler = new GreeterSOAPHandler();
  } catch (Exception ex) {
   throw new RuntimeException(ex);
  }
 }

 @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;
 }
}

這樣 Server 就算完工了
B.R.~


Reference

GAE Official Article

1 則留言: