Web Service Enable Builder
In this topic ...
Related Topics ...
Use the Web Service Enable builder to create a Web service from a model. This builder allows you to expose a method in a model as a Web service to either incoming SOAP requests to the server hosting the Factory or to service calls in local models.
Once you expose a method as a Web service, we can view the WSDL for the new service by appending "/Action!getWSDL" to the URL for your model. The example below is the URL to retrieve the WSDL document for the methods exposed as services in the GetCustomers model:
http://localhost:7001/Factory/webengine/my_models/GetCustomers/Action!getWSDL
We can get the URL for a model by opening the Model menu and selecting Model Settings. In the Model Settings dialog that is displayed, the setting "URL to run this model via browser" represents the URL.
See "Getting a WSDL URL " for information about retrieving the URL for a Web service-enabled method programmatically.
As of version 5.9.0, the Factory uses AXIS for its default inbound SOAP request processing. The method namespace URI (rpc style) or element namespace (document style) are key components in the inbound request routing. See "AXIS Deployment Descriptor" below for details.
Note, Web Service Enabling a model makes sense only for standalone webapp deployments, not for portlet WARs which run in the context of a portal.
For more information about creating, consuming, and publishing Web services, see "Web Services Overview ."
Quick Tips
- The Web Service Enable builder exposes methods whose inputs and outputs are of primitive or XML data types -- The Web Service Enable builder supports methods with the following argument and/or return types:
- Primitive types such as int, Integer, float, Float, double, Double, String, boolean, short, byte, Date, java.math.BigDecimal
- Arrays of the above primitive types as SOAP Encoded Arrays, and arrays of byte (byte[]) as the XSD base64 encoded datatype
- XML data type, passed or returned as com.bowstreet.util.IXml or org.jdom.Element
- void
For example, if you have a method that takes as an argument, or returns java.util.Hashtable, that method will not show up in the list of methods that you may expose as a Web service in the Web Service Enable builder call.
If an argument or return value is a complex type (for example, datatype = com.bowstreet.util.IXml), the Web Service Enable builder call editor displays an additional two builder inputs for that argument/return type, allowing you to select a known (to this model) XML Schema, and then a schema element within that schema, to be associated with this XML complex type. For more information about adding a schema to your model, see "How to Use the Schema Builder ."
- URL for incoming SOAP requests -- Releases prior to Factory 5.9 used the following URLs to support incoming SOAP requests:
SOAP RPC style requests for services hosted by the Factory go through the following URL:
http://FactoryHost:Port/AppContext/soaprpc/<modelnamepath>
SOAP Document style requests for services hosted by the Factory go through the following URL:
http://FactoryHost:Port/AppContext/soapdoc/<modelnamepath>
Replace "FactoryHost," "Port," and "AppContext" with the values for your Factory installation. Replace <modelnamepath> with the path to and the name of the model you want to access.
The default style in which the web service is exposed is rpc-encoded. Under the Advanced inputs section we can change the style for this web service to be rpc-literal or document-literal. When dealing with Xml documents being sent and received, doc-literal is the natural choice resulting in fewer interop issues and slightly better performance than rpc-style. WS-I chose to not endorse rpc-encoded, and so rpc-literal should probably be the choice for rpc style requests.
For backwards compatibility Factory 5.9 still supports those URLs. So a SOAP request targeted at a model with that URL will still work. However, as of version 5.9.0, the Factory uses Apache AXIS for both its inbound and outbound SOAP support. So generating a WSDL document as described above will generate the new form of URL to invoke the service. The new form is:
http://FactoryHost:Port/AppContext/servlet/AxisServlet
Note that there is no longer a reference to the model or method name in the URL. See "AXIS Deployment Descriptor" below for details on the inbound routing mechanism.
Specifying Inputs
The Web Service Enable builder takes the inputs described in the table below. For help on inputs common to many or all builders such as those in the Properties and HTML Attributes input groups, see "Using the Builder Call Editor ."
Input Name Description Name
Enter a name for this builder call. The Designer displays this name in the Builder Call List.
Method Information Method
Enter the method in this model that you want to expose as a service. Once you select one of the methods allowed for Web service enablement, the builder call editor displays that method's argument and return types as additional builder inputs.
You may specify a name and a brief description to be exposed for each of the argument in the WSDL description generated for this method.
Click here for information about using method type all.
Namespace
Specify the namespace associated with this method/service. The default value is the namespace associated with the model.
Unless you are implementing a service to a pre-defined WSDL interface, you may leave this builder input set to its default value.
This field is critical in AXIS inbound request routing. See AXIS Deployment Descriptors for details.
Reset Namespace
Press this button to recalculate the method/service namespace.
You might need to do this if you move a model to a new location , or rename a model. Pressing this button forces the builder to point to the current model path and name.
Return Value Name
An RPC style response is usually returned with a part name of "return". This input field allows you to override that part name.
Method Description
Enter some text to describe what the method, ultimately the service, does. For example,
"Returns a list of current customers based on the product name passed to this service."
Response Description
Enter some text to describe the data and its type returned by the service. For example,
"Returns a Customers structure."
Response Schema Path
Choose the schema type (or element) that defines the data returned by the method.
Note that If exposing as an RPC style it is usual to specify a type. If exposing as a doc-literal, specify an element.
For information on creating schemas for service inputs and outputs, see the "Creating Web Services " topic.
ArrayElem SchemaPath
This input is displayed If you return an IXml array ( IXml[] ) from a Method.
Set this to point to the schema type of the element in the array being returned.
The value does not show up in the WSDL, but is used in the response envelope as a type hint to the consumer.
Request Parameters Arg n Name (type)
For each argument that the method takes, enter a name that will identify this argument in the WSDL document and in the Service Call builder.
Arg n Description
For each argument the method takes, enter a brief description for this argument.
This description will be used to annotate the argument in the WSDL document.
Header Information MustUnderstand
Use this attribute to indicate whether header entry processing is mandatory or optional for the recipient. (The recipient of a header entry is defined by the SOAP actor attribute below). Choose:
Enforce - To require the recipient to process this header.
Ignore - To make processing by the recipient optional.
Request Headers
We can specify these SOAP "Request" headers for "required" header processing semantics, where you may not want or need the header defined in the WSDL. As a result, Request headers have an extra builder input per header (the WSDL column), that allows you to specify whether to also generate WSDL for that header.
Name - Name of the header
Namespace - Namespace associated with the header name
Type -Header type. Can be xsd:string, or a complex type such as soapinterop:SOAPStruct
Use -Encoding scheme. Can be literal or encoded
Required - Determines if header is required. Can be False or True
WSDL - Determines if WSDL is generated for the header. Can be False or True
SOAP Actor(s)
Use this attribute to indicate the recipients of a header element. The element will not be forwarded on by these addressees.
The value of the SOAP actor attribute is a URI.
Note that The URI "http://schemas.xmlsoap.org/soap/actor/next" indicates that the header element is intended for the first SOAP application that processes the message.
Response Headers
Specify SOAP Response header information to add the response header information to the WSDL.
Name - Name of the header
Namespace - Namespace associated with the header name
Type -Header type. Can be xsd:string, or a complex type such as soapinterop:SOAPStruct
Use -Encoding scheme. Can be literal or encoded
Advanced SOAP Style
Specify whether the service should be implemented as an RPC or Document style service.
By default, methods are enabled as RPC-encoded style services. Methods taking and returning ONLY XML (eg, IXml and/or org.jdom.Element) arguments may optionally be set to use SOAP Document style.
RPC style services include the method name as the child XML element name of the SOAP envelope body, with each method argument being represented as a separate XML child element of that method element. With AXIS, the method namespace is used for the inbound routing decision.
For Document style services, the entire child document of the SOAP envelope body will be sent to the method as a single XML (IXml or org.jdom.Element) argument. With AXIS, the element namespace is used for the inbound routing decision.
For more information on SOAP envelopes, and RPC vs Document style SOAP services, please refer to the W3C SOAP and WSDL Recommendation specifications.
Also see AXIS Deployment Descriptors for information about inbound request routing.
Encoding Style
Select an RPC encoding style. We can choose:
Encoded - To use SOAP encoding of arguments
Literal - To use XML schema typing of arguments
Note 1: RPC-encoding is the most common RPC use, but it is not endorsed by the WS-I. WS-I endorses rpc-literal and also doc-literal encoding styles.
Note 2: To expose a method as a document-literal style service, in addition to selecting doc-literal insure that the method name being exposed matches the top-level element name of the element in the SOAP Body, and that the method takes a single argument of type:
IXml or org.jdom.Element
and returns XXXX or IXML.
This restriction does not apply to rpc-style services since the method name is contained in the SOAP Body.
Content Length Zero
This input is available if the method being enabled is of type "returns void".
Use this input to specify that an HTTP response with "content length 0" should be returned.
For most deployed rpc-style services the SOAP response from a "returns void" service is a SOAP Envelope containing a Body with an empty "Return" element. The recommendation from WS-I is that "one-way" scenarios such as this return an HTTP response with content length set to 0.
This input allows you to override the default action which, in rpc-style, is to return an Envelope.
Note that If you chooses SOAP Style - Document, the Content Length Zero input will automatically switch to "true", but can overridden and switched to "false" if required..
Getting A WSDL URL
Once you have exposed a method as a Web service, you may want to access the WSDL URL programmatically in a method or using a ${Java/...} indirect reference. We can do this by using either the getActionURL() or getURL() methods on WebAppAccess and URLMapper objects, respectively.
To return the WSDL URL for the current model:
webAppAccess.getActionURL("getWSDL")
To return the WSDL URL for another model:
webAppAccess.getURLMapper().getURL(othermodelname, "getWSDL");
Both of these methods return a relative path to the WSDL document. To create absolute paths to the WSDL document, prepend the URL for the server to the result of the method calls above:
//WSDL URL for this model
String wsdlURL = webAppAccess.getRequestData().getContextURL() +
webAppAccess.getActionURL("getWSDL");
//WSDL URL for another model
String wsdlURL = webAppAccess.getRequestData().getContextURL() +
webAppAccess.getURLMapper().getURL(othermodelname, "getWSDL");
You may also want create an indirect reference to a WSDL URL for a builder call input. In both cases, you use the same API calls, but with the ${Java/...} syntax. For example, you could set the Tree Data input in a Tree builder call to:
${Java/webAppAccess.getRequestData().getContextURL() + webAppAccess.getActionURL("getWSDL")}
Processing SOAP Headers
To process incoming SOAP headers in your service method (which do yourself - there's no factory-wide default SOAP header processing provided), you may retrieve the SOAP Header information (if any was present in the incoming SOAP envelope), by retrieving them in IXml or JDOM Element format from the current HttpServletRequest via request attribute.
For example:
HttpServletRequest request = webAppAccess.getHttpServletRequest();
IXml soapHeaders = (IXml)request.getAttribute("bowstreet.soap.header");
org.jdom.Element soapHeaders = (Element) request.getAttribute("bowstreet.soap.jdom.header");
To send SOAP Headers in the response envelope from your service method, you may do so by setting a request attribute that will be picked up and inserted into the SOAP Response envelope.
request.setAttribute("bowstreet.soap.responseHeaders", ixmlSOAPHeaders);
or
request.setAttribute("bowstreet.soap.jdom.responseHeaders", jdomSOAPHeaders);
This builder also provides a set of inputs we can use to populate an control the content of SOAP headers. When working with these inputs, you refer to this W3C Note for additional information about SOAP header elements and their settings.
Limitations of Method Type "ALL"
We can choose All for the Method input to expose all the methods in a model as Web services. However, this is not a recommended practice because we cannot add information about the arguments for each method and you might inadvertently expose a method to the public. In addition, since XML arguments require schema typing to be usable, all will not expose any methods that have XML args or responses. Method type all has several additional limitations including:
- Type 'all' should only be used for methods that return simple datatypes (byte, string, boolean), and not XML.
- Specifying 'all' in the Web Service Enable builder will automatically set the service type to rpc-encoded (there is no way to change this).
- Selecting type "all" (to web-service enable all available methods) will not properly handle methods that return XML data. Since there is no way to specify a schema for the XML that is either being sent as an argument, or returned back to the service, the Service Call builder will fail and display the following error message:
"Deserializing parameter xxxxx: could not find deserializer for type
{http://ww.w3.org/2001/XMLSchema}any.
Method Type "all" and Namespaces
If a model contains two methods, one Web service-enabled explicitly with a Web Service Enable builder, and the other Web service-enabled implicitly by a Web Service Enable "all" builder, the Factory's WSDL generator can associate the specific namespaces as the method namespace of those methods, and will use the "all" namespace as the method namespace of the other methods. The service call will pick up the method namespace of the target method, and that's what Axis inbound routing will use to find a model. So specifying the two namespaces in the external properties is not a problem since the model can be located in both cases.
AXIS Deployment Descriptors
As of version 5.9.0, the Factory uses AXIS for both its inbound and outbound SOAP request handling. This section provides a summary to explain its impact on inbound request processing. (See http://ws.apache.org/axis/ for additional details. )
AXIS uses a Deployment Descriptor called "server-config.wsdd" to define the services available on a server. The deployment descriptor defines the service namespace, implementing class, methods, arguments, type mappings, etc. It resides in the project's WEB-INF directory.
An inbound SOAP envelope has as its first child element in the SOAP:Body a namespace, which is either the method namespace URI (if RPC) or the element namespace (if Document style). AXIS matches that namespace against the deployment descriptor entries, finds a match (using a FileProvider extension provided with the WebSphere Portlet Factory (WPF)), and then it invokes the WPF implementation to invoke the appropriate method in the appropriate model. There are some key points of note:
- Descriptor Information - The server-config.wsdd does not need to exist. The Factory will supply the descriptor information to AXIS dynamically at runtime and AXIS holds that data in memory.
- AXIS Examine Descriptor Property - If the server-config.wsdd does exist, there s a property (in WEB-INF/config/bowstreet.properties) that governs whether the Factory will allow AXIS to examine the descriptor first, or to call the Factory to find a model with a method that implements the namespace (and then allow AXIS to examine the descriptor file). Allowing AXIS to look at its descriptors first (and specifying them in server-config.wsdd) allows you to preempt processing of particular namespaces. (See Properties below.)
- Descriptor Deployment Property - There s a 2nd property that dictates whether, having found a model and built a descriptor, the Factory deploys that to the AXIS descriptors. The Factory returns the definition to AXIS to use, but it is just a "throw away" unless the Factory deploys it. By default the property is set to true which means that when the Factory finds a model implementing a desired namespace and creates a descriptor for it is then deploy it to AXIS (in memory), so that next time AXIS needs that namespace it will already have the information and not call the Factory to find a model for that namespace.
So having this "true" and having the other property set to allow AXIS to examine its descriptors first is the most efficient processing model. But in development when models are changing it is probably preferable to specify that the Factory does not deploy the descriptors it builds that way the changing models are always being examined for matching web services. (See Properties below.)
AXIS has various hooks for introducing request and response handlers for any inbound requests. See the AXIS site for information on this. Those handlers can be defined in the server-config.wsdd and used in the normal manner. The only difference in the mechanisms described above and the normal AXIS processing is that the Factory provides the definitions dynamically at runtime.
If bowstreet.system.request or bowstreet.system.webservice.incomingSOAPRequest log4j properties are set to debug, the descriptors generated and fed to AXIS will dumped out to the SystemOut log. This allows you to capture the descriptor for a particular model/namespace and copy it into the server-config.wsdd and override or modify values as needed. For this to work you will of course need to make sure the property that allows AXIS to look at its descriptors before calling for a model search is set.
Properties used by the WebServiceEnable or inbound SOAP request processing
The following properties are available to control the behavior of service-related operations. These properties should be set in the override.properties file located in a project's WEB-ING/config directory.
log4j Logging Properties
log4j.category.bowstreet.system.webservice.incomingSOAPRequest - Turns on debug when set to DEBUG
AXIS Properties
bowstreet.axis.inbound.checkConfigBeforeModels
- true = AXIS checks its config file and anything deployed dynamically, before it asks to search for models implementing a namespace
- false = AXIS asks to find a model matching a namespace, and only checks its config file or (dynamically deployed descriptors) if no match is found
bowstreet.axis.inbound.deployModelInfo
- true = if Factory finds a model implementing a namespace then Factory deploys the descriptor it builds into the AXIS runtime config. Thus descriptor is available for use when another request for that namespace arrives
- false = Don t deploy. If Factory finds a namespace match and return it to AXIS to use on this request, it gets thrown away afterwards and AXIS will need to ask Factory to search again if that namespace comes in again on another SOAP request.