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>&lt;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>