Articles
Enterprise Architecture
Using JAX-WS and JAXB with WebLogic Server 10
Pages:
1,
2,
3
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.
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.
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.