Using JAX-WS and JAXB with WebLogic Server 10: JAX-WS Customization Binding
Pages: 1, 2, 3

Using a JAX-WS binding declaration to specify the SEI provider interface class name

The class binding declaration is used to specify the provider interface class for an SEI (Service Endpoint Implementation). Here's an extract from the etc/server-jaxws.xbd file, which shows the class binding declaration being used for this purpose:

<bindings

    
                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

        
                         node="wsdl:definitions/wsdl:portType[@name = 'DataStaging']"

    >

       <jxb:javadoc>

          <![CDATA[<body>Name of Provider interface class for JAX-WS  
                         DataStagingService</body>.]]>

       </jxb:javadoc>

        
                         <class name="DataStagingService2"/>

    </bindings>

    ... 

</bindings> 

                      

Here, I'm telling the wsimport Ant task that I want the name of the SEI interface class it produces to be DataStagingService2. The wsdlLocation attribute gives the location of the WSDL file to process. This location is relative to where the binding declaration file is. I have it in the same directory as the WSDL file, so there is no path preceding it. The XPath expression selects the portType element in the WSDL, which is where the name of the generated interface class comes from, by default.

You'll find the resulting services.datastaging.DataStaging2.java file in the WebContent/WEB-INF/lib/DataStagingService2_wsdl.jar file.

Using a JAX-WS binding declaration to specify the skeleton SEI class name

You can also use the class binding declaration to control the name of the skeleton Java source file, which is generated by the wsimport Ant task. This happens when the wsdlc Ant task is executed. This is the same class binding declaration that is used for other things, so don't be confused by that.

I put the class binding declaration to specify the name of the skeleton Java source file in the etc/server-jaxws.xbd file. Here's an extract showing what it looks like:

<bindings

    
                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

        
                         node="wsdl:definitions/wsdl:service[@name = 'DataStagingService']"

    >

       <jxb:javadoc>

          <![CDATA[<body>Name of skeleton SEI class for JAX-WS  
                         DataStagingService</body>.]]>

       </jxb:javadoc>

        
                         <class name="DataStagingPortTypeImpl"/>

    </bindings>

    ... 

</bindings> 

                      

The bold typeface denotes the salient points. They tell the wsimport Ant task that you want the name of the skeleton class to be DataStagingPortTypeImpl. If you didn't have this binding declaration, the name of the generated skeleton class would come from the value assigned to the name attribute of the <service> element in the WSDL.

Unfortunately, doing this didn't produce the desired outcome. The problems were:

  1. The Java package name of the generated DataStagingPortTypeImpl class came out as com.acmeworld.irad.services.datastaging, not services.datastaging. I tried using a " <package>services.datastaging</package> binding declaration, as well as one tied to a <jaxws:bindings> element with a node="wsdl:definitions" attribute. Neither provided the desired results.

  2. DataStagingPortTypeImpl also becomes the name of the JAX-WS class that extends javax.xml.ws.Service. This is a class used by the service consumer, so I "let it slide" because I was on the service provider side.

  3. If you also specify a method binding declaration to change Web service operation names, they are not propagated to the DataStagingPortTypeImpl class that gets generated in #1 above. It looks like changes made with the parameter binding declaration don't get propagated either.

I think all of these anomalies are being caused by a bug in a class used with either the wsdlc or wsimport Ant tasks. There ended up being quite a few "side effects" to these anomalies, so as a workaround I chose to use Ant <replace> tasks on the skeleton SEI Java source that was generated.

Note: BEA support cases were filed to get the above issues "permanently resolved" in a WebLogic Server 10 patch or a future service pack.

Using a JAX-WS binding declaration to specify method names

The method binding declaration lets you control method names in code that is generated. One of the method names you can change is the getter for the proxy class in the generated Java source that extends javax.xml.ws.Service. Here's the associated extract from the etc/client-jaxws.xbd file. It appears in the etc/server-jaxws.xbd file as well:

<bindings

                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

         
                         node="wsdl:definitions/wsdl:service[@name = 'DataStagingService']/wsdl:port[@name = 'DataStagingServicePort']"

    >

       <jxb:javadoc>

          <![CDATA[<body>Returns proxy object used as the  
                         Dynamic Proxy client API when invoking Web service operations on the  
                         DataStagingService</body> Web service.]]>

       </jxb:javadoc>

        
                         <method name="getDataStagingPort"/>

    </bindings>

    ... </bindings>

                      

Here I change the getter method name from getDataStagingServicePort (the default name) to getDataStagingPort. You'll find the results in the test.consumers.datastaging.standalone.jaxws.DataStagingService.java file, which is in the lib/UC-01Client.jar file.

You can also change the method names used for Web service operations:

 

<bindings

     
                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

        
                         node="wsdl:definitions/wsdl:portType[@name='DataStaging']/wsdl:operation[@name='dataStaging']"

    >

       <jxb:javadoc>

          <![CDATA[<body>Sends URIs of resources to be staged</body>]]>

       </jxb:javadoc>

        
                         <method name="sendInputURIs"/>

    </bindings>

    ... 

</bindings>

                      

Here I use a method binding declaration to change the name of the dataStaging Web service operation to sendInputURIs. You'll find the results in the test.consumers.datastaging.standalone.jaxws.DataStaging.java file, which is in the lib/UC-01Client.jar file.

Using a JAX-WS binding declaration to specify method parameter names

The parameter binding declaration allows you to control the parameter names used in the methods of the skeleton SEI class. It uses:

  • A part attribute containing the XPath expression used to locate the parameter name to change.

  • The element attribute for the <part> element selected in the WSDL.

  • A name attribute to specify the new name for the parameter.

Here's the associated extract from the etc/server-jaxws.xbd file:

 

<bindings

    
                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

       xmlns:tns="http://services.irad.acmeworld.com/datastaging"

        
                         node="wsdl:definitions/wsdl:portType[@name='DataStaging']/wsdl:operation[@name='dataStaging']"

    >

       <jxb:javadoc>

          <![CDATA[<body>Input parameter for the  
                         dataStaging</body> method.]]>

       </jxb:javadoc>

        
                         <parameter            part="wsdl:definitions/wsdl:message[@name='dataStaging']/wsdl:part[@name='parameters']"            element="tns:dataStaging"            name="inputURIs"         />

    </bindings>

    ... 

</bindings> 

                      

Earlier, I used a class binding declaration to change the method name from dataStaging to sendInputURIs. Here, I'm trying to use a parameter binding declaration to change the parameter name from parameters to inputURIs. It didn't work, and the reason why appears to be because of the following important discovery:

The parameter binding declaration doesn't work if you also have a <enableWrapperStyle>true</enableWrapperStyle> binding declaration in the file.

It turns out that using the <enableWrapperStyle>true< enableWrapperStyle> binding declaration "automagically" results in the parameter name being changed to inputURIs. I decided to use <enableWrapperStyle>false</enableWrapperStyle> on the service consumer side instead. That way I could at least demonstrate this parameters binding declaration.

Using a JAX-WS binding declaration to specify exception class names

The class binding declaration has yet another use: allowing you to control the name of exception classes used on methods in the skeleton SEI class. Here's the associated extract from the etc/server-jaxws.xbd file:

 

<bindings
    
                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

        
                         node="wsdl:definitions/wsdl:portType[@name='DataStaging']/wsdl:operation[@name='dataStaging']/wsdl:fault[@name='JAXWSArticleException']"

    >

       <jxb:javadoc>

         <![CDATA[<body>General purpose exception for JAX-WS  
                         DataStagingService</body>.]]>

       </jxb:javadoc>

        
                         <class name="DataStagingServiceException"/>

    </bindings>

    ... 

</bindings> 

                      

This will cause a DataStagingServiceException class to be generated. It will be placed in the services.datastaging directory inside the WebContent/WEB-INF/lib/DataStagingService2_wsdl.jar file.

Using a JAX-WS binding declaration to specify asynchrony

The JAX-WS specification defines two paradigms for writing asynchronous clients:

  • Polling   This paradigm uses polling to determine if the response is available. The return type from the invocation of the operationAsync method is an instance of the javax.xml.ws.Response object. This javax.xml.ws.Response object contains methods that allow you to:

    1. Cancel the invocation.
    2. Block indefinitely, waiting on the server response.
    3. Block for a given time interval, waiting on the server response.
    4. Determine if the invocation was cancelled.
    5. Determine if the invocation completed, so you can subsequently get the response.

  • Callback   In this paradigm, the client provides a callback handler to accept and process the inbound response object. This callback handler needs to implement javax.xml.ws.AsyncHandler, which has a single void handleResponse(Response) callback method. javax.xml.ws.AsyncHandler extends javax.xml.ws.Response, but you really only need to use the get() method.

Both paradigms allow the JAX-WS client to continue doing things while the request is being processed at the service provider. Here's an extract from our etc/client-jaxws.xbd file, which shows how to specify the <enableAsyncMapping> binding declaration:

 

<bindings
    
                         wsdlLocation="DataStagingService2.wsdl" 

>

    ...

    <bindings

       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"

        
                         node="wsdl:definitions/wsdl:portType[@name='DataStaging']/wsdl:operation[@name='dataStaging']"

    >

        
                         <enableAsyncMapping>true</enableAsyncMapping>

    </bindings>

    ... 

</bindings> 

                      

This generates only an asynchronous version of the dataStaging method. If you want all the methods to have asynchronous versions, move the <enableAsyncMapping>true</enableAsyncMapping> to where the first ... is. The asynchronous methods will be in the test.consumers.datastaging.standalone.jaxws.DataStaging.java file, which is JARed up inside the lib/UC-01Client.jar file.

Pages: 1, 2, 3

Next Page »