2012-12-14 104 views
2

一般問題:消費SOAP Web服務 - Java VS PHP

我們正在我們公司推出一個名爲ServiceNow的新ITSM Toolsuite。 ServiceNow提供了很多不錯的開箱即用Web服務。 當前我們正在實現一些與其他interal系統的接口,並且我們使用這些Webservices來使用Servicenow的數據。

我們怎麼做的在PHP

<?php 
$credentials = array('login'=>'user', 'password'=>'pass'); 
$client = new SoapClient("https://blah.com/incident.do?WSDL", $credentials); 
$params = array('param1' => 'value1', 'param1' => 'value1'); 
$result = $client->__soapCall('getRecords', array('parameters' => $params)); 
// result array stored in $result->getRecordsResult 
?> 

而這就是它! 5分鐘的工作,美麗而簡單 - 從我的角度來看。

好了,現在在的Java相同:

我做了一些研究,似乎感到沉淪在使用Apache Axis2的在Java Web服務消費。所以我決定走下去。

  1. 安裝Apache Axis
  2. 開放的cygwin或cmd並從WSDL生成類..跆拳道?做什麼的?

    $ ./wsdl2java.sh -uri https://blah.com/incident.do?WSDL

  3. 複製生成的類Java項目在Eclipse。

  4. 使用此類:
ServiceNow_incidentStub proxy = new ServiceNow_incidentStub(); 

proxy._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, Boolean.FALSE); 
ServiceNow_incidentStub.GetRecords defectsGetRecords = new ServiceNow_incidentStub.GetRecords(); 
ServiceNow_incidentStub.GetRecordsResponse defectsResult = new ServiceNow_incidentStub.GetRecordsResponse(); 
proxy._getServiceClient().getOptions().setManageSession(true); 
HttpTransportProperties.Authenticator basicAuthentication = new HttpTransportProperties.Authenticator(); 
basicAuthentication.setUsername("user"); 
basicAuthentication.setPassword("pass"); 
proxy._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, basicAuthentication); 
defectsResult = proxy.getRecords(defectsGetRecords); 
com.service_now.www.ServiceNow_incidentStub.GetRecordsResult_type0[] defects = defectsResult.getGetRecordsResult(); 

for (int j=0; j < defects.length; j++) { 
    // do something 
} 

它的工作,但我認爲這種方式是非常複雜的.. 每次的東西在WSDL的變化 - 我必須和軸重新編譯。 沒有辦法像Soap-endpoint或類似的東西配置全局的東西。

有沒有一種更簡單的方法在Java中使用WSDL來使用SOAP?

+0

我喜歡Netbeans的網絡服務嚮導,(它這個最適合你),但我真的沒有廣泛使用它們。 – madth3

+0

@felixsigl希望你在這個時候爲你的問題找到了解決方案。你能分享一下嗎? 因爲我也遇到了同樣的問題,我發現Json Service作爲替代解決方案。但是我在連接到ServiceNow時遇到了一些問題。如果你有一些代碼片段,這將是有幫助的。 –

回答

2

首先:我完全同意。我在Web Services和ServiceNow方面做了很多工作,使用Java和/或.Net與使用腳本語言(我通常使用Perl的腳本)完全不同。固有的問題是WSDL不應該經常改變,特別是在生產環境中。 Java和.Net的想法是,你得到這些存根類來獲得編譯時錯誤檢查。

如果您目前在Ph1中並且尚未部署Prod,那麼您應該真正瞭解WSDL的變化頻率。然後從那裏決定使用哪種技術。好的是,即使WSDL發生變化,將數據發佈到實例 - 幾乎所有的字段都是可選的。所以如果添加一個新的字段,這不是什麼大問題。問題出現在數據返回時(大部分時間),因爲如果返回的XML不在所期望的結構中,那麼java和.net會多次拋出異常。

許多人所做的一件事就是將模塊設置爲CMDB中的CI,並通過Change Request模塊維護其ServiceNow實例。這樣,您的Java應用程序將成爲您查詢的任何模塊/表的下游CI,並且當放入CR來修改該表時,它會立即知道您的內部應用程序也會受到影響。

不幸的是,你是對的,這是與不同語言的權衡,從我的經驗來看,我們很難做出改變。

我忘了添加一件事,另一個選擇是使用JSON服務。這將允許您向SNC實例發出原始請求,然後使用JSON解析器爲您「即時」分析這些數據。它消除了編譯時檢查,但也消除了SOAP系統的許多缺陷。

+0

嗨,我遇到了同樣的問題,我發現Json Service作爲替代解決方案。但是,如果你有,可以提供一些示例代碼片段嗎? –

1

如果您使用的是maven,請嘗試使用此插件。

<plugin> 
    <groupId>org.codehaus.mojo</groupId> 
    <artifactId>axistools-maven-plugin</artifactId> 
    <version>1.4</version> 
    <configuration> 
     <urls> 
       <url>https://blah.com/incident.do?WSDL</url> 
      </urls> 
       <packageSpace>your.destination.package</packageSpace> 
       <serverSide>true</serverSide> 
       <outputDirectory>src/main/java</outputDirectory> 
    </configuration> 
    <executions> 
     <execution> 
      <goals><goal>wsdl2java</goal></goals> 
     </execution> 
    </executions> 
</plugin> 
0

我在我工作的公司使用PHP大量使用Soap服務,而且我總是建議爲請求和響應數據結構生成類。否則,您將很容易迷路--PHP不保留原始XML結構的任何遺留物,它將全部轉換爲數組和stdClass對象。

從WSDL描述中獲取創建的類在PHP中並不是那麼容易,因爲只有幾個腳本可以做到這一點 - 而且它們都有它們的缺點,當涉及到WSDL文件時,它們利用了更加模糊的部分SOAP標準。之後,你不知何故必須讓這些類可用於你的PHP腳本。如果這對你來說很難,這是一個組織不太好的代碼庫的標誌。藉助自動加載功能,它就像魅力一樣。

但是,這一步對PHP完全是可選的。如果只使用一個Soap服務,它可能沒有區別。

1

我還試圖從Eclipse使用Eclipse訪問ServiceNow,在我看來Axis2方法過分限制了ServiceNow設計API的方式,所以我編寫了自己的包來動態使用JDOM生成SOAP調用。這是什麼樣的代碼看起來像一個例子:

Instance instance = new Instance("https://blah.service-now.com", "username", "password"); 
GlideFilter filter = new GlideFilter("category=network^active=true");   
GlideRecordIterator iter = instance.table("incident"). 
    bulkFetcher().setFilter(filter).getAllRecords().iterator(); 
while (iter.hasNext()) { 
    GlideRecord rec = iter.next(); 
    System.out.println(
     rec.getField("number") + " " + rec.getField("short_description")); 
}   

幾個關於這個代碼的東西:

  1. 我使用運行時確認,而不是構建時驗證。如果您錯誤地鍵入getField(「shortdescription」),則代碼將引發InvalidFieldNameException。
  2. 查詢不受ServiceNow正常的250條記錄限制的約束,因爲BulkFetcher在內部根據需要循環執行儘可能多的Web Service調用以檢索所有數據。

包源代碼是https://sourceforge.net/projects/servicenowpump/