2012년 3월 5일 월요일

[Technote] javax.xml.bind.JAXBException occurs when generating JAX-WS Web service client code

javax.xml.bind.JAXBException occurs when generating JAX-WS Web service client code


Problem(Abstract)

An application contains multiple Java™ API for XML Web Services (JAX-WS) Web services. The generation of the JAX-WS client code for each Web Service Definition Language (WSDL) is targeted for a common package. Similarly, two or more WSDLs may import a common XML Schema Definition (XSD) so that each service will reference a common class. Depending on the order of the client generation, calling one of the services may return an exception like the following:

CWPKI0027I javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException:
class testpkg_proxy.Query nor any of its super class is known to this context


Symptom

Associated JAXB and JAX-WS artifacts are generated for each WSDL. There are common artifacts shared across both of the services that are generated from each of the imported schemas.
In general this would work, as the schemas are shared across services. The problem is not with the schemas, but specifically with the WSDL artifacts. A class called ObjectFactory.java (defined by JAXB) is generated specific to each service. When the second generation happens, the ObjectFactory is overwritten. The new file does not contain references to the classes from the first generation and the JAXB runtime cannot configure itself properly.


Resolving the problem

There are different ways to solve this. For example, you could make the target namespace of each WSDL unique, or you could configure a JAX-WS binding customization for each WSDL. However, these solutions ultimately involve changes to the structure of the application. An alternative solution is to use a combination of the wsimport and xjc commands.

There are two basic steps.
1. Run wsimport for each WSDL to generate the artifacts.
2. Run xjc to compile the bindings of all of the WSDLs together.

For example, consider the following application structure.


The file structure of the project:


c:/Dev/TestProj/workspace/ProjectServices/
src/
test_proxy/
<client code artifacts...>
wsdl/
Service1.wsdl (includes import of Common.xsd)
Service2.wsdl (includes import of Common.xsd)
xsd/
Common.xsd

Syntax of the wsimport command:


> cd C:/Dev/TestProj/workspace/ProjectServices/wsdl
> wsimport.bat -d ../src -keep -verbose -p test_proxy Service1.wsdl
> wsimport.bat -d ../src -keep -verbose -p test_proxy Service2.wsdl

Syntax of the xjc command:


> cd C:/Dev/TestProj/workspace/ProjectServices/wsdl
> xjc.bat -d ../src -p test_proxy -verbose -wsdl Service1.wsdl Service2.wsdl

A simple bat file is included which can be used to automate the sequence of these commands.


* Note: File com.ibm.jaxws.thinclient_6.1.0.jar is needed by the xjc process for this technique. There are two solutions based on the platform.



    1. Update the default setting of WASFP_CLASSPATH to place this jar at the head of the list

    set WASFP_CLASSPATH=%WAS_HOME%\runtimes\com.ibm.jaxws.thinclient_6.1.0.jar;
    %WAS_HOME%\plugins\com.ibm.jaxb.tools_6.1.0.jar;
    %WAS_HOME%\plugins\com.ibm.ws.runtime_6.1.0.jar;%WAS_CLASSPATH%


    or

    2. Append the jar file after the default setting of WASFP_CLASSPATH

    set WASFP_CLASSPATH=%WAS_HOME%\plugins\com.ibm.jaxb.tools_6.1.0.jar;
    %WAS_HOME%\plugins\com.ibm.ws.runtime_6.1.0.jar;%WAS_CLASSPATH%

    @REM this line added to include thinclient jar file
    set WASFP_CLASSPATH=%WAS_HOME%\runtimes\com.ibm.jaxws.thinclient_6.1.0.jar;
    %WASFP_CLASSPATH%
Wsimport_XJC_Generic.bat

댓글 없음:

댓글 쓰기