2010/07/30

[C#] 在 .Net 程式中呼叫 Java 的 Web Service

先前測過 Java 中呼叫 .Net 的 Web Service (here), 現在反過來, 在.Net 中呼叫 Java 的 Web Service.
環境說明:
  • Java 開發工具: Netbeans 6.5.1
  • Java Web Server: Tomcat 6.0.18
  • Java Web Service 套件: JAX-WS 2.1
  1. 在 Tomcat 中建立 Java 的 Web Service: Netbeans 的 Web Service 設定可以參考官網的 說明.
    1. 新增一個名為 MyJavaWsTest 的 Web Application, 並將該專案運作的 Server 指定至 Tomcat. (Server 要指定哪個都沒關係, 只要能運行 Java Web Services)
    2. 如果發現在此專案中無法新增 Web Service, 請至 [Tools] -> [Plugins] -> [Available Plugins], 找尋名稱為 [Web Services] 的套件, 然後安裝它(如下圖).
      安裝Web Services的Plugin
    3. 在專案中新增一個 Web Service, 名稱為 [BasicMathWs], package 訂為 test.ws. (如下圖)
      建立Web Service
    4. 在 Netbeans 中有兩個方式可以新增這個 Web Service 的函式 (工具中叫 Operation). 一個是在 Source 模式下, 到 class 內按滑鼠右鍵 -> 選取 [Web Service] -> [Add Operation]
      接下來會產生一個新增 Operation 的畫面 (如下圖). 這邊我僅簡單地做一個將 a,b 兩陣列元素相加的函式, 參數是兩個 int 陣列, 回傳值也是一個 int 陣列.
      新增Operation
    5. 此 Operation 的程式碼如下:
      @WebMethod(operationName = "addIntList")
      public int[] addIntList(@WebParam(name = "a") int[] a
      , @WebParam(name = "b") int[] b) {
          if (a == null) {//如果a是null -> 回傳b
              return b;
          } else if (b == null) {//如果b是null -> 回傳a
              return a;
          }
          //初始化回傳的陣列
          int[] aryResult = new int[(a.length>b.length) ? a.length : b.length];
          if (a.length > b.length) {
              //如果a陣列長度大於b陣列長度 -> 多餘的設定a陣列值
              for (int i = 0; i < a.length; i++) {
                  aryResult[i] = (i < b.length) ? a[i] + b[i] : a[i];
              }
          } else {
              //如果b陣列長度大於a陣列長度 -> 多餘的設定b陣列值
              for (int i = 0; i < b.length; i++) {
                  aryResult[i] = (i < a.length) ? a[i] + b[i] : b[i];
              }
          }
          return aryResult;
      }
    6. Web Service 設計完成後, 可以透過 Netbeans 的 Deploy 功能, 將程式佈署到 Tomcat.
  2. 新增一個 C# 的主控台應用程式專案 (JavaWsClientConsole_CSharp):
    1. 如果專案的 Framework 是 2.0, 會有 [加入Web服務參考] 的項目; 若是 Framework3.5, 會有 [加入服務參考] 的項目.
      我是用 Framework3.5, 所以新增服務參考的畫面如下: (命名空間定為 MyJavaWs)
      新增服務參考
    2. 在呼叫這個 Web Service 的時候, 應該有人會發現輸入和輸出的參數都多了問號 (?). 如下圖:
      呼叫Web Service的函式(C#)
    3. 在 C# 中, 可以參考 此網頁 (這是 C# 的 Nullable 說明). 使用上就是在型別旁邊加一個問號 (?), 之後這個變數就可設定為 null.
      測試的程式碼如下:
      BasicMathWsClient wsClient = new BasicMathWsClient();
      int?[] a = new int?[] { 1, 2, 3, 4, 5 };
      int?[] b = new int?[] { 1, 2, 3, 4 };
      int?[] c = wsClient.addIntList(a, b);
      for (int i = 0; i < c.Length; i++)
      {
          Console.WriteLine(c[i]);
      }
  3. 以 VB.Net 做相同的測試, 新增一個名為 JavaWsClientConsole_VB 的專案.
    1. 新增服務參考的方式與 C# 的專案做法一樣.
    2. 呼叫相同的 Web Service 函式, 一樣會出現 Nullable 的宣告. (如下圖)
      呼叫Web Service的函式(VB)
    3. VB 在 Nullable 這方面的說明, 可以參考 這個網頁 的說明. 相關程式如下:
      Dim wsClient As New BasicMathWsClient
      Dim a As Integer?() = {1, 2, 3, 4, 5}
      Dim b As Integer?() = {1, 2, 3, 4}
      Dim c As Integer?() = wsClient.addIntList(a, b)
      For i As Integer = 0 To c.Length - 1
          Console.WriteLine(c(i))
      Next
    4. 也可以宣告 Nullable:
      Dim wsClient As New BasicMathWsClient
      Dim a() = New Nullable(Of Integer)() {1, 2, 3, 4, 5}
      Dim b() = New Nullable(Of Integer)() {1, 2, 3, 4}
      Dim c() As Nullable(Of Integer) = wsClient.addIntList(a, b)
      For i As Integer = 0 To c.Length - 1
          Console.WriteLine(c(i))
      Next
Java 的 Web Service, 對於 java.util.ArrayList, java.util.Vector, java.util.Stack 這類 List 的類別, 在 .Net 這邊都會轉型為 object[]; 不過 HashMap 這類的資料結構就會有問題.
所以建議, 如果 Java 所撰寫的 Web Services, 有可能會被其他語言呼叫的話, 請盡可能的採用基本型別, 例如: int, string 等, 以避免增加 Web Service Client 的設計.

沒有留言: