Web Service Development Guide : PART I Getting Started : Chapter 4 Extending Your Web Service : Add a Special SOAP Header
Add a Special SOAP Header
HydraExpress offers full support for SOAP and transport headers, and processes all required headers as well as any number of custom header elements. In this section, we extend the HelloWorld example further to create an appropriate response based on a provided locale.
Add the SOAP Header to the Generated Client
The first step is to modify the generated client implementation by adding a SOAP header element to a rwsf::CallInfo object. The call to the client proxy sayHello() service operation method passes in the rwsf::CallInfo object. The code that assembles the request message adds the SOAP header elements to the SOAP message header as well as adding the transport header elements to the transport header.
NOTE >> This example manipulates the SOAP header directly in the client and server implementation code, for the sake of simplicity. A better design would be to create message handlers on the client and server to do this work outside of the business logic. This design would allow future changes without having to recompile and redeploy the service. For information on creating custom message handlers, see Chapter 14, “SOAP Message Handlers.”
Open the generated client sample implementation, GreetingPortClient.cpp, located in the Extended\app\client directory.
Here’s the generated service operation method, as yet unimplemented. We’ll add the new code to this method.
 
void invoke_sayHello(GreetingBindingProxy& proxy)
{
std::string hellorequest_in;
std::string return_ret;
rwsf::CallInfo callInfo;
 
try {
return_ret = proxy.sayHello(callInfo, hellorequest_in);
} catch(const rwsf::SoapFaultException& e) {
std::cout << "Fault Code: " << e.getFault().getFaultcode().asString()
<< std::endl;
std::cout << "Fault String: " << e.getFault().getFaultstring() << std::endl;
}
}
 
Replace the above code for the service operation method with the following implementation to add a SOAP header element to the request message:
 
void invoke_sayHello(GreetingBindingProxy& proxy)
{
std::string hellorequest_in("World!");
std::string return_ret;
 
try {
rwsf::CallInfo callInfo; //1
 
callInfo.addRequestSoapHeader(rwsf::XmlName("LocaleHeader",
rwsf::XmlNamespace("locale",
"http://www.roguewave.com/examples/webservices/helloworld")),
"es_MX"); //2
 
return_ret = proxy.sayHello(callInfo, hellorequest_in); //3
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;
}
}
//1 Instantiates a rwsf::CallInfo object. This class contains data about a message, including session or transaction data, SOAP headers, or transport headers.
//2 Adds a request SOAP header element named LocaleHeader, in a namespace with the prefix locale, whose value is the literal string "es_MX", representing Mexican Spanish. In a real application, the locale would be obtained from the system’s locale data so the application would work correctly on any machine. As suggested earlier, this could actually be handled in a message handler rather than in the implementation code.
//3 Calls the sayHello() method in the proxy, passing the rwsf::CallInfo object containing the header data.
Save and close the file.
Edit the Server-Side Code to Return a Response Based on the Header
On the server-side, the server code extracts the locale information from the SOAP header and uses it to create an appropriate response for the locale.
Open the generated server sample implementation GreetingPortTypeImp.cpp located in your Extended\app\server directory. Let’s look at the generated sample service operation method:
 
std::string
GreetingPortTypeImp::sayHello(rwsf::CallInfo& callInfo, const std::string&
hellorequest_in)
{
typedef std::string returnType;
throw rwsf::ServerFault("Sorry: The service was invoked but the requested
operation \"sayHello\" has not been implemented. An implementation must be
written.");
return returnType(); // (never executed)
}
 
To implement the method to extract the locale information from the client’s SOAP header, replace the code above with the implementation below:
 
std::string GreetingPortTypeImp::sayHello(rwsf::CallInfo& callInfo,
const std::string& hellorequest_in)
{
std::string localeValue = //1
callInfo.getRequestSoapHeaderValue(
rwsf::XmlName("LocaleHeader", rwsf::XmlNamespace("locale",
"http://www.roguewave.com/examples/webservices/helloworld")));
std::string response;
if (localeValue == "es_MX") { //2
response = "Hola al mundo!";
}
else {
response = "Hello" + hellorequest_in;
}
return std::string(response); //3
}
//1 Extracts the value for the locale contained in the SOAP header from the client.
//2 Logic to determine the correct response. Of course, a real application would have some kind of map from locale value to appropriate responses.
//3 Returns the appropriate response.
Save and close the file.