Alpha 0.1 Version
Let's start by examining a simple example Web Service client that invoke a remote procedure echoString on the public Axis server at Apache.
1. #include "Platform.hpp" 2. #include <iostream> 3. #include "ServiceFactory.hpp" 4. #include "Call.hpp" 5. 6. 8. void main(int argc, char* argv[]) 9. { 10. const std::string endpoint = "http://nagoya.apache.org:5049/axis/servlet/AxisServlet"; 11. 12. Call *call = ServiceFactory::CreateCall(); 13. 14. std::string value = "Hello World!"; 15. 16. call->SetTargetEndpointAddress(endpoint.c_str()); 17. call->AddParameter(value, Call::IN_PARAM); 18. call->SetOperationName("echoString"); 19. call->SetMethodNamespaceURI("http://soapinterop.org/"); 20. 21. void* ret = call->Invoke(); 22. 23. if(ret) 24. { 25. std::cout << "The Result: " << (*(std::string*)ret) << std::endl ; 26. 27. delete (std::string*)ret; 28. } 29. 30. delete call; 31. }
(This example can be found in the folder TestHarnesses/Axis_client.cpp)
The above example shows the working order of the client library. To build this example for testing/debugging purpose first you should build the library from the source. To build the library you should posses GNU tools like GCC and GNU Make You must first make sure you have these tools installed on your system before proceeding. If you do not have required tools, ask your system administrator to get them for you. These tools are free under the GNU Public License and may be obtained from the Free Software Foundation.
Extract the Axis C++ client library distribution to a Folder of your choice (Lets call this folder as <Axis_folder>). In this folder start building the library & example as follows:
% gmake ; this will build the lib and place the library in <Axis_folder>/lib/<your platform> % cd TestHarnesses % gmake ; this will create a executable axtest in the same folder % ./axtest ; runs the example.
What's happening in the above piece of code? On lines 12 we instantiated a Web service handler from the service Factory: the Call object. This object stores the metadata about the web service you want to access. On line 16, we set the Call object with endpoint URL of the Web service we are interested with, i.e. the address of the SOAP-RPC provider. On line 17 we add a parameter to pass into the method that we are calling: the echoString(string str). On line 18, we set the operation (method) name of the Web Service. Line 19 defines the namespace URI to use on the Body of the SOAP-RPC. On line 21 we invoke the Web service, which return the result on the ret (a void pointer to the object -- in this case the result should be the message we are sending; "Hello World!" -- string). On line 25 we get the result by explicitly casting the data into the returned data type, in this case std::string. Next we clean up the memory allocated for this object & the memory allocated for the Call object.
You can see what happens to the arguments by looking at the SOAP request that goes out on the wire (look at the colored sections, and notice they match the values in the call above):
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:echoString xmlns:ns1="http://soapinterop.org/"> <arg0 xsi:type="xsd:string">Hello World!</arg0> </ns1:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
The String argument is automatically serialized into XML, and the server responds with an identical string, which we deserialize and print.
Note: You can actually see,XML flowing back and forth between a SOAP client and server, these on the consol.
In the above example, the parameters are in the order in which we sent them, but since we only passed
the objects themselves, Axis automatically named the XML-encoded arguments in the SOAP message "arg0",
"arg1", etc. If you want to change this, it's easy! Before calling invoke()
you need to call
AddParameter
for each parameter, like so:
call->AddParameter("testParam", value, Call::IN_PARAM);
This will assign the name testParam to the 1st (and only) parameter on the invoke call. This will also define whether it is an input, output or inout parameter - in this case its an input parameter. Now when you run the program you'll get a message that looks like this:
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:echoString xmlns:ns1="http://soapinterop.org/"> <testParam xsi:type="xsd:string">Hello World!</testParam> </ns1:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Note that the param is now named "testParam" as expected.