The Generated Application Samples
By default, HydraExpress produces sample client and service implementations. For the operation sayHello located at portType GreetingPortType, its code generator produces:
• a sample client implementation GreetingPortClient located in the directory HelloWorldExample\app\client. This implementation uses the generated proxy, GreetingBindingProxy located HelloWorldExample/codegen/client.
• a sample service implementation GreetingPortTypeImp located in directory HelloWorldExample\app\server.
NOTE >> The files in the project\app directory are meant to be edited and used to implement your client and service. The files in the project\codegen directory provide background functionality and should not be edited.
To implement the client and server, you can implement the methods in these generated sample implementations, or create your own implementations. In most cases, modifying the sample implementation is the simplest approach.
For this example, we will use the provided implementations, which are located directly in the HelloWorld directory, as follows:
<installdir>
examples/
HelloWorld/
GreetingPortClient.cpp //provided client implementation
GreetingPortTypeImp.cpp //provided server implementation
The following sections explain how to use the client and server implementations.
The Client Proxy
Class GreetingBindingProxy is the generated client proxy for the HelloWorld service. It provides five methods for each operation specified in the WSDL file. One pair of methods implements synchronous behavior, and the remaining three methods implement asynchronous behavior.
Excerpt from the client proxy for the HelloWorld service, GreetingBindingProxy.h, located in the generated HelloWorldExample\include\HelloWorldExample directory:
std::string sayHello(const std::string& hellorequest_in); //1
std::string sayHello(rwsf::CallInfo& callInfo, const std::string& //2
hellorequest_in);
rwsf::AsyncHandle sayHelloStart(const std::string& hellorequest_in); //3
rwsf::AsyncHandle sayHelloStart(rwsf::CallInfo& info, //4
const std::string& hellorequest_in);
std::string sayHelloEnd(rwsf::AsyncHandle& handle); //5
To send a message to the Web service, we must construct an instance of the proxy and invoke either the synchronous or asynchronous method(s) that correspond to the WSDL operation. The method returns the values defined in the WSDL file for the response message.
Using the Client Proxy and the Client Implementation
We use the client proxy to implement the HelloWorld client application. The generated sample implementations by default use one of the proxy’s synchronous methods, as shown here:
void invoke_sayHello(GreetingBindingProxy& proxy)
This section discusses implementing the client for a synchronous operation. For information on asynchronous operations, see
Chapter 13, “Asynchronous Messaging.”The following code shows the provided client implementation file, <installdir>\examples\HelloWorld\GreetingPortClient.cpp. The client implementation is not a class, but rather a source file that includes the proxy header file and a main() function that invokes the proxy’s methods. The code below is reformatted slightly to fit on the page:
#include "HelloWorldExample/GreetingBindingProxy.h" //1
#include <iostream>
#include <rwsf/webservice/DefaultLogger.h>
#include <rwsf/webservice/HandlerManager.h>
#include <rwsf/webservice/MessageHandler.h>
#include <rwsf/webservice/transport/TransportManager.h>
void invoke_sayHello(GreetingBindingProxy& proxy) //2
{
std::string hellorequest_in("World!");
std::string return_ret;
rwsf::CallInfo callInfo;
try {
return_ret = proxy.sayHello(callInfo, hellorequest_in);
std::cout << "Server Response: " << return_ret << std::endl;
} catch(const rwsf::SoapFaultException& e) {
std::cout << "Fault Code: " << e.getFault().getFaultcode().asString()
<< std::endl;
std::cout << "Fault String: " << e.getFault().getFaultstring()
<< std::endl;
}
}
void logError(std::string error, std::string detail) {
rwsf::HandlerManager::invokeLogger(error + ": " + detail,
rwsf::CallInfo::Error);
}
using rwsf::DefaultLogger;
RWSF_DEFINE_STATIC_MESSAGE_HANDLER("RWSFClientLogger", DefaultLogger)
int main(int argc, char* argv[])
{
// Instantiate GreetingBindingProxy.
// If you need to override the URL given in the WSDL file for
// the service, modify the constructor argument or pass in on
// the command line
std::string location; //3
if (argc < 2) {
location = "http://localhost:8090/helloworld/HelloWorld";
}
else if (argv[1][0]=='-' && argv[1][1]=='a') {
location = "http://localhost:8013/helloworld/HelloWorld";
}
else if (argv[1][0]=='-' && argv[1][1]=='l') {
location = "http://localhost:8090/helloworld/HelloWorld";
}
else {
location = argv[1];
}
try {
// initialize config files
try {
// default path from the bin directory
rwsf::NamingContext::loadGlobal("../conf/client-objects.xml");
rwsf::HandlerManager::loadConfiguration("../conf/client-handlers.xml");
rwsf::TransportManager::initialize("../conf/client-transports.xml"); //4
}
catch(...) {
// default path from the app/client vcproj file
rwsf::NamingContext::loadGlobal("../../conf/client-objects.xml");
rwsf::HandlerManager::loadConfiguration("../../conf/client-handlers.xml");
rwsf::TransportManager::initialize("../../conf/client-transports.xml");
}
GreetingBindingProxy proxy = GreetingBindingProxy::make(location); //5
if(!proxy.isValid()) {
std::cerr << "Unable to create proxy. " << "\nExiting" << std::endl;
return 1;
}
invoke_sayHello(proxy); //6
}
catch (const rwsf::Exception& x) { //7
logError("rwsf::Exception thrown", x.what());
std::cerr << "rwsf::Exception thrown: "
<< x.what() << std::endl;
return 1;
}
catch(const std::exception& x) {
logError("std::exception thrown", x.what());
std::cerr << "std::exception thrown:" << std::endl
<< x.what() << std::endl;
return 1;
}
catch(...) {
logError("Unknown exception thrown", "");
std::cerr << "Unknown exception thrown" << std::endl;
return 1;
}
return 0;
}
The sayHello operation requires a string as input (“World!”) and returns a message containing an string with the value “Hello World!”
The next step is to develop the service implementation. Then we’ll compile and run the application.
The Service Implementation
The GreetingPortType service operations are implemented by the service implementation class GreetingPortTypeImp.
To implement the server, you may either implement the methods of this class or derive your own class from GreetingPortTypeBase. In this example, we will use the provided implementation GreetingPortTypeImp located at <installdir>\examples\HelloWorld.
#include <rwsf/webservice/Fault.h> //1
#include <rwsf/core/NamedObject.h>
#include "GreetingPortTypeImp.h"
RWSF_DEFINE_MESSAGE_HANDLER(GreetingPortTypeImp) //2
std::string
GreetingPortTypeImp::sayHello(rwsf::CallInfo& callInfo,
const std::string& hellorequest_in)
{
return std::string("Hello " + hellorequest_in); //3
}
The section
“Compiling and Running the Application” explains how to compile and run the example program.