You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by nm...@apache.org on 2002/10/16 22:29:49 UTC
cvs commit: xml-axis-wsif/java/doc how_to_wsdl_extensions.htm how_to_provider.htm
nmukhi 2002/10/16 13:29:49
Modified: java/doc how_to_provider.htm
Added: java/doc how_to_wsdl_extensions.htm
Log:
Did provider documentation, first pass.
Added a placeholder for doc on how to write WSDL extensions and use them
in WSDL4J, which is related to the provider doc and reqd knowledge
for implementing a WSIF provider.
Revision Changes Path
1.2 +356 -3 xml-axis-wsif/java/doc/how_to_provider.htm
Index: how_to_provider.htm
===================================================================
RCS file: /home/cvs/xml-axis-wsif/java/doc/how_to_provider.htm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- how_to_provider.htm 14 Oct 2002 16:47:53 -0000 1.1
+++ how_to_provider.htm 16 Oct 2002 20:29:49 -0000 1.2
@@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-<meta name="Author" content="Aleksander Slominski">
+<meta name="Author" content="Aleksander Slominski, Nirmal Mukhi">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>Web Services Invocation Framework: How To Write Provider</title>
<link rel="stylesheet" href="wsif.css" type="text/css"></head>
@@ -13,10 +13,363 @@
<h2>What is WSIF Provider?</h2>
-<p>
+<p>WSIF, as its name suggests is an open-ended framework for invoking WSDL described
+services. As long as a WSDL description of the endpoint exists, it should be possible
+to use this framework ro invoke that piece of software, whatever it may be.</p>
+<p>As has been described in <a href="http://www-106.ibm.com/developerworks/webservices/library/ws-appwsif.html?loc=dwmain">this introductory article</a>, the WSIF API is driven by
+the abstract WSDL description of the service, and thus operates at a protocol-independent
+level. When an invocation takes place at runtime, the invocation of the abstract operation
+offered by the service needs to be converted into a protocol-specific mechanism for contacting
+the service endpoint, conveying the input message or other required information to the service,
+and receiving the response if any that results from the invocation. This result is eventually
+returned to the application that uses the high-level, protocol-independent WSIF API.</p>
+<p>The protocol-specific piece of software that enables the invocation to take place
+is the WSIF provider. There is one WSIF provider for each kind of WSDL binding supported
+by a particular installation of WSIF. For example, a particular installation may include the
+WSIF core along with the SOAP andEJB providers only. This would allow clients using WSIF
+at that site to invoke WSDL-described service that have SOAP or EJB bindings. Providers
+are pluggable and can be added to the installation at runtime.</p>
+<p>So far we understand that when the code using the WSIF API (let's call it the application,
+even though this code might actually be WSIF's dynamic proxy which provides an additional
+layer of abstraction for the real application) to invoke a service with a SOAP binding, the
+invocation takes place through a WSIF provider that supports this binding. How is a provider
+discovered? What happens if multiple providers support the same binding? (This is indeed
+the case for SOAP, since WSIF includes a SOAP provider based on Axis and one based on Apache
+SOAP). We will not address these issues in this document, here we will concentrate on
+the provider architecture itself, without regard to how WSIF knows about their existence.</p>
+<h2>Writing your own WSIF provider</h2>
+<p>A pre-condition for a working provider is that there should be a well-defined
+WSDL binding that it supports, along with the associated WSDL4J code that is capable
+of parsing the binding. Note that WSDL4J, by default, supports only the standard WSDL 1.1
+bindings: SOAP, HTTP and MIME. To add support for other providers in WSIF, one would first
+need to define the WSDL binding extensions, define the corresponding WSDL4J extensibility
+elements, and then register the serializers and deserializers for these extensibility
+elements with the WSDL4J extension registry. Details on this are available
+<a href="how_to_wsdl_extensions.htm">here</a>. The WSIF provider will use the WSDL4J
+extensibility elements defined since these are the in memory representation of the
+data in the binding.</p>
+<h3>The <tt>WSIFProvider</tt> interface</h3>
+<p>Let's discuss the specifics of a WSIF provider. A provider must implement the following
+interface:<br>
+<tt><pre>
+ /**
+ * For the given WSDL definition, service and port
+ * try to provide dynamic port,
+ * or return null if this provider can not do it.
+ * It is required to pass definition and service in addition to port
+ * as in current WSDL4J it is not posssible to retrieve service to
+ * which port belongs and definition in which it was defined.
+ */
+ public WSIFPort createDynamicWSIFPort(
+ Definition def,
+ Service service,
+ Port port,
+ WSIFDynamicTypeMap typeMap)
+ throws WSIFException;
-TBW
+ /**
+ * Returns the WSDL namespace URIs of any bindings this provider supports.
+ * The assumption is made that the provider supports all combintations of
+ * binding and address namespaces returned by this and the
+ * getAddressNamespaceURIs method.
+ * @return an array of all binding namespaces supported by this provider
+ */
+ public String[] getBindingNamespaceURIs();
+ /**
+ * Returns the WSDL namespace URIs of any port addresses this provider supports.
+ * The assumtion is made that the provider supports all combintations of
+ * binding and address namespaces returned by this and the
+ * getBindingNamespaceURIs method.
+ * @return an array of all address namespaces supported by this provider
+ */
+ public String[] getAddressNamespaceURIs();
+</tt></pre>
+</p>
+<p>OK, that's all you need to know. What, you mean the above wasn't self-explanatory?</p>
+<p>So let's get into a little more detail. Let's start witht he simpler methods:
+<tt>getBindingNamespaceURIs()</tt> and <tt>getAddressNamespaceURIs()</tt>. Each binding
+extension in WSDL is defined in a particular XML namespace. For example, the SOAP binding
+is defined in the namespace <tt>http://schemas.xmlsoap.org/wsdl/soap/</tt>, and similarly,
+so are the extensions under the <tt><port></tt> section of a WSDL document (often, as in
+the case with the SOAP extensions, the namespace is the same as the one in which binding
+extensions are defined). So, as the javadoc comments suggest, the WSIF runtime assumes that
+the provider supports invocation of any service with a namespace URI for binding extensions
+that is one of those returned by <tt>getBindingNamespaceURIs()</tt> and a namespace URI
+for address extensibility elements that is one of those returned by
+<tt>getAddressNamespaceURIs()</tt>.</p>
+<p>The core of the provider is the method <tt>createDynamicWSIFPort(..)</tt>. This returns
+a <tt>WSIFPort</tt> object that is constructed dynamically using:
+<ul>
+<li>the definition of the service we are invoking (the <tt>javax.wsdl.Definition</tt>
+parameter)</li>
+<li>the service we are invoking within that particular WSDL (the <tt>javax.wsdl.Service</tt>
+ parameter)</li>
+<li>the port offered by the service that lets us know the specific service endpoint, the
+binding and the port type that is being invoked (the <tt>javax.wsdl.Port</tt> parameter)</li>
+<li>a type map that maps abstract schema types in the WSDL messages for the operations in the
+port type being invoked to java types that correspond to them. WSIF will expect messages
+provided at the timeof invocation to have parts that are java objects of the required type,
+as specified by the type map (it of course allows the object used for the invocation to be of
+a less specific type as well).</li>
+</ul>
+</p>
+<p>Let's consider how a specific provider implements this and other interfaces. We will
+concentrate on identifying patterns that most provider implementations follow. Consider,
+for example, the Apache SOAP provider.
+<a href="../src/org/apache/wsif/providers/soap/apacheaxis/WSIFDynamicProvider_ApacheAxis.java">
+Here</a> is the source code for this implementation of the <tt>WSIFProvider</tt> interface.
+It is fairly straightforward. The constructor usually does very little, in most cases nothing.
+In this particular case it has a mechanism to set up the binding and address namespace URIs
+supported by this provider. It also adds to the WSDL4J extension registry used by WSIF the
+capability to parse JMS extensions. The capability to parse SOAP, EJB and java extensions are
+pre-registered, all other binding extensions may be registered in this fashion. The
+<tt>createDynamicWSIFPort</tt> method in the Apache Axis provider parses the binding associated
+with the port being invoked and verifies that it is indeed a SOAP binding. If this is the case,
+it creates a <tt>WSIFPort_ApacheAxis</tt> object, which implements the <tt>WSIFPort</tt>
+interface.</p>
+<h3>The <tt>WSIFPort</tt> interface</h3>
+<p>The main function of the WSIF port that is to create a <tt>WSIFOperation</tt> object at
+runtime when a WSDL operation needs to be invoked. At the minimum, the <tt>WSIFPort</tt> needs
+to know the name of the operation. If there is a possibility of overloaded operations, the
+application may invoke the form that takes the names of the input and output messages in
+addition to the name of the operation. <tt>WSIFOperation</tt> objects are the brains of the
+outfit; they actually perform the invocation based on a specific protocol. But more on that
+later, first let's see how the Axis provider implements the <tt>WSIFPort</tt> interface. The
+<a href="../src/org/apache/wsif/providers/soap/apacheaxis/WSIFPort_ApacheAxis.java">
+implementation</a> in the constructor itself parses the binding being invoked, doing some
+processing based on the transport being used (since WSIF's Axis provider supports SOAP messages
+over HTTP or JMS). In addition, it also verifies that the binding is indeed supported (for
+example WSIF does not support SOAP bindings that use document style instead of RPC style
+invocations <em>using the Axis provider</em> (document style is supported when using the Apache
+SOAP provider to handle SOAP bindings). Finally, the Axis implementation of the port actually
+iterates through the binidng, creating a <tt>WSIFOperation_ApacheAxis</tt> object (the
+protocol-specific implementation of the <tt>WSIFOperation</tt> interface) for each operation
+in the binding. These <tt>WSIFOperation</tt> objects are cached so that they don't have to be
+created each time. Of course that is optional, a bare-bones version of a provider could do very
+little in the constructor. The most useful method implemented here is <tt>createOperation</tt>,
+which creates the appropriate <tt>WSIFOperation_ApacheAxis</tt> object (based on the operation
+name and input and output names, if provided, to resolve the exact operation the application
+wants to invoke). The method first looks up the cache containing previously created instances
+and may reuse them or may create a new one.</p>
+<h3>The <tt>WSIFOperation</tt> interface</h3>
+<p>The real brains of the outfit is the <tt>WSIFOperation</tt> object. This interface has a
+number of useful methods, so let's do it in some detail:<br>
+<pre><tt>
+/**
+ * A WSIFOperation is a handle on a particular operation of a portType
+ * that can be used to invoke web service methods. This interface is
+ * implemented by each provider. A WSIFOperation can be created using
+ * {@link WSIFPort#createOperation(String)}.
+ *
+ * @author Owen Burroughs <ow...@apache.org>
+ * @author Ant Elder <an...@apache.org>
+ * @author Jeremy Hughes <hu...@apache.org>
+ * @author Mark Whitlock <wh...@apache.org>
+ */
+public interface WSIFOperation extends Serializable {
+
+ /**
+ * Execute a request-response operation. The signature allows for
+ * input, output and fault messages. WSDL in fact allows one to
+ * describe the set of possible faults an operation may result
+ * in, however, only one fault can occur at any one time.
+ *
+ * @param op name of operation to execute
+ * @param input input message to send to the operation
+ * @param output an empty message which will be filled in if
+ * the operation invocation succeeds. If it does not
+ * succeed, the contents of this message are undefined.
+ * (This is a return value of this method.)
+ * @param fault an empty message which will be filled in if
+ * the operation invocation fails. If it succeeds, the
+ * contents of this message are undefined. (This is a
+ * return value of this method.)
+ *
+ * @return true or false indicating whether a fault message was
+ * generated or not. The truth value indicates whether
+ * the output or fault message has useful information.
+ *
+ * @exception WSIFException if something goes wrong.
+ */
+ public boolean executeRequestResponseOperation(
+ WSIFMessage input,
+ WSIFMessage output,
+ WSIFMessage fault)
+ throws WSIFException;
+
+ /**
+ * Execute an asynchronous request
+ * @param input input message to send to the operation
+ *
+ * @return the correlation ID or the request. The correlation ID
+ * is used to associate the request with the WSIFOperation.
+ *
+ * @exception WSIFException if something goes wrong.
+ */
+ public WSIFCorrelationId executeRequestResponseAsync(WSIFMessage input)
+ throws WSIFException;
+
+ /**
+ * Execute an asynchronous request
+ * @param input input message to send to the operation
+ * @param handler the response handler that will be notified
+ * when the asynchronous response becomes available.
+ *
+ * @return the correlation ID or the request. The correlation ID
+ * is used to associate the request with the WSIFOperation.
+ *
+ * @exception WSIFException if something goes wrong.
+ */
+ public WSIFCorrelationId executeRequestResponseAsync(
+ WSIFMessage input,
+ WSIFResponseHandler handler)
+ throws WSIFException;
+
+ /**
+ * fireAsyncResponse is called when a response has been received
+ * for a previous executeRequestResponseAsync call.
+ * @param response an Object representing the response
+ * @exception WSIFException if something goes wrong
+ */
+ public void fireAsyncResponse(Object response) throws WSIFException;
+
+ /**
+ * Processes the response to an asynchronous request.
+ * This is called for when the asynchronous operation was
+ * initiated without a WSIFResponseHandler, that is, by calling
+ * the executeRequestResponseAsync(WSIFMessage input) method.
+ *
+ * @param response an Object representing the response.
+ * @param output an empty message which will be filled in if
+ * the operation invocation succeeds. If it does not
+ * succeed, the contents of this message are undefined.
+ * (This is a return value of this method.)
+ * @param fault an empty message which will be filled in if
+ * the operation invocation fails. If it succeeds, the
+ * contents of this message are undefined. (This is a
+ * return value of this method.)
+ *
+ * @return true or false indicating whether a fault message was
+ * generated or not. The truth value indicates whether
+ * the output or fault message has useful information.
+ *
+ * @exception WSIFException if something goes wrong
+ *
+ */
+ public boolean processAsyncResponse(
+ Object response,
+ WSIFMessage output,
+ WSIFMessage fault)
+ throws WSIFException;
+
+ /**
+ * Execute an input-only operation.
+ *
+ * @param input input message to send to the operation
+ * @exception WSIFException if something goes wrong.
+ */
+ public void executeInputOnlyOperation(WSIFMessage input) throws WSIFException;
+
+ /**
+ * Allows the application programmer or stub to pass context
+ * information to the binding. The Port implementation may use
+ * this context - for example to update a SOAP header. There is
+ * no definition of how a Port may utilize the context.
+ * @param context context information
+ */
+ public void setContext(WSIFMessage context);
+
+ /**
+ * Gets the context information for this binding.
+ * @return context
+ */
+ public WSIFMessage getContext();
+
+ /**
+ * Create an input message that will be sent via this port.
+ * It is responsibility of caller to set message name.
+ * @return a new message
+ */
+ public WSIFMessage createInputMessage();
+
+ /**
+ * Create an input message that will be sent via this port.
+ * @param name for the new message
+ * @return a new message
+ */
+ public WSIFMessage createInputMessage(String name);
+
+ /**
+ * Create an output message that will be received into via this port.
+ * It is responsibility of caller to set message name.
+ * @return a new message
+ */
+ public WSIFMessage createOutputMessage();
+
+ /**
+ * Create an output message that will be received into via this port.
+ *
+ * @param name for the new message
+ * @return a new message
+ */
+ public WSIFMessage createOutputMessage(String name);
+
+ /**
+ * Create a fault message that may be received into via this port.
+ * It is responsibility of caller to set message name.
+ * @return a new message
+ */
+ public WSIFMessage createFaultMessage();
+
+ /**
+ * Create a fault message that may be received into via this port.
+ *
+ * @param name for the new message
+ * @return a new message
+ */
+ public WSIFMessage createFaultMessage(String name);
+
+}
+</tt></pre>
+</p>
+<p>Most of the above is self-explanatory. The important things to note is that the
+invocation is achieved through this object. It also is capable of creating the messages
+(input, output, fault) that are associated with any invocation; such messages can be
+populated with data and then provided to methods such as
+<tt>executeRequestResponseOperation</tt>. Note also that as operations are designed
+right now, instances may not be reused since they often carry state that interferes
+with subsequent invocations using the same object. To prevent such misuse, the default
+implementation of the interface (which is extended by other implementations including
+<tt>WSIFOperation_ApacheAxis</tt>) has a <tt>close</tt> method which muct be invoked at
+the end of an invocation and sets a flag preventing further use. Applications may create a
+new operation instance using the <tt>WSIFPort</tt>. At some point we expect to modify
+the way operation instances are handled to allow reuse except in specific cases, hopefully
+simplifying the provider contract and improving performance.</p>
+<p>The Axis provider implementation of this interface is
+<a href="../src/org/apache/wsif/providers/soap/apacheaxis/WSIFOperation_ApacheAxis.java">
+here</a>. Everything the class does boils down to the use of the
+<tt>invokeRequestResponseOperation</tt> method. We won't get into detail, but this uses
+a protocol-specific library (in this case JAX-RPC, which is the client programming model
+supported by Axis) to invoke the service. Note how the provider code handles the type map that
+was provided at the time of creating the <tt>WSIFPort</tt> for invoking this service.
+For Axis, we need to register serializers and deserializers to marshall and unmarshall java
+objects into SOAP messages. This must be done prior to an invocation for it to work. Other
+providers may have to take similar steps to make sure they are capable of handling the
+java-typed data that populate the input and output messages used for invocation.</p>
+<p>So far we have not touched on <tt>WSIFMessage</tt> objects which are ubiquitous in the
+provider code. It's enough to think of a <tt>WSIFMessage</tt> as a map of WSDL message
+part names to java objects representing the value of that particular part. The type of the
+java object must match the expected type according to the type mapping supplied to the
+WSIF provider. WSIF also allows for creation of messages using primitive java types. The
+WSIF message interface is available <a href="../src/org/apache/wsif/WSIFMessage.java">here</a>.
+</p>
+<h3>That's it!</h3>
+<p>The protocol-specific implementation of the <tt>WSIFProvider</tt> interface, the
+<tt>WSIFPort</tt> interface and the <tt>WSIFOperation</tt>interface are all that are generally
+required to implement a WSIF provider. Supporting classes may also be included - for example
+the SOAP providers (both, Apache SOAP and Apache Axis providers) have utility classes to
+handle message exchanges using the JMS transport.</p>
<h2>Open Issues</h2>
<h2>performance and statefulness (for exampl in JCA connectors)</h2>
1.1 xml-axis-wsif/java/doc/how_to_wsdl_extensions.htm
Index: how_to_wsdl_extensions.htm
===================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Nirmal Mukhi">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>Web Services Invocation Framework: How To Write Provider</title>
<link rel="stylesheet" href="wsif.css" type="text/css"></head>
<body alink="#0000ff" bgcolor="#ffffff" leftmargin="2" topmargin="2" marginwidth="2" marginheight="2">
<h2>How to write your own WSDL extensions and plug them into WSDL4J</h2>
to do
<hr width="100%">
</body></html>