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

Building with a build.xml File

I'm going to be using the Eclipse IDE that ships with WebLogic Server 10 for the walk through. WebLogic for Workshop 10 doesn't have a specific Eclipse IDE plug-in for JAX-WS and JAXB development, so I'll use a build.xml Ant script and the Ant View window.

This build.xml is too long to embed in the article, so I'll present just noteworthy fragments of it.

<path id="jaxws.classpath">

        <fileset dir="${bea.home}/modules">

                <include name="javax.xml.stream_1.0.0.0.jar"/>

                <include name="javax.jws_2.0.jar"/>

                <include name="javax.xml.bind_2.0.jar"/>

                <include name="javax.xml.ws_2.0.jar"/>

                <include name="javax.xml.soap_1.3.0.0.jar"/>

                <include name="javax.activation_1.1.jar"/>

                <include name="glassfish.jaxws.rt_2.0.1.jar"/>

                <include name="glassfish.jaxb_2.0.5.jar"/>

                <include name="glassfish.jaxws.saaj.impl_2.0.1.jar"/>

                <include name="glassfish.jaxws.tools_2.0.1.jar"/>

        </fileset>

</path>

The above listing points out the <path> element used in the build.xml. It shows that WebLogic Server 10 uses shared Java EE library modules for the classes in its JAX-WS and JAXB implementation. As you can see, these are classes from the Glassfish RI JARs, not classes written by the WebLogic Server 10 Web Services stack development team. Shared Java EE library modules facilitate packaging up the Glassfish JARs, and allow a single copy of them to be used for multiple internal (to BEA) and external purposes. The ${BEA_HOME}/modules directory is the well-known place for these library modules.

The JARs in the above listing were placed in a user-defined library to make it easier to write code that uses the JAX-WS and JAXB APIs inside the Eclipse IDE.

Generating the JAX-WS Service Endpoint and JAXB Classes

The next step looks at the coding of the DataStagingService Web service. It starts with running the BEA wsdlc Ant task, in order to produce a skeleton JAX-WS endpoint implementation and the JAXB classes.

WebLogic Server 10.1 uses jars from the Glassfish Project for its JAX-WS and JAXB implementations. The presence of the type="JAXWS" attribute is what causes JAX-WS and JAXB to be used, instead of JAX-RPC.

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

 <taskdef name="wsdlc" classname="weblogic.wsee.tools.anttasks.WsdlcTask" 

          classpathref="compile.classpath" />



 <property name="client.binding" value="custom-client.xjb"/>



 <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="${client.binding}"/>

        <classpath>

                <path refid="compile.classpath"/>

        </classpath>

 </wsdlc>

;/target>

                      

The main things to note are the type="JAXWS" attribute and the <binding> child element.

You should now be able to run the Ant build file. This will generate the code for the JAX-WS endpoint implementation. Because I supplied a customization file, the generated code will be in the com.acmeworld.irad.services.datastaging package. The full code for the JAX-WS endpoint implementation is too long to include here, but here's an extract:

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

{

    DataStagingResponse dataStagingResponse = null;

    InputStream inputstream = null;



    try

    {

        //DataStaging.InputURIs contains zero or more

        //DataStaging.InputURIs.InputURI JAXB objects.

        //We loop through them, and use one of their getter

        //methods to print out a bound value.



        DataStaging.InputURIs.InputURI inputURI = null;

        List<datastaging.inputuris.inputuri> inputURIList = inputURIs.getInputURI();



        for (int i = 0; i < inputURIList.size(); i++)

        {

            inputURI = inputURIList.get(i);

log("dataStaging(InputURIs)", "inputURI.getUri()=" + inputURI.getUri());

        }



        //Next, we show one way to use the JAXB API, to convert

        //the DataStaging.InputURIs input parameter to a byte[].

        //This byte[] will contain an XML representation of that

        //input parameter.



        JAXBContext jc = JAXBContext.newInstance(DataStaging.InputURIs.class);

        Marshaller marshaller = jc.createMarshaller();

        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        JAXBElement<datastaging.inputuris> je = new JAXBElement(

            new QName("http://services.irad.acmeworld.com/datastaging","inputURIs"),

            DataStaging.InputURIs.class,

            inputURIs

        );

        marshaller.marshal(je, baos);



        //We use an existing XML file for the response from the

        //Web service operation. We�ll load this XML file from

        //the WEB-INF/classes directory, and use the JAXB API

        //to create the JAXB object of our response.

        inputstream = Thread.currentThread().getContextClassLoader().getResourceAsStream("SampleDataStagingResponseDocument.xml");



        jc = JAXBContext.newInstance(DataStagingResponse.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();

        dataStagingResponse = (DataStagingResponse)unmarshaller.unmarshal(inputstream);

    }

    catch (Exception e)

    {

        throw new RuntimeException(e);

    }

    finally

    {

        if (inputstream != null) try {} catch (Exception e){}   

    }

        

    return dataStagingResponse.getOutputURIs();

}

The code comments provide a pretty good explanation of what's going on, so I won't supply any additional narrative here.

Compiling the JAX-WS Service Endpoint

The BEA jwsc Ant task is used to compile the JAX-WS service endpoint and produce the WAR file that will be deployed.

<target name="run-jwsc">

  <taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask"

           classpathref="compile.classpath" />



  <jwsc

    destdir="${domain.home}/deployments/${project.name}"

    srcdir="${src.dir}/${package.path}"

    classpath="WebContent/WEB-INF/lib/${wsdl.file.name}_wsdl.jar"

    keepGenerated="${keep}"

  >

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

    <module explode="false" name="${portType.name}Impl">

      <jws

         
                        
type="JAXWS"

          file="${service.name}Impl.java"

          compiledWsdl="WebContent/WEB-INF/lib/${wsdl.file.name}_wsdl.jar"

      >

         
                        
<WLHttpTransport

            contextPath="datastaging"

          serviceUri="DataStagingService"

          portName="DataStagingServicePort"

        />

      </jws>

    </module>

    <classpath>

      <path refid="compile.classpath"/>

      <pathelement location="WebContent/WEB-INF/lib/${wsdl.file.name}_wsdl.jar"/>

    </classpath>

  </jwsc> 

</target>

                      

Again, the main things to note are the type="JAXWS" attribute and the <binding> child element. It also illustrates a way to avoid putting WebLogic-specific annotations (for example, @WLHttpTransport) in the JWS.

Pages: 1, 2, 3

Next Page »