Simple Object Access Protocol (SOAP) is a protocol for exchanging structured information in a decentralized, distributed environment. It is XML-based and consists of three parts:
To illustrate just how easy it is to use OFBiz to create an unlimited number of SOAP-based web service clients, we shall discuss writing an SOAP-based client to request service from a real world web service: the U.S. National Weather Service's National Digital Forecast Database (NDFD). This web service provides a number of useful weather-related products. To keep our example simple, we shall request service from the NWS operation that provides the latitude and longitude for a given (valid) ZIP code. (Note: this web service only supports ZIP codes for the Continental United States, Alaska, Hawaii, and Puerto Rico).
To view the WSDL for all the operations supported by this web service, point your web browser to:
http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php#
To see the WSDL for just the zip code operation, select the LatLonListZipCode link.
Verify that the web service is up and running by viewing the WSDL in your browser:
http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl
While technically not part of the creation of an SOAP web service client, to illustrate many of the points of this chapter we shall describe a simple HTML form that allows us to enter in ZIP codes from a browser instead of hardcoding values in our SOAP client-code. This form shall be part of the myWebapp
main web page built elsewhere in this book. In this way, we may also return results in real time to the same web page as contains the form.
In addition to the HTML form, we shall build an OFBiz Service that takes the web page form, creates the appropriate SOAP message envelope, and calls the NWS web service.
For all this to work, we will also need to create a request-map in the myComponent
Component's myWebapp
webapp controller.xml
file that maps the form's URI request location to our OFBiz Service. To get started, the steps are as follows:
myWebapp
(within myComponent)
. When the run test button is clicked, this form will call an OFBiz Service. This can be seen in the following figure:abbreviated
) HTML form looks something like this:<form name="soapClient" action="<@ofbizUrl>soapClientService</@ofbizUrl>" method=post> <#-- HTML removed to improve readability --> <label for="01">Zip Code:</label> <input type="text" id="01" name="param1" value="" size="7"/> <input id="smt" style="display: inline" type="submit" class="smallSubmit" value="run test"/> </form>
controller.xml
file for the myWebapp
webapp:<!-- ======= Testing Soap Client ===== --> <request-map uri="soapClientService"> <security https="false" auth="false"/> <event type="service" invoke="soapClientService"/> <response name="success" type="view" value="main"/> <response name="error" type="view" value="main"/> </request-map>
<service name="soapClientService" engine="java" location="org.ofbiz.myComponent.myNewclasses.MyWebServices" invoke="soapClientService"> <description>Example SOAP client web service</description> <attribute name="endPoint" type="String" mode="IN" optional="true"/> <attribute name="namespace" type="String" mode="IN" optional="true"/> <attribute name="serviceName" type="String" mode="IN" optional="true"/> <attribute name="param1" type="String" mode="IN" optional="true"/> <attribute name="result" type="String" mode="OUT" optional="true"/> </service>
In this section, we look at the specifics of creating an SOAP client to call the U.S. National Weather Service web service and get the latitude and longitude given a ZIP code as passed from an HTML form:
JAR
files:// All the magic is in the following Axis client classes // They do all the hard work of creating SOAP wrappers // and dealing with the XML import org.apache.axis.client.Call; import org.apache.axis.client.Service; // We also need these JAR files import javax.xml.namespace.QName; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map;
soapClientService
OFBiz Service, is all that is needed to call the NWS web service and return an XML document containing our Service response:public static Map<String, Object> soapClientService( DispatchContext dctx, Map context) { Map results = FastMap.newInstance(); results.put("result", "success"); // Get everything we need out of the context (the HTML Form) String endPoint = (String) context.get("endPoint"); URL endpoint = null; // Define the web services end point as a URL try { endpoint = new URL(endPoint); } catch (MalformedURLException e) { Debug.log("Location not a valid URL" +e); } Service service = null; Call call = null; try { // Instantiate a new Axis Service object service = new Service(); // And create a call object from the Service call = (Call) service.createCall(); call.setTargetEndpointAddress(endpoint); String nameSpace = null; // Just in case, validate the FORM variables if(UtilValidate.isNotEmpty( (String) context.get("namespace"))) { nameSpace = (String) context.get("namespace"); } String serviceName = null; if(UtilValidate.isNotEmpty( (String) context.get("serviceName"))) { serviceName = (String) context.get("serviceName"); } // This is how we tell NWS which procedure to invoke call.setOperationName(new QName(nameSpace,serviceName)); // Since this is an artificial program and we know // that there is only a single input parameter for this // service that is the zip code, we are just going // to force it. Making this Service more generic is left // as an exercise for the reader. String zipcode = (String) context.get("param1"); // This is where we make the call and let OFBiz and Axis // do all the heavy lifting Object ret = (String) call.invoke(new Object[] {zipcode}); // And, hopefully, we return in line with a useful result results.put("result", ret.toString()); } catch (Exception e) { Debug.log("Exception when running our SOAP client test: " +e); results.put("result", "error: "); } // Note: we are returning the results as is and not extracting // each parameter as sent by the NWS web service. return results; }
myComponent
Component. myComponent
webapp using:http://localhost:8080/mywebapp/control/main
Like other web service clients, OFBiz SOAP-based clients first request access to a remote web service and then, when access is granted, consume the Service directly from the service provider inline with the programming logic in which they are embedded. Using the OFBiz SOAP integration greatly simplifies the business of writing SOAP web service client code.
In this example, results are returned directly to the calling web page as shown here:
You may use the WebTools Run Service service utility to invoke the NWS service by making a few simple changes to the Service definition for the testRemoteSoap
Service that is part of OFBiz out-of-the-box. The testRemoteSoap
Service definition is found in:
~framework/common/servicedef/services_test.xml
The following is the code:
<!-- the location = endpoint --> <!-- invoke parameter is the name of the service to invoke for example LatLonListZipCode --> <service name="testRemoteSoap" engine="soap" export="true" location= "http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php" invoke="LatLonListZipCode"> <description>A service to invoke the NWS web service</description> <namespace> http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ ndfdXML.wsdl#LatLonListZipCode </namespace> <attribute name="ZipCode" type="String" mode="IN"/> <attribute name="invoke" type="String" mode="IN" /> <attribute name="result" type="String" mode="OUT"/> </service>
Note: the out-of-the-box OFBiz Service definition for the testRemoteSoap
calls a web service that is no longer operational. It will not work as is.
After changing the testRemoteSoap
Service definition, you may invoke the Service without creating a web page or HTML form using the WebTools Run Service utility as shown here:
Submitting the Run Service form will bring up a form that will allow entry of the required ZIP code input for the NWS web service as shown here:
Hitting the Submit button will run the testRemoteSoap
OFBiz Service that, in turn, calls the NWS web service LatLonListZipCode
procedure with the ZIP code as entered on the Run Service form as part of the service request. Web service return values or an error code are displayed on the Schedule Job web page as shown here:
52.14.82.217