Using JAX-WS and JAXB with WebLogic Server 10: JAX-WS Customization Binding

by Mike Wooten
10/30/2007

This article provides a set of tutorials devoted to JAX-WS customization binding—the part of the JAX-WS specification that covers WSDL-to-Java mappings. Some mention of JAXB customization binding appears here and there.

Table of Tutorials

After introducing JAX-WS customization bindings, this article presents a set of tutorials showing how to carry out various customization tasks:

Afterwards, I'll take a look at some code samples that use the results of applying JAX-WS and JAXB customization bindings. Customization bindings apply to both the service consumer and service provider, so this will be reflected in these code samples:

Introduction to JAX-WS Customization Binding

JAX-WS customization binding is the part of the JAX-WS specification that covers WSDL-to-Java mappings. The JAXB specification includes a similar section that covers XSD-to-Java mappings.

This is all well and good, but why would you want to control WSDL-to-Java (or XSD-to-Java) mapping, anyway? I'll answer that question by using some situations you may have faced recently.

  1. You've got a WSDL that uses the value parameters for the name attribute of every <message><part> element. Your JAX-WS tools complain that they can't produce JAX-WS artifacts from this WSDL because the value of the name attributes aren't unique. You obtain the WSDL by concatenating ?WSDL to the service endpoint, and the party hosting the service endpoint has stated that it has no control over the WSDL because it generated "automagically."

    A customization binding will allow you to make the name attributes unique, and thereby solve this issue.

  2. You have a project where you need the Java method names and parameters of your JAX-WS Web service to match UML artifacts generated by the corporate architecture team at your company. The WSDL you've already distributed to partners would need to be changed to accommodate this, but you can't do that.

    A customization binding will allow you to make the method signature (for example, method name, input parameters) in the JAX-WS Web service match the ones in the UML artifacts.

  3. Your group has a policy that all classes generated from an XML schema must have a fully-qualified name that includes the following, in the order specified:

    • The word "schemas"
    • The four-digit year of the version, preceded by a lowercase x (for example, x2007)
    • The two-digit month of the version, preceded by a lowercase x (for example, x09)
    • The name of the .xsd file for the XML schema

    A customization binding will allow you to instruct your JAXB tools to meet this requirement when they generate JAXB classes.

These are just a few situations where you would want (or need) to use a customization binding. I'll be talking about how to do this throughout this article, so I'll return to defining what it is for now.

Customization binding is frequently referred to as binding declaration, so I'll switch to using that term for the remainder of this article. Binding declarations essentially are "instructions" expressed in XML, which can either be embedded in a WSDL or XML Schema file, or placed in an external XML file. With the latter, XPath expressions are used to select the target section in the WSDL or XML Schema file. The XML file-based approach is the one preferred by SOA architects and developers because it offers flexibility without sacrificing maintainability or governance.

Binding declarations are XML elements that are processed by Sun's wsimport Ant task. In the first article, I pointed out that BEA's Ant tasks (that is, jwsc, wsdlc and clientgen) call the wsimport task internally. I'll be using BEA's wsdlc Ant task in the code associated with this article, so here's the run-wsdlc Ant target that contains it:

<target name="run-wsdlc" depends="clean">

   <taskdef name="wsdlc" classname="weblogic.wsee.tools.anttasks.WsdlcTask" classpathref="compile.classpath" />

   <mkdir dir="${src.dir}"/>



    
                         <property name="binding.declaration.files" value="server-jaxws.xbd,shared-jaxb.xbd"/>



   <wsdlc

        
                         type="JAXWS"

       srcWsdl="etc/${wsdl.file.name}.wsdl"

       destJwsDir="WebContent/WEB-INF/lib"

       destImplDir="${src.dir}"

       explode="false"

       verbose="${verbose}"

       debug="${debug}"

       failonerror="true"

   >

        
                         <binding dir="etc" includes="${binding.declaration.files}"/>

       <classpath>

          <path refid="compile.classpath"/>

       </classpath>

   </wsdlc>

</target> 

                      

The type="JAXWS" attribute and child <binding> element are what matter for this discussion. The binding declarations reside inside the file(s) assigned to the includes attribute of the <binding> element. I use .xbd (which stands for XML Binding Declaration) as the file extension, for binding declaration files. The type="JAXWS" attribute tells the wsdlc Ant task to pass the file(s) through to the wsimport Ant task.

The <property> element holds the names of the two binding customization files that are used. The first one, named etc/server-jaxws.xbd, is for service provider-side JAX-WS binding declarations. The second one, named etc/shared-jaxb.xbd, relates to JAXB and is used on both the service provider and service consumer side.

What can you do with a JAX-WS binding declaration?

The simple answer is that you can specify how the information in the WSDL maps to Java code generated for a JAX-WS Web service and a JAX-WS Web service consumer. This Java code includes:

  • The interface class for the SEI provider

  • The skeleton class that implements the SEI provider interface class

  • The names of methods and parameters used in the skeleton class

  • The exception classes for faults

  • Using a java.util.Vector instead of a java.util.List in the method signature of a Web service*

  • Generating sub-classes, super-classes, and super-interfaces for Java objects used as the return value and input arguments of a Web service*

  • Generating enum classes and the values assigned to their members*

*Accomplished using a JAXB binding customization file

The next section of the article describes the JAX-WS binding declarations that allow you to do the non-asterisk items above.

Usage of JAX-WS Binding Declarations

Now I'll take a look at some of the ways you can use JAX-WS binding declarations.

Using a JAX-WS binding declaration to specify Java package names

This binding declaration is probably more valuable with JAXB than with JAX-WS, but it's an important one nonetheless.

I covered the JAX-WS aspect of this binding declaration in the first article, but this one is from the JAXB aspect. The purpose for using it is the same: to control the Java package name for the classes that are generated. Here are the contents of the shared-jaxb.xbd binding declaration file that is used to specify the Java package name for classes generated from an XML schema file:

<jxb:bindings

  version="1.0"

>

    <jxb:bindings

       xmlns:xs="http://www.w3.org/2001/XMLSchema"

        
                         schemaLocation="datastaging_exceptions.xsd"

       node="/xs:schema"

    >

       <jxb:schemaBindings>

           
                         <jxb:package name="services.datastaging.exceptions"/>

       </jxb:schemaBindings>

    </jxb:bindings>

</jxb:bindings> 

                      

Using this shared-jaxb.xbd file will result in services.datastaging.exceptions being used for the Java package name in all the JAXB classes generated from the datastaging_exceptions.xsd file. If you didn't specify a binding declaration file, the Java package name for the classes would be based on the targetNamespace attribute (of the <schemas> element) in the datastaging_exceptions.xsd file.

Note: Don't use the package attribute on the wsdlc, jwsc, or clientgen Ant tasks. Doing this will override the <package> binding declarations in your binding declaration file.

If your XML schema file uses <xs:include> or <xs:import> elements, things can be more challenging. The same holds true for a WSDL with a <xs:schema> that uses <xs:import> elements. In either case, you'll want to use a JAXB binding declaration file to specify the Java package name. Here's an extract from a JAXB binding declaration file that illustrates how to do that using an XML schema from the OASIS WS-Notification specification:

<jxb:bindings

  version="1.0"

>

  <jxb:bindings

    xmlns:xs="http://www.w3.org/2001/XMLSchema"

     
                         schemaLocation="schemas/oasis-wsn13.xsd"       node="/xs:schema"

  >

    <jxb:bindings

      xmlns:xs="http://www.w3.org/2001/XMLSchema"

       
                         node="//xs:schema/xs:import[@namespace='http://docs.oasis-open.org/wsn/b-2']"

    >

      <jxb:schemaBindings>

        <jxb:package name="org.oasis_open.docs.wsn.b_2"/>

      </jxb:schemaBindings>

    </jxb:bindings>



    <jxb:bindings

      xmlns:xs="http://www.w3.org/2001/XMLSchema"

       
                         node="//xs:schema/xs:import[@namespace='http://docs.oasis-open.org/wsn/br-2']"

    >

      <jxb:schemaBindings>

        <jxb:package name="org.oasis_open.docs.wsn.br_2"/>

      </jxb:schemaBindings>

    </jxb:bindings>



    <jxb:bindings

      xmlns:xs="http://www.w3.org/2001/XMLSchema"

       
                         node="//xs:schema/xs:import[@namespace='http://docs.oasis-open.org/wsn/t-1']"

    >

      <jxb:schemaBindings>

          <jxb:package name="org.oasis_open.docs.wsn.t_1"/>

      </jxb:schemaBindings>

    </jxb:bindings>

    ...

  </jxb:bindings> 

</jxb:bindings> 

                      

The bold typeface sections highlight the fact that the XPath expression in the node attribute is what makes things click. The first nested <jxb:bindings> element contains the schemaLocation attribute, which establishes the XML schema file to be operated on. The node attribute in the other nested <jxb:bindings> elements is where you deal with the various <xs:import> elements in the XML schema file.

You can have more than one nested <jxb:bindings> element with a schemaLocation attribute in a single binding declaration file. If modularity and ease of reuse are high on your list of priorities, then you may not want to do that. Using a separate binding declaration file for each XML schema allows them to be easily used for other purposes. It also makes it easier to organize them into reusable software assets, for governance purposes.

Pages: 1, 2, 3

Next Page »