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 handler chains

The <javaee:handler-chains> binding declaration allows you to specify that JSR-181 (Web Services Metadata for the Java Platform) artifacts be generated. It will:

  1. Generate a handler chain XML configuration file
  2. Insert a javax.jws.HandlerChain annotation in code that is generated.

Here's an extract of the <javaee:handler-chains> binding declaration I used on the service provider side:

 

<bindings

    
                         wsdlLocation="DataStagingService2.wsdl"

>

    ...

    <bindings

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

        
                         node="wsdl:definitions"

    >

        
                         <javaee:handler-chains            <javaee:handler-chain>               <javaee:handler>                  <javaee:handler-name>VendorSOAPHandler</javaee:handler-name>                  <javaee:handler-class>services.datastaging.VendorSOAPHandler</javaee:handler-class>               </javaee:handler>            </javaee:handler-chain>         </javaee:handler-chains>

    </bindings>

    ... 

</bindings> 

                      

Writing the JAX-WS handler was a rather involved process, so I'll skip discussing it in this article. The only thing I'll point out is that the VendorSOAPHandler class processes a SOAP header, which was created by a service consumer side JAX-WS handler. If you're interested in in-depth information on how to write JAX-WS handlers, you should check out Young Yang's "Get a handle on the JAX-WS API's handler framework" article.

Sample JAX-WS Code that Uses Binding Declarations

Until now, I've focused primarily on the binding declarations file and the things you can do in it. Now I'm going to switch it up a little bit and look at some service consumer and service provider code that:

  • Was generated during the running of BEA's wsdlc Ant task, or

  • Uses the JAX-WS artifacts generated during the running of BEA's wsdlc Ant task.

Sample JAX-WS Code that uses binding declarations in the service provider

I've done a complete 180 from the service provider code used in the first article. The key differences are:

  1. I switched from the "Start from Java" to the "Start from WSDL" programming model.

  2. I added a binding declaration to change the name of the Web service operation from dataStaging to sendInputURIs.

  3. I added a binding declaration that causes wrapper style types to be used in the skeleton SEI class that's generated.

  4. I added a binding declaration that changes the name of the generated SEI interface class to DataStagingService2.

  5. I added a binding declaration to control the name of a new Exception class ( DataStagingServiceException) I added.

  6. I added a JAX-WS SOAP Handler to process the Vendor SOAP Header added by a service consumer-side JAX-WS SOAP Handler.

The skeleton SEI class generated by BEA's wsdlc Ant task is so small that I decided to include it here in its totality:

 

package services.datastaging;  



import javax.jws.WebService; 

import javax.xml.ws.BindingType; 

import javax.jws.HandlerChain;  



/**  

* services.datastaging.DataStagingServiceImpl class implements web service endpoint interface services.datastaging.DataStagingService2 

*/  



@WebService(

   portName="DataStagingServicePort",

   serviceName="DataStagingService",

   targetNamespace="http://services.irad.acmeworld.com/datastaging",

   endpointInterface="services.datastaging.DataStagingService2",

   wsdlLocation="/wsdls/DataStagingService2.wsdl"

) 

@BindingType(value="http://schemas.xmlsoap.org/wsdl/soap/http") 

@HandlerChain(

   file="jar:file:WebContent/WEB-INF/lib/DataStagingService2_wsdl.jar!/services/datastaging/DataStagingService2_handler.xml"

) 

public class DataStagingServiceImpl implements services.datastaging.DataStagingService2 

{

    public DataStagingServiceImpl() 

    {   

    }



    public com.acmeworld.irad.services.datastaging.DataStagingResponse.OutputURIs sendInputURIs(com.acmeworld.irad.services.datastaging.DataStaging.InputURIs inputURIs)

      throws services.datastaging.DataStagingServiceException 

    {

        //replace with your impl here

        return null;

    }

} 

This skeleton SEI class will be overwritten every time you run BEA's wsdlc Ant task, so you need to guard against code losses resulting from running it accidentally. The safest way to do this is to make periodic backup copies of it. I also combat this by removing the run-wsdlc Ant target from all the depends attributes appearing in the build.xml file.

Sample JAX-WS code that uses binding declarations in the service consumer

I used the Dispatch client API approach in the JAX-WS client code for the first article. In this article, I switch to the Dynamic Proxy client API approach. The Dynamic Proxy client API involves using a service proxy class that was generated by BEA's clientgen Ant task. That Ant task calls Sun's wsimport Ant task internally.

Our etc/client-jaxws.jbd file contains the binding declarations I use on the service consumer side. It includes binding declarations to:

  1. Generate asynchronous methods in the service proxy class. I use these methods in the sample JAX-WS client to invoke the SEI method asychronously.
  2. Change the method names used in the interface class for the service proxy.
  3. Change the parameter names used in the interface class for the service proxy.
  4. Generate the JSR-181 artifacts for a service consumer-side JAX-WS handler chain.

I'll show you the code for doing the asynchronous method invocation first:

 

        ... 

        DataStagingService service = new DataStagingService();  



        service.setExecutor(Executors.newSingleThreadExecutor());          



        DataStaging port = service.getDataStagingServicePort();         

        ... 

This code extract shows that a single-threaded threading model is used to invoke the void handleResponse(Response) callback method. The setExecutor() method on the client's java.xml.ws.Service instance is used to designate this. Here's a code extract of the class that implements the javax.xml.ws.AsyncHandler interface:

 

... 

private class ClientCallback implements AsyncHandler<datastagingresponse> 

{

     public void handleResponse(Response<datastagingresponse> response)

     {

         try

         {

           log("handleResponse(Response<datastagingresponse>)", (new StringBuffer()).append("Callback method was invoked.").toString());



           printDataStagingResponse(response.get());

         }

         catch (Exception e)

         {

             e.printStackTrace();

         }

     }

}

... 

These tutorials reveal that you can do a lot of useful things with binding declarations. They also provide lots of details about how to use them with WebLogic Server 10. The reason for providing this level of detail was twofold:

  1. I've seen quite a few "unanswered" posts on the BEA NewsWeb newsgroup, where individuals are seeking assistance with doing JAX-WS and JAXB on WebLogic Server 10. I used this article to answer some of these, plus did a little "knowledge transfer" on JAX-WS development with WebLogic Server 10.

  2. I wanted to provide something that could function as a "complementary reference" to the documentation provided by Sun on this topic.

This level of detail should reduce the number of Google searches you need to do, when you encounter issues while using the JAX-WS implementation in WebLogic Server 10.

Using the Table of Tutorials is the recommended way to go directly to the use case you need to implement.

Summary

JAX-WS binding declarations provide you with a powerful mechanism for influencing the artifacts generated by Sun's wscompile and wsimport Ant tasks. These binding declarations can either be embedded in a WSDL or placed in a file containing an XML document that conforms to the XML Schema. Using a file is the recommended method.

The WebLogic Server 10 Web services stack provides BEA Ant tasks (that is, clientgen, wsdlc, and jwsc) that call the above-mentioned Sun Ant tasks internally. They provide a <binding child element for you to specify the JAX-WS (and/or JAXB) binding declaration file to use.

Having this kind of control is great, but it does come at a cost complexity-wise. Java EE development has a history of being perceived as "overly complex," and JAX-WS binding declarations don't do anything to change this. "Hand-coding" JAX-WS binding declarations files in a text editor is not an activity that most Java developers will find appealing and better IDE support is required.

Looking Ahead

The final article in this series will be devoted to some of the advanced capabilities in the Glassfish JAX-WS Commons project. My research revealed that the JARs from that project can be used along side the Glassfish JAX-WS 2.0 ones already being used in a WebLogic Server 10. I'll primarily be covering things like:

  1. Using Spring beans as service implementations.

  2. Using the Spring configuration framework to create a JAX-WS service that supports multiple binding types simultaneously. The javax.xml.ws.BindingType annotation allows you to use only one.

  3. Creating, hosting, and invoking RESTful services on WebLogic Server 10. These are "true" RESTful services, not just some HTTP endpoint that uses the HTTP GET method and a long query string.

  4. Creating, hosting, and invoking JSON (Java-Script Object Notation) services on WebLogic Server 10.

  5. Creating JSON service consumers that invoke JSON services.

See you then.

References

The following links provide additional information on things discussed in this article:

Mike Wooten is a Sr. Principal Solutions Engineer in BEA's prestigious TSG (Technical Solutions Group). His waking hours are usually spent helping BEA customers turn their abstract technical notions/concepts, into revenue-generating solutions that exceed the capabilties offered by their competitors.