【问题标题】:Consuming SOAP Webservice - Java VS PHP使用 SOAP Web 服务 - Java VS PHP
【发布时间】:2012-12-14 13:12:12
【问题描述】:

一般问题:

我们正在我们公司推出一个名为 ServiceNow 的新 ITSM 工具套件。 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 服务。所以我决定走这条路。

  1. 安装 Apache Axis
  2. 打开 cygwin 或 cmd 并从 WSDL 生成类.. WTF?干什么用的?

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

  3. 将生成的类复制到 Eclipse 中的 Java 项目中。

  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??

【问题讨论】:

  • 我喜欢 Netbeans Web 服务向导,(它为您完成了大部分工作)但我真的没有广泛使用它们。
  • @felixsigl 希望你在这个时候找到了解决问题的方法。你能分享一下吗?因为我也遇到了同样的问题,我发现 Json Service 作为替代解决方案。但是我在连接到 ServiceNow 时遇到了一些问题。如果你有一些代码sn-ps,那会很有帮助。

标签: java php web-services soap servicenow


【解决方案1】:

首先:我完全同意。我在 Web 服务和 ServiceNow 方面做了很多工作,使用 Java 和/或 .Net 与使用脚本语言有很大不同(我通常使用 Perl 编写脚本)。固有的问题在于 WSDL 不应该经常更改,尤其是在生产中。 Java 和 .Net 中的想法是让这些存根类进行编译时错误检查。

如果您目前处于 Ph1 并且尚未部署 Prod,那么您应该真正了解 WSDL 的更改频率。然后从那里决定使用哪种技术。好消息是,即使 WSDL 发生更改,将数据发布到实例 - 几乎所有字段都是可选的。因此,如果添加一个新字段,这没什么大不了的。当返回数据时(大部分时间)会出现问题,因为如果返回的 XML 不在其预期的结构中,java 和 .net 会多次抛出异常。

许多人做的一件事是将模块设置为 CMDB 中的 CI,并通过更改请求模块维护他们的 ServiceNow 实例。这样,您的 java 应用程序将成为您正在查询的任何模块/表的下游 CI,并且当放入 CR 以修改该表时,将立即知道这也会对您的内部应用程序产生影响。

不幸的是,您是对的,这是对不同语言的权衡,根据我的经验,我们几乎无法改变这一点。

我忘了添加一件事,您的另一种选择是改用 JSON 服务。这将允许您向 SNC 实例发出原始请求,然后使用 JSON 解析器“即时”为您解析该数据,可以这么说。它消除了编译时检查,但也消除了 SOAP 系统的许多缺陷。

【讨论】:

  • 嗨,我遇到了同样的问题,我发现 Json Service 作为替代解决方案。但是如果你有,你能提供一些示例代码 sn-ps 吗?
【解决方案2】:

如果您使用的是 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>

【讨论】:

    【解决方案3】:

    我还尝试使用 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"));
    }           
    

    关于这段代码的几点说明:

    1. 我使用运行时验证而不是构建时验证。如果您错误地键入 getField("shortdescription"),则代码将引发 InvalidFieldNameException。
    2. 查询不受 ServiceNow 正常的 250 条记录限制的约束,因为 BulkFetcher 在内部循环,根据需要进行尽可能多的 Web 服务调用以检索所有数据。

    包源代码在https://sourceforge.net/projects/servicenowpump/

    【讨论】:

      【解决方案4】:

      我在我工作的公司中使用 PHP 使用了大量的 Soap 服务,我总是建议为请求和响应数据结构生成类。否则你很容易迷路——PHP 不会保留原始 XML 结构的任何残留物,它将全部转换为数组和 stdClass 对象。

      在 PHP 中获取从 WSDL 描述创建的类并不是那么容易,因为只有少数脚本可以做到这一点 - 当涉及到使用SOAP 标准。之后,您必须以某种方式使这些类可用于您的 PHP 脚本。如果这对您来说很难,则表明代码库组织得不太好。使用自动加载功能,它就像一个魅力。

      但是是的,这一步对于 PHP 来说是完全可选的。如果只使用一种 Soap 服务,那可能没什么区别。

      【讨论】:

        猜你喜欢
        • 2019-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多