2012-12-14 105 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/