一般性问题:
我们正在我们公司推出名为ServiceNow的新ITSM Toolsuite。 ServiceNow提供了许多开箱即用的Web服务。 目前我们正在为其他内部系统实现一些接口,我们使用这些Web服务来使用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服务。所以我决定走那条路。
打开cygwin或cmd并从WSDL生成类.. WTF?为什么?
$ ./wsdl2java.sh -uri https://blah.com/incident.do?WSDL
将生成的类复制到Eclipse中的Java Project。
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 :(得分: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系统的许多缺陷。
答案 1 :(得分: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>
答案 2 :(得分:1)
我也试图使用Eclipse从Java访问ServiceNow,在我看来,鉴于ServiceNow如何设计他们的API,Axis2方法过于严格,所以我编写了自己的包来使用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"));
}
关于此代码的一些事项:
答案 3 :(得分:0)
我在我工作的公司中使用PHP消耗了大量的Soap服务,我总是建议为请求和响应数据结构生成类。否则你很容易迷失 - PHP不保留原始XML结构的任何遗留物,它将全部转换为数组和stdClass对象。
在PHP中获取从WSDL描述创建的类并不是那么容易,因为只有少数脚本可以做到这一点 - 当涉及到使用更隐蔽部分的WSDL文件时,它们都有它们的缺点。 SOAP标准。之后,您必须以某种方式使这些类可用于您的PHP脚本。如果这对你来说很难,那就表明代码库组织得不太好。凭借自动加载功能,它就像一个魅力。
但是,这一步对于PHP来说完全是可选的。如果只使用一个Soap服务,它可能没什么区别。