douqun1977
2012-12-14 13:12
浏览 74
已采纳

使用SOAP Webservice - Java VS PHP

a general question:

We are launching a new ITSM Toolsuite in our company called ServiceNow. ServiceNow offers a lot of nice out-of-the-box Webservices. Currenty we are implementing some interfaces to other interal systems and we use these Webservices to consume data of Servicenow.

How we did it in 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
?>

And thats it! 5 minutes of work, Beautiful and simple - from my point of view.

Ok and now the same in Java:

I did some research and it seems everbody is using Apache Axis2 for consuming Webservices in Java. So I decided to go down that road.

  1. Install Apache Axis
  2. open cygwin or cmd and generate Classes from WSDL.. WTF? what for?

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

  3. copy generated classes to Java Project in Eclipse.

  4. Use this classes:
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
}

Its working but I think this way is very complicated.. everytime something in the wsdl changes - i must recompile them with axis. There is no way to configure something globally like Soap-endpoint or something like that.

Is there an easier way in Java to consume SOAP with a WSDL??

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • douci1615 2012-12-20 08:23
    已采纳

    First off: I completely agree. I do quite a bit of work with Web Services and ServiceNow, and using Java and/Or .Net is quite different than using a scripted language (I usually use Perl for scripts). The inherent issue comes into the fact that a WSDL should not be changing that often, especially in production. The idea in Java and .Net is that you get these stub classes to get compile time error checking.

    If your currently in a Ph1 and haven't deployed Prod yet, then you should really look into how often that WSDL will be changing. Then make your decision from there on which technology to use. The nice thing is that even if the WSDL changes, posting data to the instance - almost all of the fields are optional. So if a new field is added it's not a big deal. The issue comes in when data is returned (most of the time) because many times java and .net will throw an exception if the returned XML is not in the structure it is expecting.

    One thing that many people do is setup Modules as CI's in the CMDB and maintain their ServiceNow instance through the Change Request module. That way your java application will be a downstream CI to whatever module/table you are querying, and when a CR is put in to modify that table, it will be known immediately that there will be an impact on your internal application as well.

    Unfortunately you are right though, that is a trade off with the different languages and from my experience there is very little we can do to change that.

    One thing I forgot to add, another option for you is to use the JSON service instead. That will allow you to make raw requests to the SNC instance then use a JSON parser to parse that data for you "on the fly" so to speak. It takes away the compile time checking but also takes away many of the flaws of the SOAP system.

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • doujin8476 2012-12-14 13:38

    IF you are using maven, try using this plugin.

    <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>
    
    评论
    解决 无用
    打赏 举报
  • douqi3195 2012-12-15 17:55

    I consume lots of Soap services with PHP in the company I work for, and I would always suggest generating classes for the request and response data structure. Otherwise you will easily get lost - PHP does not preserve any remains of the original XML structure, it will all be converted to arrays and stdClass objects.

    Getting classes created from the WSDL description is not that easy in PHP, as there are only a few scripts that do this - and they all have their shortcomings when it comes to WSDL files that make use of the more obscure parts of the SOAP standard. After that, you somehow have to make these classes available to your PHP script. If this is hard for you, it is a sign of a not too well organized code base. With the autoloading feature it works like a charm.

    But yes, this step is entirely optional for PHP. If using only one Soap service, it'll probably make no difference.

    评论
    解决 无用
    打赏 举报
  • douweilei2307 2013-05-13 21:21

    I was also trying to access ServiceNow from Java using Eclipse, and it seemed to me that the Axis2 approach was overly restrictive given how ServiceNow designed their API, so I wrote my own package to generate SOAP calls dynamically using JDOM. Here is an example of what the code looks like:

    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"));
    }           
    

    A couple of things about this code:

    1. I use run-time validation rather than build-time validation. If you mistakenly type getField("shortdescription") the code throws an InvalidFieldNameException.
    2. Queries are not bound by ServiceNow's normal 250 record limit because the BulkFetcher loops internally making as many Web Service calls as necessary to retrieve all the data.

    The package source code is at https://sourceforge.net/projects/servicenowpump/

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题