Terry.Li-彬

          虛其心,可解天下之問;專其心,可治天下之學;靜其心,可悟天下之理;恒其心,可成天下之業。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks
          本文是在理解官方指南的基礎上,用實例實現Axis2提供的4種調用機制,并給出測試結果。
          author: ZJ 07-3-13
          Blog:
          http://zhangjunhd.blog.51cto.com/
           
          1.使用Axis2的底層API開發Web Service Server端
          1.1創建一個WebService(取名為MyService)
              在MyService中有兩個operations,如下所示。
          public void ping(OMElement element){}//IN-ONLY模式。僅僅接收OMElement,并對其處理。
          public OMElement echo(OMElement element){}//IN_OUT模式。接收OMElemen,并返回OMElement。
           
          1.2如何寫Web Service
          1)創建實現服務的類。
          2)創建services.xml來解析這個Web Service。
          3)將其打包成一個*.aar文檔(Axis Archive)。
          4)部署Web Service。
           
          1.2.1 創建實現服務的類
              此類中提供的方法必須與Web Service(在services.xml中聲明)中的operations對應。除非你提供了數據綁定,否則所有的方法只能接收一個參數,其類型為OMElement。
          public class MyService{
            public void ping(OMElement element){...}
            public OMElement echo(OMElement element){...}
          }
          MyService.java
          package userguide.example1;
          import org.apache.axiom.om.OMElement;
          import org.apache.axis2.AxisFault;
          import javax.xml.stream.XMLStreamException;
          public class MyService {
              public OMElement echo(OMElement element) throws XMLStreamException {
                  //Praparing the OMElement so that it can be attached to another OM Tree.
                  //First the OMElement should be completely build in case it is not fully built and still
                  //some of the xml is in the stream.
                  element.build();
                  //Secondly the OMElement should be detached from the current OMTree so that it can
                  // be attached some other OM Tree. Once detached the OmTree will remove its
                 // connections to this OMElement.
                  element.detach();
                  return element;
              }
              public void ping(OMElement element) throws XMLStreamException {
                  //Do some processing
              }
              public void pingF(OMElement element) throws AxisFault{
                  throw new AxisFault("Fault being thrown");
              }
          }
           
          1.2.2 創建services.xml
              Axis2使用services.xml來充當一個Web Servicea的配置文件。每一個使用Axis2部署的Web Service都必須擁有一個services.xml。
          <services>
            <description>
              This is a sample Web Service with two operations,echo and ping.
            </description>
            <parameter name=”ServiceClass” locked=”false”>
            userguide.example1.MyService
            </parameter>
            <operation name=”echo”>
              <messageReceiver class=”org.apache.axis2.receivers.RawXMLINOutMessageReceiver”/>
              <actionMapping>urn:echo</actionMapping>
            </operation>
            <operation name=”ping”>
              <messageReceiver class=”org.apache.receivers.RawXMLINOnlyMessageReceiver”/>
              <actionMapping>urn:ping</actionMapping>
            </operation>
          </service>
          注:The actionMapping is required only if you want to enable WS-Addressing.
              可以創建一個services.xml,其中包含一組服務。這樣在運行期,你可以在這些服務間共享信息。
          <serviceGroup>
            <service name=”Service1”>
              <!--details for Services1-->
            </service>
          <service name=”Service2”>
              <!--details for Services2-->
            </service>
            <module ref=”ModuleName”/>
            <parameter name=”serviceGroupParam1” locked=”false”>value1</parameter>
          </serviceGroup>
          注:name of the service is a compulsory attribute.
           
          1.2.3打包與部署
              這里不再詳述,參見《
          基于Tomcat5.0和Axis2開發Web Service應用實例 》。
           
          2.使用Axis2底層APIs實現Web Service客戶端
          2.1ClientUtil
              創建一個客戶端通用的SOAP包裝Util文件。封裝"getEchoOMElement"和"getPingOMElement"分別對應"echo"和"ping"這兩個operation。
          ClientUtil.java
          package userguide.clients;
          import org.apache.axiom.om.OMAbstractFactory;
          import org.apache.axiom.om.OMElement;
          import org.apache.axiom.om.OMFactory;
          import org.apache.axiom.om.OMNamespace;
          public class ClientUtil {
              public static OMElement getEchoOMElement() {
                  OMFactory fac = OMAbstractFactory.getOMFactory();
                  OMNamespace omNs = fac.createOMNamespace(
                          "
          http://example1.org/example1", "example1");
                  OMElement method = fac.createOMElement("echo", omNs);
                  OMElement value = fac.createOMElement("Text", omNs);
                  value.addChild(fac.createOMText(value, "Axis2 Echo String "));
                  method.addChild(value);
                  return method;
              }
              public static OMElement getPingOMElement() {
                  OMFactory fac = OMAbstractFactory.getOMFactory();
                  OMNamespace omNs = fac.createOMNamespace(
                          "
          http://example1.org/example1", "example1");
                  OMElement method = fac.createOMElement("ping", omNs);
                  OMElement value = fac.createOMElement("Text", omNs);
                  value.addChild(fac.createOMText(value, "Axis2 Ping String "));
                  method.addChild(value);
                  return method;
              }
          }
           
          2.2EchoBlockingClient
              Axis2向用戶提供了從blocking single channel調用到non-blocking dual channel調用的多種調用Web Service的模式。下面用最簡單的blocking調用機制來實現”MyService”中的"echo" operation。
          EchoBlockingClient.java
          package userguide.clients;
          import org.apache.axiom.om.OMElement;
          import org.apache.axis2.AxisFault;
          import org.apache.axis2.addressing.EndpointReference;
          import org.apache.axis2.client.Options;
          import org.apache.axis2.client.ServiceClient;
          /**
           * Sample for synchronous single channel blocking service invocation.
           * Message Exchage Pattern IN-OUT
           */
          public class EchoBlockingClient {
          private static EndpointReference targetEPR =
           new EndpointReference("
          http://localhost:8080/axis2/services/MyService");
              public static void main(String[] args) {
          try {
                      OMElement payload = ClientUtil.getEchoOMElement();
                  
              Options options = new Options();
                      options.setTo(targetEPR); // this sets the location of MyService service
                      ServiceClient serviceClient = new ServiceClient();
                      serviceClient.setOptions(options);
                      OMElement result = sender.sendReceive(payload);
                      System.out.println(result);
          } catch (AxisFault axisFault) {
                   axisFault.printStackTrace();
          }
          }
              綠色部分顯示了為了調用一個Web Service而需要對operation作的設置。剩下的部分是用來創建OMElement,用來發送和顯示相應的OMElement。
           
          結果:
          <example1:echo xmlns:example1="http://example1.org/example1"
          xmlns:tns="
          http://ws.apache.org/axis2">
          <example1:Text>
          Axis2 Echo String
          </example1:Text>
          </example1:echo>
           
          2.3 PingClient
              在”MyService”中,我們有一種IN-ONLY模式的名為"ping"的operation。應用它的客戶端代碼如下:
          PingClient.java
          package userguide.clients;
          import org.apache.axiom.om.OMElement;
          import org.apache.axis2.AxisFault;
          import org.apache.axis2.addressing.EndpointReference;
          import org.apache.axis2.client.Options;
          import org.apache.axis2.client.ServiceClient;
          /**
           * Sample for fire-and-forget service invocation
           * Message Exchage Pattern IN-Only
           */
          public class PingClient {
          private static EndpointReference targetEPR =
           new EndpointReference("
          http://localhost:8080/axis2/services/MyService");
              public static void main(String[] args) {
          try {
                 OMElement payload = ClientUtil.getPingOMElement();
                 Options options = new Options();
                 options.setTo(targetEPR);
                 ServiceClient serviceClient = new ServiceClient();
                 serviceClient.setOptions(options);
                
          serviceClient.fireAndForget(payload);
                  /**
                   * We have to block this thread untill we send the request , the problem
                   * is if we go out of the main thread , then request wont send ,so
                   * you have to wait some time :)
                   */
                 Thread.sleep(500);
               }
          catch (AxisFault axisFault) {
                      axisFault.printStackTrace();
               }
          }
              由于我們在訪問一個IN-ONLY模式的operation,所以我們可以直接使用ServiceClient中的"fireAndForget()"方法來調用這個operation。而且那樣做的話,不會阻塞發起端,因此,它會立刻將控制權返回給客戶端。
           
          2.4 EchoNonBlockingClient
              在客戶端EchoBlockingClient,一旦調用"serviceClient.sendReceive(payload);",客戶端將會被阻 塞直到operation完成。這種方式在有很多Web Service需要在一個單一的客戶端應用程序中啟動時很不可取。一種解決方法是使用Non-Blocking API來調用這些Web Services。Axis2提供給用戶一種基于回叫機制的non-blocking API。
          EchoNonBlockingClient.java
          package userguide.clients;
          import org.apache.axiom.om.OMElement;
          import org.apache.axis2.AxisFault;
          import org.apache.axis2.addressing.EndpointReference;
          import org.apache.axis2.client.Options;
          import org.apache.axis2.client.ServiceClient;
          import org.apache.axis2.client.async.AsyncResult;
          import org.apache.axis2.client.async.Callback;
          /**
           * Sample for asynchronous single channel non-blocking service invocation.
           * Message Exchage Pattern IN-OUT
           */
          public class EchoNonBlockingClient {
          private static EndpointReference targetEPR =
           new EndpointReference("
          http://127.0.0.1:8080/axis2/services/MyService");
              public static void main(String[] args) {
                  ServiceClient sender = null;
                  try {
                      OMElement payload = ClientUtil.getEchoOMElement();
                      Options options = new Options();
                      options.setTo(targetEPR);
                      //Callback to handle the response
                     
          Callback callback = new Callback() {
                          public void onComplete(AsyncResult result) {
                              System.out.println(result.getResponseEnvelope());
                          }
                          public void onError(Exception e) {
                              e.printStackTrace();
                          }
                      };
                      //Non-Blocking Invocation
                      sender = new ServiceClient();
                      sender.setOptions(options);
                     
          sender.sendReceiveNonBlocking(payload, callback);
                      //Wait till the callback receives the response.
                      while (!callback.isComplete()) {
                          Thread.sleep(1000);
                      }
                  } catch (AxisFault axisFault) {
                      axisFault.printStackTrace();
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  } finally {
                      try {
                          sender.finalizeInvoke();
                      } catch (AxisFault axisFault) { }
                  }
              }
          }
           
          結果:
          <?xml version='1.0' encoding='utf-8'?>
          <soapenv:Envelope xmlns:soapenv="
          http://schemas.xmlsoap.org/soap/envelope/">
          <soapenv:Header />
          <soapenv:Body>
          <example1:echo xmlns:example1="
          http://example1.org/example1"
          xmlns:tns="
          http://ws.apache.org/axis2">
          <example1:Text>
          Axis2 Echo String
          </example1:Text>
          </example1:echo>
          </soapenv:Body>
          </soapenv:Envelope>
              sender.sendReceiveNonBlocking(payload, callback);這個調用接受一個callback對象作為參數。Axis2客戶端API提供了一個抽象類CallBack,其中提供了方法:
          public abstract void onComplete(AsyncResult result);
          public abstract void onError(Exception e);
          public boolean isComplete() {}
              用戶需要重寫"onComplete " 和 "onError "方法。一旦客戶端收到Web Service的response,onComplete方法將會被調用,這樣將中止阻塞狀態。
           
          2.5EchoNonBlockingDualClient
              當調用的Web Service需要很長一段時間來完成時,這種由Non-Blocking API提供的解決方式將有一定的局限性。這種局限性是由使用單一的傳輸連接來調用Web Service并接收response造成的。換句話說,客戶端提供一種沒有阻塞的調用機制,但request和response的傳輸使用單一的傳輸 (雙工方式)連接(如HTTP)。長時間運行的Web Service調用或Web Service調用使用單工傳輸方式(如SMTP)不能簡單地利用一個沒有阻塞的調用。
              一種嘗試地解決方法是request和response各自使用單獨的傳輸連接(單工或雙工均可)。這種方式產生的問題是如何解決相關性(關聯 request和response)。WS-Addressing提供了一種很好的解決方法,在頭中使用<wsa:MessageID> 和 <wsa:RelatesTo> 標簽。Axis2對這種基于關聯機制的尋址方式提供了支持。
              用戶可以選擇Blocking 或Non-Blocking APIs的Web Service,并使用兩個傳輸連接。通過使用一個布爾標記,同一個API可以調用多個在兩個傳輸連接上的Web Services(IN-OUT operations)。下例使用Non-Blocking API 以及兩個傳輸連接來實現上文中提到的"echo" operation。
          EchoNonBlockingDualClient.java
          package userguide.clients;
          import org.apache.axiom.om.OMElement;
          import org.apache.axis2.AxisFault;
          import org.apache.axis2.Constants;
          import org.apache.axis2.addressing.EndpointReference;
          import org.apache.axis2.client.Options;
          import org.apache.axis2.client.ServiceClient;
          import org.apache.axis2.client.async.AsyncResult;
          import org.apache.axis2.client.async.Callback;
          import javax.xml.namespace.QName;
          /**
           * Sample for asynchronous dual channel non-blocking service invocation.
           * Message Exchage Pattern IN-OUT
           * Ulitmate asynchronous service invocation sample.
           */
          public class EchoNonBlockingDualClient {
          private static EndpointReference targetEPR =
           new EndpointReference("
          http://127.0.0.1:8080/axis2/services/MyService");
              public static void main(String[] args) {
                  ServiceClient sender = null;
                  try {
                      OMElement payload = ClientUtil.getEchoOMElement();
                      Options options = new Options();
                      options.setTo(targetEPR);
                      options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
                   
             options.setUseSeparateListener(true);
                      options.setAction("urn:echo");  // this is the action mapping we put within the service.xml
                      //Callback to handle the response
                      Callback callback = new Callback() {
                          public void onComplete(AsyncResult result) {
                              System.out.println(result.getResponseEnvelope());
                          }
                          public void onError(Exception e) {
                              e.printStackTrace();
                          }
                      };
                      //Non-Blocking Invocation
                     ConfigurationContext sysContext = ConfigurationContextFactory
                      .createConfigurationContextFromFileSystem(
                       "D:\\Dvp\\Axis2\\axis2\\WEB-INF", null);//見注解①
                      sender = new ServiceClient(sysContext, null);
                      sender.engageModule(new QName(Constants.MODULE_ADDRESSING));
                      sender.setOptions(options);
                      sender.sendReceiveNonBlocking(payload, callback);
                      //Wait till the callback receives the response.
                      while (!callback.isComplete()) {
                          Thread.sleep(1000);
                      }
                      //Need to close the Client Side Listener.
                  } catch (AxisFault axisFault) {
                      axisFault.printStackTrace();
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  } finally {
                      try {
                        
            sender.finalizeInvoke();
                      } catch (AxisFault axisFault) {
                          //have to ignore this
                      }
                  }
              }
          }
          注解①
          RE: [Axis2] 0.95 WS-Addressing web SERVICE-SIDE: module not found
              I now have managed to get EchoNonBlockingDualClient working. I still can't get the original code to work, where ever I put addressing-0.95.mar, but the ConfigurationContext works.
              The code I ended up with was:
           ConfigurationContext sysContext = ConfigurationContextFactory
                     .createConfigurationContextFromFileSystem(
                      "C:\\axis2", null);
            sender = new ServiceClient(sysContext, null);
              with no need, obviously, for the .engageModule method.
              I did discover though that the directory which the ConfigurationContext points to has to have two directories within it: "conf", which must contain the axis.xml configuration file, and the "modules" directory which contains addressing-0.95.mar.
              在方法"options.setUseSeparateListener(...)"中的布爾標記通知通知Axis2引擎使用兩個不同的傳輸連接來分別處 理request和response。Finally中的 "serviceClient.finalizeInvoke()"方法通知Axis2引擎停用客戶端的用于接收response的listener。
              在我們運行客戶端的例程之前,我們還有一件事情要做。如前面提到的,Axis2使用基于地址的關聯機制,因此我們必須在服務器端和客戶端“搭建”尋址模塊。

          結果:
          <?xml version='1.0' encoding='utf-8'?>
          <soapenv:Envelope xmlns:soapenv="
          http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
          <soapenv:Header>
          <wsa:To>http://59.14.131.187:6060/axis2/services/__ANONYMOUS_SERVICE__/__OPERATION_OUT_IN__
          </wsa:To>
          <wsa:ReplyTo>
          <wsa:Address>
          http://www.w3.org/2005/08/addressing/anonymous
          </wsa:Address>
          </wsa:ReplyTo>
          <wsa:From>
          <wsa:Address>
          http://127.0.0.1:8080/axis2/services/MyService
          </wsa:Address>
          </wsa:From>
          <wsa:FaultTo>
          <wsa:Address>
          http://127.0.0.1:8080/axis2/services/MyService
          </wsa:Address>
          </wsa:FaultTo>
          <wsa:MessageID>
          urn:uuid:B087CBB98F1B51A24711742241136206
          </wsa:MessageID>
          <wsa:Action>urn:echo</wsa:Action>
          <wsa:RelatesTo wsa:RelationshipType="wsa:Reply">
          urn:uuid:CA4B9513377E6E9E1511742241130391
          </wsa:RelatesTo>
          </soapenv:Header>
          <soapenv:Body>
          <example1:echo xmlns:example1="
          http://example1.org/example1" xmlns:tns="http://ws.apache.org/axis2">
          <example1:Text>
          Axis2 Echo String
          </example1:Text>
          </example1:echo>
          </soapenv:Body>
          </soapenv:Envelope>
          [SimpleHTTPServer] Stop called
           
          2.6 實現服務器端的尋址
              根據Axis2的結構,尋址模塊在"pre-dispatch"階段已經給出它的句柄。因此,所謂的“搭建”僅僅是在”axis2.xml”(注意不是 services.xml)增加一個模塊的引用?,F在將下面這行字加入到axis2.xml,該文件在"/webapps/axis2/WEB- INF/conf"目錄下。
          <module ref="addressing"/>
          注: 一旦你改變了axis2.xml,你必須重啟這個servlet容器,改變才能生效。
           
          2.7 實現客戶端的尋址
              有兩種方式。
              一種方法是在%Axis2_HOME%\axis2-std-1.0-bin\modules目錄下得到addressing-< version>.mar。并且在你的classpath中對其可見。(此種方法目前,我還沒有調試成功,具體見注解①。下面的第二種方法可用)
              另一種方法是創建一個ConfigurationContext,指定一個repository位置。Axis2支持repository的方式來保存服務和模塊。
              你可以使用二進制distribution作為repository,只要它含有一個Axis2 repository認可的repository結構(其中應包含services和modules目錄)。ConfigurationContext 中含有Axis2體系的運行時的上下文信息。
              如果你解壓一個標準的二進制distribution到目錄(譬如)$user_home/axis2/dist, 那么在 sender = new ServiceClient();之前加入(具體見EchoNonBlockingDualClient.java):
          new ServiceClient();之前加入(具體見EchoNonBlockingDualClient.java):
          ConfigurationContext configContext =
          ConfigurationContextFactory.createConfigurationContextFromFileSystem(< Axis2RepositoryLocation >, null);
              用"sender = new ServiceClient(configContext, null);" 替換 "sender = new ServiceClient();"
          這樣可以在客戶端和服務器端都實現尋址。
           
          2.8 EchoBlockingDualClient
              這又是一個兩路的傳輸的request/response客戶端,但這次,我們使用一個Blocking API。實現機制和EchoNonBlockingDualClient差不多,唯一的不同是,這里不需要使用一個callback對象來處理 response。
          EchoBlockingDualClient.java
          package userguide.clients;
          import org.apache.axiom.om.OMElement;
          import org.apache.axis2.AxisFault;
          import org.apache.axis2.Constants;
          import org.apache.axis2.addressing.EndpointReference;
          import org.apache.axis2.client.Options;
          import org.apache.axis2.client.ServiceClient;
          import javax.xml.namespace.QName;
          import javax.xml.stream.XMLOutputFactory;
          import java.io.StringWriter;
          /**
           * Sample for synchronous dual channel blocking service invocation.
           * Message Exchage Pattern IN-OUT
           */
          public class EchoBlockingDualClient {
          private static EndpointReference targetEPR =
           new EndpointReference("
          http://127.0.0.1:8080/axis2/services/MyService");
              public static void main(String[] args) {
                  ServiceClient sender = null;
                  try {
                      OMElement payload = ClientUtil.getEchoOMElement();
                      Options options = new Options();
                      options.setTo(targetEPR);
                      options.setAction("urn:echo");
                      //The boolean flag informs the axis2 engine to use two separate transport connection
                      //to retrieve the response.
                      options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
                      options.setUseSeparateListener(true);
                      //Blocking Invocation
                      ConfigurationContext sysContext = ConfigurationContextFactory
                      .createConfigurationContextFromFileSystem(
                       "D:\\Dvp\\Axis2\\axis2\\WEB-INF", null);
                      sender = new ServiceClient(sysContext, null);
                      sender.engageModule(new QName(Constants.MODULE_ADDRESSING));
                      sender.setOptions(options);
                      OMElement result = sender.sendReceive(payload);
                      StringWriter writer = new StringWriter();
                     result.serialize(XMLOutputFactory.newInstance().createXMLStreamWriter(writer));
                      writer.flush();
                      System.out.println(writer.toString());
                      //Need to close the Client Side Listener.
                  } catch (AxisFault axisFault) {
                      axisFault.printStackTrace();
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  } finally{
                      try {
                          sender.finalizeInvoke();
                      } catch (AxisFault axisFault) {
                          //
                      }
                  }
              }
          }
          結果:
          <example1:echo xmlns:example1="
          http://example1.org/example1" xmlns:tns="http://ws.apache.org/axis2">
          <example1:Text>Axis2 Echo String </example1:Text>
          </example1:echo>
          [SimpleHTTPServer] Stop called
          posted on 2008-07-11 12:26 禮物 閱讀(1371) 評論(0)  編輯  收藏 所屬分類: web service 、Axis
          主站蜘蛛池模板: 远安县| 青河县| 清流县| 枞阳县| 遵化市| 甘德县| 阳泉市| 延长县| 花垣县| 贡觉县| 新乡市| 武邑县| 浦东新区| 连城县| 平凉市| 建宁县| 沅陵县| 永仁县| 昌乐县| 阿拉善左旗| 平遥县| 吐鲁番市| 堆龙德庆县| 陈巴尔虎旗| 吴川市| 双城市| 天柱县| 大余县| 板桥市| 鹤壁市| 龙泉市| 岳普湖县| 莱阳市| 前郭尔| 万盛区| 微博| 翁源县| 安国市| 杭州市| 千阳县| 三台县|