Create And Consume SOAP Web Services Using WSDL

NuSOAP is a group of PHP classes that allow developers to create and consume SOAP web services. It does not require any special PHP extensions. The current release version (0.6.7) of NuSOAP at the time this was written (03-November-2004), supports much of the SOAP 1.1 specification. It can generate WSDL 1.1 and also consume it for use in serialization. Both rpc/encoded and document/literal services are supported. However, it must be noted that NuSOAP does not provide coverage of the SOAP 1.1 and WSDL 1.1 that is as complete as some other implementations, such as .NET and Apache Axis.

This document follows up Introduction to NuSOAP, Programming with NuSOAP, and Programming with NuSOAP Part 2 with additional samples that demonstrate how to use NuSOAP to create and consume SOAP web services using WSDL.

Hello, World Redux

Showing no imagination whatsoever, I used the ubiquitous “Hello, World” example in Introduction to NuSOAP. In that document, I showed the SOAP request and response exchanged by the client and server. Here, I extend that sample to use WSDL.

A WSDL document provides metadata for a service. NuSOAP allows a programmer to specify the WSDL to be generated for the service programmatically using additional fields and methods of the soap_server class.

The service code must do a number of things in order for correct WSDL to be generated. Information about the service is specified by calling the configureWSDL method. Information about each method is specified by supplying additional parameters to the register method. Service code for using WSDL is shown in the following example.

<?php
// Pull in the NuSOAP code
require_once('nusoap.php');
// Create the server instance
$server = new soap_server();
// Initialize WSDL support
$server->configureWSDL('hellowsdl', 'urn:hellowsdl');
// Register the method to expose
$server->register('hello',                // method name
    array('name' => 'xsd:string'),        // input parameters
    array('return' => 'xsd:string'),      // output parameters
    'urn:hellowsdl',                      // namespace
    'urn:hellowsdl#hello',                // soapaction
    'rpc',                                // style
    'encoded',                            // use
    'Says hello to the caller'            // documentation
);
// Define the method as a PHP function
function hello($name) {
        return 'Hello, ' . $name;
}
// Use the request to (try to) invoke the service
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

Now for some magic. Point a Web browser at this service, which in my environment is at http://localhost/phphack/hellowsdl.php. The HTML that is returned to your browser gives you links to view the WSDL for the service or view information about each method, in this case the hello method. The screen should look something like this.

The Basics Of Working With Web Services

ADF to fully exploit the use of Web services for communicating with ArcGIS Server services. Directly as a developer with the ADF and ArcGIS Server, it is important to understand the use of SOAP and its relationship with the WSDL file with ArcGIS. This article describes some of the basics of working with Web Services, SOAP and WSDL with ArcGIS Server. After this article you must read some documents that explain how the ideas discussed here apply in relation to a specific ADF.


Web services applications can communicate via messages from different protocols. Because Web services means for communication between applications in the program itself is written in a programming language, is language-independent communications. XML is the format used to maintain present information about applications. XML messaging via SOAP (Simple Object Access Protocol). SOAP defines a header and a valid means of message exchange. This exchange of messages is usually via HTTP, but actually a protocol such as SMTP, FTP, or DCOM, to be known. SOAP, XML, and wrap the message so that the applications received and processed they can be transferred appropriaptely.

 

WSDL, but also explains what Web services do not, what methods it has, what parameters and the guy who knows how you and the port used for communication. WSDL defines the valid content of XML SOAP messages are transmitted. WSDL is a specification, such as IDL, interfaces and parameters to describe the Web. The available methods are usually together in “port”, which can be viewed as a Web destination for the various activities they are interested in groups. A WSDL may contain one or more ports. Has the WSDLs provided by ESRI, a single interface for WSDL. For example, all methods show the MapServer WSDL recorded as part MapServerPort. Another feature of the Web service described in WSDL that specifies a protocol for sending messages, and optionally the URL of the corresponding server. WSDL specification does all this work in a very general, so that the toolkit in various languages, such as the Axis in Java, to generate code from WSDL descriptions.

 

WSDLs and ArcGIS Server
If you are in the installation directory under the XmlSchema found eight WSDL file. Each fits the description of the ArcGIS Server Web service can publish. Each WSDL corresponds roughly with the ArcObjects classes, for example, corresponds to the object MapServer.wsdl MapServer and GeoDataServer.wsdl GeoDataServer consistent with the object. Because Web services are usually only text messages (XML) to send between applications, there are differences in method signatures and data types from WSDL and ArcObjects. If you are open GeocodeServer.wsdl there are two major stages, you need to understand. The first part is <types> element and the second part is an element PortType.

 

Value of the items
<types> All the elements that defines the data type for WSDL, and valuables. This section contains definitions for all elements that are used as parameters to a web service method to pass. Object value can consist of objects of value, but at the end of the “end” must be a valid data type schema type such as String, int length or XML data. When a Java toolkit for the sale of all classes of the Java-like element in the WSDL Java objects of value, as the old Java objects (POJOs). For example, if you look at the point in the WSDL Look, this is an XML representation of a point sufficient to ArcObjects Web service operation:

 

<xs:complexType name=”PointN”>
<xs:complexContent>
<xs:extension base=”Point”>
<xs:sequence>
<xs:element name=”X” type=”xs:double”/>
<xs:element name=”Y” type=”xs:double”/>
<xs:element name=”M” type=”xs:double” minOccurs=”0″/>
<xs:element name=”Z” type=”xs:double” minOccurs=”0″/>
<xs:element name=”ID” type=”xs:int” minOccurs=”0″/>
<xs:element name=”SpatialReference” type=”SpatialReference” minOccurs=”0″/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>

 

The Javadoc for the class generated using the AXIS toolkit, shows a Java class which is very similar to a POJO. From the WSDL definition we can see that M, Z, ID, and SpatialReference are not required properties since their minOccurs attribute is equal to 0. Therefore when you need to use a PointN value object you can create it using the default construct, set the X and Y, and then pass it as a parameter. There is no need to create the object on the Server Context, it is created on the local machine. When you are setting the object’s properties since they are set locally no remote call is made to the ArcGIS serverl.

Port Usage

Inside the <portType> element is the listing of all the methods that can be called on the web service. For example, one of the calls you can make is ReverseGeocode, which takes a point and figures out the closest address.

<operation name=”ReverseGeocode”>
<input message=”e:ReverseGeocodeIn”/>
<output message=”e:ReverseGeocodeOut”/>
</operation>

There is a definition for the input message (the input parameters) and the output message (the returned values) in another section of the WSDL. In this case they are defined earlier in the file as <message> elements, which are then mapped to <types>. Through this mapping you can see that a ReverseGeocode input message contains a location, which is a point, a boolean to indicate if intersections should be returned, and some properties in a PropertySet

<xs:element name=”ReverseGeocode”>
<xs:complexType>
<xs:sequence>
<xs:element name=”Location” type=”Point”/>
<xs:element name=”ReturnIntersection” type=”xs:boolean”/>
<xs:element name=”PropMods” type=”PropertySet”/>
</xs:sequence>
</xs:complexType>
</xs:element>

When the WSDL is used to generate Java proxies through AXIS a class will be generated named GeocodeServerPort which contains all the methods you can call on the ArcGIS Server GeocodeServer object using web services. The GeocodeServerPort object is instantiated in the local JVM but any method call on this class will execute a remote call to the server. Any object returned from the server will be a value object and therefore accessing its properties will not require calls to the server. Therefore, the only methods in the Java classes generated from the WSDL which make remote calls will be those methods exposed on a *Port object.

Implications for ArcGIS Server Developer

Using SOAP has several advantages for ArcGIS Server developers. The greatest advantage is that the value objects are Java objects in the local JVM. Because they reside in the local JVM and they are pure Java they are easier to debug and work with in general. Another serious advantage is that the only remote calls are those on the *Port objects. When using ArcGIS Server with the server API, each call to set a variable or execute a GIS operation is a remote call. Because the value objects are in the local JVM all calls to their mutators are local calls. When you call one of the methods on a *Port object you pass the value object as a parameter. The returned objects are also value objects, so retrieving values from this object are local calls as well. This overall reduction in remote calls greatly increases the performance of your application.

Here is an example which comes from the example below. It uses Value objects and the MapServerPort to query the count of features in a layer in the map. Using the server API every method call, from creating the envelope to the query feature count call would be a remote method call.

// The envelope is a value object so this constructor is not a remote call
EnvelopeN env = new EnvelopeN(webExtent.getMinX(), webExtent.getMinY(), webExtent.getMaxX(), webExtent.getMaxY(),
null, null, null, null, null);
// make a spatialfilter value object with the required parameters – none of these method calls are remote
SpatialFilter spatialFilter = new SpatialFilter();
spatialFilter.setFilterGeometry(env);
spatialFilter.setSpatialRel(EsriSpatialRelEnum.esriSpatialRelIntersects);
spatialFilter.setWhereClause(“”);
spatialFilter.setSearchOrder(EsriSearchOrder.esriSearchOrderSpatial);
spatialFilter.setSpatialRelDescription(“”);
spatialFilter.setGeometryFieldName(“”);

int layerId = layer.getId();
//because queryFeatureCount is found on the MapServerPort the call to queryFeatureCount goes back
//to the server which can throw an RemoteException
try {
numberOfFeatures =  mapServer.queryFeatureCount(mapServer.getDefaultMapName(), layerId, spatialFilter);
} catch (RemoteException e){}

There are also some drawbacks, especially for current ArcGIS Server programmers. Because of the requirements of the WSDL using simple types and the way different toolkits generate default values, some of the generated objects need more properties set before the methods will work. For example, using an Element for custom graphics needs to have its color set when using SOAP but not using the Server API. The implications of this for current ArcGIS Server developers is that your code will not translate directly and that you may have to set more values before the method call.

Now that you have basic understanding of the ArcGIS Server web services, you can go on to reading about how these generated Java proxies are used in the Web ADF and the Enterprise ADF. The Javadoc for the generated Java proxies can be found by themselves or as part of the Javadoc for the Web ADF and the Enterprise ADF

The custom command and tool example shows using the Value objects and Port calls.

Edit Into A SOAP Envelope

An application that depends largely on the work of the SOAP web service asp.net much in the simulator and then hit with a shock that CoreServices library function that does not contain all web services available on the iPhone. I keep hoping that this feature was recently added.

All my code depends on receiving the object NSArray and NSDictionary key, and do not want to edit into a SOAP envelope to create the missing features emulate approval of the request is REST. I can only method used to make web service call and the same code base. I thought I share to all in this together.

Fortunately asp.net and is compatible with the REST style requests (I am not aware of this earlier today), so no changes are needed in the web server.

To demonstrate here the call to a simple method called “SayHello”. You pass in name and it returns a single item called “string” that contains “Hello [yourname]“. The code will work with more complex objects with child properties as well, and return them as NSDictionary and NSArray objects, but for simplicity I’m using “SayHello”.

Code :

NSArray *keys = [NSArray arrayWithObjects:@"userName", nil];
NSArray *objects = [NSArray arrayWithObjects:@"jeremy", nil];
NSDictionary *params = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSDictionary *wsResponse=[WebServices callRestService:@"SayHello" :params];

NSString *responseString=[wsResponse objectForKey:@"string"];

 

callRestService is a helper method I created in a class called Webservices. This code was exactly the same before except the helper method was called callSoapService.

WebServices.m contains two methods. getRestUrl just appends all the method parameters into a url to make the REST request. callRestService uses the build-in NSXMLParser class to retrieve the xml and sends it to a custom class called XmlParser to handle the callbacks and create the NSDictionary result,

WebServices.m

Code:

+(id)callRestService: (NSString *) methodName : (NSDictionary *) params
{
        NSURL *url=[WebServices getRestUrl: methodName : params];
        XmlParser *xmlParser = [[XmlParser alloc] init];

        NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
        [parser setDelegate:xmlParser];
        [parser setShouldProcessNamespaces:NO];
        [parser setShouldReportNamespacePrefixes:NO];
        [parser setShouldResolveExternalEntities:NO];
        [parser parse];
        [parser release];
        return xmlParser.result;
}

+(NSURL *)getRestUrl: (NSString *) methodName : (NSDictionary *) params
{
        NSString *url=@"http://services.mywebsite.com/mywebservice.asmx/";
        url=[url stringByAppendingString:methodName];

        BOOL firstKey=TRUE;
        for (NSString *key in params)
        {
               NSString *value=[params objectForKey:key];
               if (firstKey) url=[url stringByAppendingString:@"?"]; else url=[url stringByAppendingString:@"&"];
               url=[url stringByAppendingString:key];
               url=[url stringByAppendingString:@"="];
               url=[url stringByAppendingString:value];
               firstKey=FALSE;
        }
        return [NSURL URLWithString:url];
}

 

The final step is to create the XmlParser handler. This class keeps track of each open and close tag to build an object tree containing NSMutableArray NSMutableDictionary and NSString objects.

XmlParser.h

Code:

 

#import <Foundation/Foundation.h>


@interface XmlParser : NSObject {
        NSMutableDictionary *result;
        NSString *currentElementName;
        NSString *currentElementValue;
        NSMutableArray *parentArray;
}

@property (nonatomic, retain) NSMutableDictionary *result;
@property (nonatomic, retain) NSString *currentElementName;
@property (nonatomic, retain) NSString *currentElementValue;
@property (nonatomic, retain) NSMutableArray *parentArray;


- (void)parserDidStartDocument:(NSXMLParser *)parser;
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;

@end

XmlParser.m

Code:

#import "XmlParser.h"


@implementation XmlParser
@synthesize result;
@synthesize currentElementName;
@synthesize currentElementValue;
@synthesize parentArray;


- (void)parserDidStartDocument:(NSXMLParser *)parser
{
        result=[[NSMutableDictionary alloc] init];
        parentArray=[[NSMutableArray alloc] init];
        [parentArray addObject:result];
        currentElementName=@"";
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
        if (qName) {
               elementName = qName;
        }
        currentElementValue=@"";
        if (currentElementName!=@"")
        {
               id newParent=NULL;
               if ([currentElementName isLike:@"*Array*"])
               {
                       newParent=[[NSMutableArray alloc] init];
               } else {
                       newParent=[[NSMutableDictionary alloc] init];
               }
               [parentArray addObject:newParent];
        }
        currentElementName=elementName;
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
        if (qName) {
               elementName = qName;
        }

        if (currentElementName==@"")
        {
               //We're adding a container with children.  Add it to the parent and remove this item fromt he parentArray
               int currentIndex=[parentArray count]-1;
               int parentIndex=currentIndex - 1;
               id currentChild=[parentArray objectAtIndex:currentIndex];
               id currentParent=[parentArray objectAtIndex:parentIndex];

               if ([currentParent isKindOfClass:[NSMutableArray class]])
               {
                       [currentParent addObject:currentChild];
               } else {
                       [currentParent setObject:currentChild forKey:elementName];
               }

               [parentArray removeObjectAtIndex:currentIndex];
        } else {
               //We're adding a simple type element
               int currentIndex=[parentArray count]-1;
               id currentParent=[parentArray objectAtIndex:currentIndex];
               if ([currentParent isKindOfClass:[NSMutableArray class]])
               {
                       [currentParent addObject:currentElementValue];
               } else {
                       [currentParent setObject:currentElementValue forKey:currentElementName];
               }
        }
        currentElementName=@"";
}


- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
        currentElementValue=string;
}

@end

 

 

That’s it. I’m sure it’s not the cleanest code (This is my very first XCode app) and there may be a better way of doing this, but it saved me from having to rewrite all my code that was retrieving data from SOAP services. I’ve seen tons of other people with the same problem and no solutions so far.

Test The SOAP Messages

A client needs to develop SOAP web services. I’m involved in web services interface specifications and comply with specifications. JMeter and finally using XPath statements. Should not depend on the test unit “green bar”, but it worked.


The need is to test the SOAP messages that play on the network. At least one of the first customers to publish applications SOAP requests and responses from the XML SOAP service, instead of using SOAP kit. We need to ensure that the Web service interface to behave as expected, and the business logic behind the interface changes have no impact on the customer’s application.

 

Before the actual test in JMeter Google quickly reveals what is suitable for quick and dirty test. Tests can be written with JUnit and unity, but the solution may be in the client’s declaration that the e-mail is preferred. JMeter has a job, but has some problems.

 

The Recipe

  1. Download and install JMeter. (Activation.jar and mail.jar are required for SOAP testing. See installation notes.)
  2. Create a new Test Plan.
  3. Add a Thread Group to the Test Plan. Check that the number of threads is set to 1 and the number of loops is 1.
  4. For each test, add a Web Service (SOAP) Request samplers as a child of the Thread Group. Name them with a numeric identitifier for ease of reference. e.g. “1. Invalid Foo, Valid Bar”. You will need to supply the URL to the WSDL file and a fully formed SOAP request XML document.
  5. For each sampler, add as many XPath Assertions as you need to validate the result. XPath expressions can be used to check pretty much everything about the content and structure of XML documents.
  6. Add a View Results Tree listener to capture and display the requests and responses. Any tests that fail will be shown in red.
  7. Save your Test Plan.
  8. Run it.
  9. View results by clicking on the View Results Tree.
  10. Clear results before running the test again. Results are stored cumulatively, not replaced by each test.

SoapUI Is Useful Tool For Testing Web Services

SoapUI is a useful tool for testing web services. Not only makes it possible to test deployed web services, but it also offers the possibility to mock any “external” service needed by the service you want to test. As a result, you can test your web service independently from any other external service.

The following basic example describes how to test a service that computes the price of a trip (TripPriceService). It invokes one service that returns prices for hotel rooms (HotelPriceService) and one service that returns prices for flights (FlightPriceService).

Formula : price = duration * rooms * getRoomPrice() + adults * getFlightPrice(from, to)

Here are the WSDLs of the three services.

 

TripPriceService.wsdl

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="TripPriceServiceFacadeService"
  targetNamespace="http://trip.price.service" xmlns:ns1="http://cxf.apache.org/bindings/xformat"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://trip.price.service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified"
      targetNamespace="http://trip.price.service" xmlns:tns="http://trip.price.service" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="getTripPrice" type="tns:getTripPrice" />
      <xs:element name="getTripPriceResponse" type="tns:getTripPriceResponse" />
      <xs:complexType name="getTripPrice">
       <xs:sequence>
         <xs:element minOccurs="0" name="trip" type="tns:trip" />
       </xs:sequence>
      </xs:complexType>
      <xs:complexType name="trip">
        <xs:sequence>
          <xs:element name="adults" type="xs:int" />
          <xs:element name="duration" type="xs:int" />
          <xs:element minOccurs="0" name="from" type="xs:string" />
          <xs:element name="rooms" type="xs:int" />
          <xs:element minOccurs="0" name="to" type="xs:string" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="getTripPriceResponse">
        <xs:sequence>
          <xs:element name="return" type="xs:float" />
        </xs:sequence>
      </xs:complexType>
      <xs:element name="TripPriceServiceException" type="tns:TripPriceServiceException" />
      <xs:complexType name="TripPriceServiceException">
        <xs:sequence />
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="TripPriceServiceException">
    <wsdl:part element="tns:TripPriceServiceException" name="TripPriceServiceException">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getTripPrice">
    <wsdl:part element="tns:getTripPrice" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getTripPriceResponse">
    <wsdl:part element="tns:getTripPriceResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="ITripPriceServiceFacade">
    <wsdl:operation name="getTripPrice">
      <wsdl:input message="tns:getTripPrice" name="getTripPrice">
    </wsdl:input>
      <wsdl:output message="tns:getTripPriceResponse" name="getTripPriceResponse">
    </wsdl:output>
      <wsdl:fault message="tns:TripPriceServiceException" name="TripPriceServiceException">
    </wsdl:fault>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="TripPriceServiceFacadeServiceSoapBinding" type="tns:ITripPriceServiceFacade">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getTripPrice">
      <soap:operation soapAction="" style="document" />
      <wsdl:input name="getTripPrice">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getTripPriceResponse">
        <soap:body use="literal" />
      </wsdl:output>
      <wsdl:fault name="TripPriceServiceException">
        <soap:fault name="TripPriceServiceException" use="literal" />
      </wsdl:fault>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="TripPriceServiceFacadeService">
    <wsdl:port binding="tns:TripPriceServiceFacadeServiceSoapBinding" name="TripPriceServiceFacadePort">
      <soap:address location="http://localhost:8080/trip-price-0.0.1-SNAPSHOT/webservices/TripPriceService" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

HotelPriceService.wsdl

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="HotelPriceServiceFacadeService"
  targetNamespace="http://external.services/hotel" xmlns:ns1="http://cxf.apache.org/bindings/xformat"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://external.services/hotel"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <xs:schema elementFormDefault="unqualified" targetNamespace="http://external.services/hotel"
      version="1.0" xmlns:tns="http://external.services/hotel" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="getRoomPrice" type="tns:getRoomPrice" />
      <xs:element name="getRoomPriceResponse" type="tns:getRoomPriceResponse" />
      <xs:complexType name="getRoomPrice">
        <xs:sequence />
      </xs:complexType>
      <xs:complexType name="getRoomPriceResponse">
        <xs:sequence>
          <xs:element name="return" type="xs:float" />
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="getRoomPrice">
    <wsdl:part element="tns:getRoomPrice" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getRoomPriceResponse">
    <wsdl:part element="tns:getRoomPriceResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="IHotelPriceServiceFacade">
    <wsdl:operation name="getRoomPrice">
      <wsdl:input message="tns:getRoomPrice" name="getRoomPrice">
    </wsdl:input>
      <wsdl:output message="tns:getRoomPriceResponse" name="getRoomPriceResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HotelPriceServiceFacadeServiceSoapBinding" type="tns:IHotelPriceServiceFacade">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getRoomPrice">
      <soap:operation soapAction="" style="document" />
      <wsdl:input name="getRoomPrice">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getRoomPriceResponse">
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HotelPriceServiceFacadeService">
    <wsdl:port binding="tns:HotelPriceServiceFacadeServiceSoapBinding" name="HotelPriceServiceFacadePort">
      <soap:address location="http://localhost:8088/external-services-0.0.1-SNAPSHOT/webservices/HotelPriceService" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

FlightPriceService.wsdl

<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="FlightPriceServiceFacadeService" targetNamespace="http://external.services/flight"
  xmlns:ns1="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="http://external.services/flight" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified"
      targetNamespace="http://external.services/flight" xmlns:tns="http://external.services/flight"
      xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="getFlightPrice" type="tns:getFlightPrice" />
      <xs:element name="getFlightPriceResponse" type="tns:getFlightPriceResponse" />
      <xs:complexType name="getFlightPrice">
        <xs:sequence>
          <xs:element minOccurs="0" name="from" type="xs:string" />
          <xs:element minOccurs="0" name="to" type="xs:string" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="getFlightPriceResponse">
        <xs:sequence>
          <xs:element name="return" type="xs:float" />
        </xs:sequence>
      </xs:complexType>
      <xs:element name="LocationNotFoundException" type="tns:LocationNotFoundException" />
      <xs:complexType name="LocationNotFoundException">
        <xs:sequence />
      </xs:complexType>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="LocationNotFoundException">
    <wsdl:part element="tns:LocationNotFoundException" name="LocationNotFoundException">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getFlightPrice">
    <wsdl:part element="tns:getFlightPrice" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getFlightPriceResponse">
    <wsdl:part element="tns:getFlightPriceResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="IFlightPriceServiceFacade">
    <wsdl:operation name="getFlightPrice">
      <wsdl:input message="tns:getFlightPrice" name="getFlightPrice">
    </wsdl:input>
      <wsdl:output message="tns:getFlightPriceResponse" name="getFlightPriceResponse">
    </wsdl:output>
      <wsdl:fault message="tns:LocationNotFoundException" name="LocationNotFoundException">
    </wsdl:fault>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="FlightPriceServiceFacadeServiceSoapBinding" type="tns:IFlightPriceServiceFacade">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getFlightPrice">
      <soap:operation soapAction="" style="document" />
      <wsdl:input name="getFlightPrice">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getFlightPriceResponse">
        <soap:body use="literal" />
      </wsdl:output>
      <wsdl:fault name="LocationNotFoundException">
        <soap:fault name="LocationNotFoundException" use="literal" />
      </wsdl:fault>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="FlightPriceServiceFacadeService">
    <wsdl:port binding="tns:FlightPriceServiceFacadeServiceSoapBinding" name="FlightPriceServiceFacadePort">
      <soap:address location="http://localhost:8088/external-services-0.0.1-SNAPSHOT/webservices/FlightPriceService" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

SOAP Request For Basic Report Using The Omniture

A large deficit in the lack of SDK from the framework SDK OSX WebServicesCore services Web. Because the focus under the terms of the relationship line, at least surprising that any SOAP web services stack frame house. So what is the developer? You must register themselves.


Although the use of more convenient and better than the frames of all, no SOAP interaction with it is not difficult, but it seems the implementation of useful web services: Data Published endpoint via HTTP to a specific URL and removal of applications operating in what is natural.

Here’s a SOAP request for a basic report — an overtime trend of one metric — using the Omniture Web Services API:

<soapenv:Envelope>

<soapenv:Header>

<wsse:Security>

<wsse:UsernameToken>

<wsse:Username>$(ApiUsername)</wsse:Username>

<wsse:Password>$(OneTimeEncryptedPassword)</wsse:Password>

<wsse:Nonce>$(OneTimeNonce)</wsse:Nonce>

<wsu:Created>2009-01-09T18:53:56.545Z</wsu:Created>

</wsse:UsernameToken>

</wsse:Security>

</soapenv:Header>

<soapenv:Body>

<omn:Report.QueueOvertime>

<reportDescription xsi:type=“omn:reportDescription”>

<reportSuiteID xsi:type=“xsd:string”>$(ReportSuiteId)</reportSuiteID>

<date xsi:type=“xsd:string”>2008-11</date>

<dateGranularity>day</dateGranularity>

<metrics soapenc:arrayType=“omn:reportDefinitionMetric[]” xsi:type=“soapenc:Array”>

<item>

<id>pageviews</id>

</item>

</metrics>

</reportDescription>

</omn:Report.QueueOvertime>

</soapenv:Body>

</soapenv:Envelope>

This chunk of XML is POSTed to our SOAP endpoint, https://api.omniture.com/admin/1.2/. The response returned looks something like the following:

<?xml version=“1.0” encoding=“UTF-8”?>

<SOAP-ENV:Envelope>

<SOAP-ENV:Body>

<ns1:<eport.queueovertimeresponse></eport.queueovertimeresponse

<return xsi:type=”tns:reportQueueResponse”>

<status xsi:type=“xsd:string”>queued</status>

<statusMsg xsi:type=“xsd:string”>Your report has been queued</statusMsg>

<reportID xsi:type=“xsd:int”>1313624</reportID>

</return>

</ns1:Report.QueueOvertimeResponse>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

 

Creating and Parsing a SOAP request on the iPhone

To get this request to work in an iPhone application, we need to do the following:

  1. Create the SOAP header, complete with valid authentication credentials
    1. Encrypt your Omniture api username and secret.
    2. Use [NSString stringWithFormat:@"..."] to create the XML for our SOAP request.
  2. Package the SOAP header from (1), along with a SOAP Body, into a SOAP envelope.
  3. POST the SOAP envelope to the Omniture Web Service endpoint.
  4. Store the results and parse them using libxml.

Authentication Credentials

The following code snippet creates a valid SOAP header in Objective-C:

/** Returns a SOAP Header that complies to the OASIS UsernameToken profile specification
 */
- (NSString*) createSoapHeader {
    NSString* formatString = @"...use the header sample provided earlier...";
    //nonce
    srand(time(NULL));
    int n = rand();
    NSString* nonce = [[NSString stringWithFormat:@"%i", n] md5HexHash];
    //binary version for base64 encoding
    NSData* nonceBinary = [nonce dataUsingEncoding:NSUTF8StringEncoding];
    //date
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
    NSString* created = [formatter stringFromDate:[[NSDate date] 
                                                    dateWithCalendarFormat:nil 
                                                    timeZone:[NSTimeZone 
                                                        timeZoneForSecondsFromGMT:0]]];
    [formatter release];
    // digest = base64(sha1(base64_decode(nonce)+created+secret))
    NSString* digest_concat = [NSString stringWithFormat:@"%@%@%@", 
                                            nonce, created, 
                                            @"YOUR_API_SECRET_THAT_YOU_NEVER_SHARE"];
    NSString* digest = [[[digest_concat dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO] 
                          sha1Hash] 
                        base64Encoding];
    return [NSString stringWithFormat:formatString, 
            [user username], 
            digest, 
            [nonceBinary base64Encoding], 
            created];

 

Consuming Web Service

Consuming Web Service Using SOAP


  1. Start a new ASP.NET web application.
  2. Install msxml.msi, then click on “Add reference “ and then select “Interop.MSXML2.dll” and click on add.
  1. Create one label to display result (ID = lablel1).
  2. Declare objXMLHttp of type MSXML2.ServerXMLHTTP40.

Collapse

      Protected MSXML2.ServerXMLHTTP40 objXMLHttp
  1. Declare one string strSoapEnvelope which contains soap request.

Collapse

      string strSoapEnvelope= “”;
  1. Create SOAP Envelope strSoapEnvelope like this:

Collapse

strSoapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
strSoapEnvelope += "<soap:Envelope ";
strSoapEnvelope += "xmlns:xsi = \"http://www.w3.org/2001/XMLSchema-instance\" ";
strSoapEnvelope += "xmlns:xsd= \"http://www.w3.org/2001/XMLSchema\" ";
strSoapEnvelope += "xmlns:soap= \"http://schemas.xmlsoap.org/soap/envelope/\">";
strSoapEnvelope += "<soap:Body>";
strSoapEnvelope += "<AddTwoNumbers
  xmlns=\"http://localhost/wwwroot/addnumbers/Service1\">";
strSoapEnvelope +="<a>10</a>";
strSoapEnvelope += "<b>12</b>"
strSoapEnvelope += "</AddTwoNumbers >";
strSoapEnvelope += "</soap:Body>";
strSoapEnvelope += "</soap:Envelope>";
  1. Create an instance of ServerXMLHTTP40.

Collapse

objXMLHttp = new ServerXMLHTTP40();
  1. Set the header of SOAP request.

Collapse

objXMLHttp.open("POST", http://192.168.84.90/AddNumbers/Service1.asmx,false,"","")
objXMLHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
objXMLHttp.setRequestHeader("SOAPAction",
  "http://localhost/wwwroot/addnumbers/Service1/AddTwoNumbers");
  1. Send the SOAP request.

Collapse

objXMLHttp.send(strSoapEnvelope.ToString());
  1. Wait for some time.

Collapse

objXMLHttp.waitForResponse(500);
  1. Take response in string outXML.

Collapse

string outXML = objXMLHttp.responseText.ToString();
  1. Display result in label(ID= label1):

Collapse

Label1.Text = outXML.ToString();

Web Service Request To The SOAP Functions

I get a lot of people ask me how a Web service request to the SOAP functions and how cfinvoke ColdFusion CreateObject (“webservice”) to make. This usually means the same as in advertising, at the request of the soap (and answers) a clean, easy to ColdFusion file. Of course, this is not the case that people ask me, as a rule, people want to see how cfinvoke or CreateObject (is) to work with complex APIs.
There is no doubt that the soap ColdFusion works fine (albeit somewhat outdated). But if something is too hard, I find it easier to deploy and maintain applications soap work, if you fall in raw XML and HTTP users. Operational nature of soap that you have full control over all aspects of both the request and response so that the secret of how this type of data transfer.
To prove this, let me pass the SOAP API Monitor subscription request newsletter campaign up. Because the WSDL file, you should be able to think (with some determination) of each type of SOAP request expects a certain method calls. Depending on the complexity of a given WSDL file, can be a simple task or a complete nightmare. Fortunately, the API documentation is completed on the sample request XML professional audio and values ??of the response.

Here, we are defining our SOAP request in the content buffer, soapBody. This XML variable is then posted to the Campaign Monitor API using CFHTTP. Notice that when I post to the API, I am not using the “WSDL” URL flag; this is only needed when we actually want to retrieve the web service definition (as is typically required by the ColdFusion SOAP wrappers). Since we are posting the raw XML, no additional web service definition is required.

Creating A SOAP Message

Before going into details of the SOAP specification, let’s try a very simple SOAP example. There are 3 basic steps involved in a SOAP communication:

1. Creating a SOAP message. This is easy. Just use any text editor to enter the following SOAP message, hello.msg:

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
 <env:Header>
  <h:control xmlns:h="http://herong.com/header">
   <h:sender>Herong</h:sender>
  </h:control>
 </env:Header>
 <env:Body>
  <b:greeting xmlns:b="http://herong.com/body">
   <b:msg>Hello there!</b:msg>
  </b:greeting>
 </env:Body>
</env:Envelope>

2. Transmitting the message from a SOAP node, my machine, to another SOAP node, your machine. A simple way to do this is for me to send hello.msg to you as an email, so you will get something like this:

From: herong@my.com
To: you@your.com
Subject: Greeting

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
 <env:Header>
  <h:control xmlns:h="http://herong.com/header">
   <h:sender>Herong</h:sender>
  </h:control>
 </env:Header>
 <env:Body>
  <b:greeting xmlns:b="http://herong.com/body">
   <b:msg>Hello there!</b:msg>
  </b:greeting>
 </env:Body>
</env:Envelope>

SOAP-Based Web Services In The Manning Early Access Program

Just added a new chapter to discuss the channel and SOAP-based Web services in the Manning Early Access Program (MEAP) Create a beautiful version of Java. I am willing to cuibhiúil MEAP customers, I share here:
“Although they have fallen out of favor recently, offers exciting opportunities for SOAP-based web services for integration of Java / Groovy. This technology is mature, with cases of the use of special tools and knowledge that has been standard Java. In this chapter , go to the fundamentals of Web services with an emphasis on wsgen wsimport tool and integrated into the JDK 1.6.
Groovy build your application using the Web client services almost trivial. Wsimport tool to generate Java stubs, which can be an example and using the slot like any other Java class. Described as a reward to the Internet, XML, rather than points, it is easier to work with Groovy and Java.
To create a web service, I found it easier to use Groovy where the service of women in accordance with the application service endpoint interface, although not strictly required by the specifications. Standard interface / implementation split combination of Java and Groovy in any easier, though. A small complication when it comes to domain classes, but only if there is better access to other areas of the property, all work fine.
In general, web services, SOAP-based XML for disclosure of any of the two clients or servers. Exemption operator when using the pre-or post-processing of the message. As usual, Groovy is easier treatment of the Java XML. The solution I propose to use the Java classes that implement the appropriate interface manager, but a delegation from the actual class Groovy XML processing and manipulation.
Finally, I present the work assignments and wsimport wsgen Gradl, based on the same ant task.
Although most changes in the soap industry with the SES, SOAP based web services will become a reality for many companies in the near future. This chapter shows how you can use Groove to develop and work with them more easily.
Note that the list in Chapter 7 of the circle. For sample code using the various technologies included in the section in the middle (test Spock, use Gradl, etc.), but the lack of data that can read this chapter. ”

I like the model, although I always suspected that the data actually Gartner periodically to shake hands with the figure is purely speculation. In my experience, the time is rapidly approaching the peak PARTY inflated expectations. I know several people who have been successful, but the tools and APIs are still maturing. I am working on my current chapter on Java beautiful, although I can get everything to work, more effort than I expected. Do not wrong – I do not see the value of a sexually transmitted disease, but at this point is to get Java to work with more effort to use SOAP, believe it or not.
(Required somewhat funny anecdote: when I worked in the corporate culture, about six or seven years we have been partners in the production of Crystal Reports for business eventually acquired by a company called Business Objects (SAP even own businesses, but another story) . However, most business objects for OS short BOBJ most reasons are obvious. Of course, we use BO jokes about the kinds of teaching the class, followed by soap ….)
Part of the vision for the excess, but there it is compared to the frustration of web-based SOAP services to more people in recent days. One would think it would be plain SOAP safe productivity per hour, but if you go to all the conferences (or talk to a lawyer) is an insult is the world of soap is frustration.
No, I agree, but I think a good solution to this problem. In my opinion, one of the most important tasks for the day of Java developers to work with SOAP Web-based services, possibly in the architectural services (which may be misleading, but what can you do? Service)-oriented, and not go any time soon. In fact, the developers also work if it’s still early, and you begin to adapt to such words as hate the course, and idempotent