This is a very simple example of using the restToSoap extension of the WebSphere sMash Connection API with a php-based client app to invoke a remote web service. We have not implemented any of the PHP SOAP libraries yet for WebSphere sMash, but this example shows the relative ease in which a PHP script can use our PHP to Java bridge to invoke native Java classes and methods.
The SOAP web service referenced in this example is the W3Schools temperature conversion service at http://www.w3schools.com/webservices/tempconvert.asmx.
4 required elements in the sMash application:
- ivy.xml configuration of dependencies
- zero.config updates for the connection API configuration to wire our remote web service to a handler
- a groovy template file which generates the request body
- the php client script
/config/ivy.xml – need to include php and zero.connection.soap dependencies, and resolve the sMash application in order to get the required support from the repository:
<dependencies>
<dependency org="zero" name="zero.core" rev="[1.0.0.0, 2.0.0.0["/>
<dependency org="zero" name="zero.php" rev="[1.0.0.0, 2.0.0.0["/>
<dependency org="zero" name="zero.connection.soap" rev="[1.0.0.0, 2.0.0.0["/>
</dependencies>/config/zero.config – need to add a connection configuration to map connection API requests for a given local address our external web service URL:
/config/connection/destinations += {
"http://localhost:8080/f2c/*" : {
"handlers" : [{
"name" : "restToSoap",
"config" : {
"endpointAddress" : "http://www.w3schools.com/webservices/tempconvert.asmx",
"SOAPVersion" : "1.2",
"r2sMapping" : [{
"RESTOperation" : "POST",
"URLMatch" : "/f2c/{Fahrenheit}",
"SOAPAction" : "FahrenheitToCelcius",
"SOAPBodyTemplate" : "f2c.gt"
}]
}
}]
}
}/app/views/f2c.gt – a groovy template that generates the SOAP request body
<ns1:FahrenheitToCelsius xmlns:ns1='http://tempuri.org/'>
<ns1:Fahrenheit xmlns:ns1='http://tempuri.org/'><%= r2s_getParam("Fahrenheit") %></ns1:Fahrenheit>
</ns1:FahrenheitToCelsius>/public/getws.php – php client script that uses the PHP-Java bridge (java_import api) to expose the Java-based Connection API to php.
<?php
java_import("zero.core.connection.Connection",NULL,false);
java_import("java.util.ArrayList",NULL,false);
$contents=new ArrayList();
$contents->add('application/json');
$url = "http://localhost:8080/f2c/100"; //parm value '100' gets inserted into groovy template
$result=Connection::doPOST($url, array('Content-Type' =>$contents), NULL); // body provided by connection api
$responseBody=$result->getResponseBodyAsString();
echo "responseBody=".$responseBody;
?>When a user hits http://server:port/getws.php, it fires the Connection API call doPOST with the local url that matches our zero.config. The Connection api assembles the SOAP request, using the /app/views/f2c.gt template. The r2s_getParam(”Fahrenheit”) in the groovy template file is replaced with the value of {Fahrenheit} identified by the URLmatch parm of the connection configuration. The SOAP request is sent to our endpointAddress, and results are made available by getResponseBodyAsString().
Addendum: Move the client into a RESTful resource
I thought it would be more sMash-friendly if the simple PHP client above were converted into a RESTful resource. Just a little bit of wrappering around the existing PHP logic.
/app/resources/getws.php – Alternate client, converted to a RESTful resource
<?php
java_import("zero.core.connection.Connection",NULL,false);
java_import("java.util.ArrayList",NULL,false);
class getws {
function onRetrieve() {
// get passed in Fahrenheit value to use for temp conversion
$fahrenheit = zget('/request/params/getwsId');
// compose url
$url = "http://localhost:8080/f2c/".$fahrenheit; //parm value retrieved from gets inserted into groovy template
// setup and call connection api to invoke remote web service
$contents=new ArrayList();
$contents->add('application/json');
$result=Connection::doPOST($url, array('Content-Type' =>$contents), NULL); // body provided by connection api
// set the output content
$responseBody=$result->getResponseBodyAsString();
zput('/request/json/output',$responseBody);
// set the output content-type and render result
zput('/request/view', 'JSON');
render_view();
} // end of function onRetrieve()
} // end of class
?>When this resource is invoked via http://server:port/resources/getws/100, the RESTful parm on the end (100) is sent to the remote web service, converted from Fahrenheit to Celcius, and the SOAP response returned.
Addendum 2: Convert to a shared script, leveraged by both a public script and a resource
Taking one more step into sMash-friendly architecture. Separate the common logic shared by both the public script and the resource above into a shared script, then leverage using php include().
/app/scripts/common_ws_invocation.php – move the common logic into a function, and include in the calling scripts
<?php
java_import("zero.core.connection.Connection",NULL,false);
java_import("java.util.ArrayList",NULL,false);
function invoke_ws($fahrenheit) { // parm value now passed into function
$url = "http://localhost:8080/f2c/".$fahrenheit;
// setup and call connection api to invoke remote web service
$contents=new ArrayList();
$contents->add('application/json');
$result=Connection::doPOST($url, array('Content-Type' =>$contents), NULL); // body provided by connection api
// set the output content
$responseBody=$result->getResponseBodyAsString();
return($responseBody);
} // end of function invoke_ws()
?>/public/getws2.php – public script leveraging the shared common_ws_invocation.php. /app/scripts is automatically available in the php include path.
<?php include "common_ws_invocation.php"; //.include the common script $input_fahrenheit=$_GET['temp']; // unique parm parsing for public script $responseBody=invoke_ws($input_fahrenheit); // call common function echo "responseBody=".$responseBody; // unique output handling for public script ?>
/app/resources/getws2.php – resource handler that leverages common_ws_invocation.php.
<?php
include"common_ws_invocation.php"; // include the common script
class getws2 { // resource-specific class requirement
function onRetrieve() { // resource-specific RESTful function requirement
$fahrenheit = zget('/request/params/getws2Id'); // resource-specific retrieval of input parm
$responseBody=invoke_ws($fahrenheit); // call common function
zput('/request/json/output',$responseBody); // resource-specific output handling
zput('/request/view', 'JSON');
render_view();
}
}
?>


Leave a Reply