Glen Mazza's Weblog

« Previous day (Jun 3, 2017) | Main | Next day (Jun 5, 2017) »

https://web-gmazza.rhcloud.com/blog/date/20170604 Sunday June 04, 2017

Customizing and enhancing JAXB classes generated during the WSDL-to-Java process

If you're using JAXB databinding for your SOAP services, CXF's wsdl2java tool provides considerable flexibility in customizing the JAXB-generated Java classes, in general, those which map to the SOAP request and response objects. I'll be showing how this configuration can be added using a wsdl2java run on the eBay WSDL (download). (Not covered in this entry, but if you also or alternatively wish to modify the JAX-WS artifacts (i.e., the port and service classes) consult the wsdl2java command-line options and/or use a JAX-WS binding file.) The tutorial source code can be obtained from GitHub by using the "Clone or Download" button on the project site.

Four methods of configuring JAXB are discussed:

  1. Passing arguments to the XJC compiler to modify the generated JAXB artifacts
  2. Using a binding customization file
  3. Using third-party JAXB plugins to expand XJC command-line and binding file options
  4. Creating your own JAXB plugin

For ease of reference the pom.xml holding many of these customizations is shown below:

  1. Passing arguments to the XJC compiler to modify the generated JAXB artifacts

    There are several command-line options that can modify the generated JAXB objects without need for binding files or custom plugins, calling "xjc -help" at a command line that has the Java SDK in the classpath will give provide a complete list. Command-line options include specifying binding customization files, episode files (although they have limitations with wsdl2java), and changing the desired package name (-p) for the generated Java classes (this can also be done with binding files, as will be shown later.) Other options include the ability to add SAX Locator information (-XLocator), the @Generated annotation (-mark-generated) and the synchronized keyword (-Xsync-methods) to the exposed methods of the JAXB classes. You can see this configuration done in the pom.xml above via extraargs elements added to the cxf-codegen-plugin configuration. Note the desired options can either be placed on one line or split into multiple lines.

    Command-line option inheritance: The CXF Maven plugin provides an ability via the defaultOptions element to declare settings common for all WSDLs being processed within submodules. Unfortunately an extraargs or xjcArgs element declared at the WSDL level will override all other XJC settings defined at the higher level, so if you do a WSDL-level override of XJC arguments you will also need to include the non-overridden XJC settings present at the higher level.

  2. Using a binding customization file

    Customization of the XML Schema-to-Java binding process is covered in Chapter 7 of the JAXB 2.2 specification. The binding customization schema (download) provides a formal definition of the allowed customization elements, however JAXB provides extensions that again can be listed via xjc -help via command line. The sample binding file referenced by the cxf-codegen-plugin configuration is below. Note that the #types1 suffix to the jaxb:binding's schemaLocation attribute refers to the 1-based count of the xsd:schema element within the wsdl:types section. The JAXB compiler will usually give a helpful error message if the node syntax is incorrectly given.

    In addition to the JAXB configuration given in the pom.xml, the above binding file will make the following changes to the generated Java classes:

    • Via jaxb:schemaBindings, specifies the Java package that the classes will be a part of. (If not specified, package names derived from the Schema namespaces are used.)
    • Specifies that MyRenamedCatalogProductType will be the generated Java class for element CatalogProductType, and gives the class-level JavaDoc comment to be used for it.
    • Has MyRenamedCatalogProductType implement two interfaces using the third-party JAXB2 Basics's Inheritance Plugin: Cloneable and an empty marker interface I placed in the client package.
    • In class ErrorParameterType, adds a method-level JavaDoc comment for the errorValue property and renames a member variable from the paramID specified in the schema to myParamOverrideID.

    You can inspect the changes made by running mvn clean install on the project and then looking at the generated classes in the target/generated-sources folder.

    Notes:

    • These customizations can also be done in-line within the schema instead of using an external binding file as explained in the Sun Web Services tutorial.
    • An important customization not shown in the above binding file is jaxb:javaType, used in changing the mapping between the schema type and the resulting Java object generated, for example switching from XMLGregorianCalendar to java.util.Date for XML date/time types.
    • There is both a standard jaxb:javaType and a xjc:javaType extension providing additional functionality--see this Core Java Tech Tips article for details on the latter's usage.
    • Stackoverflow has a post on how the JAXB classes can be made serializable for caching or other purposes.

  3. Using third-party JAXB plugins to expand XJC command-line and binding file options

    Third party products such as the CXF XJC Extensions and Aleksei Valikov's JAXB2 Basics allow for additional customizations besides the functionality provided by JAXB, such as adding toString() and hashCode() methods to the generated classes. Mr. Valikov provides a wiki page and sample project for integrating JAXB Basics with CXF. (CXF also provides a JAXB wrapper that allows its plugins to be used for pure databinding--i.e., non-JAX-WS--purposes.) The pom.xml for this sample uses plugins from both these libraries, as explained in its comments. Note in the case of the JAXB2 Basics configuration the need to include the jaxb2-basics dependency within the codegen plugin and also jaxb2-basics-runtime as a compile-scope dependency as the plugin generates references to classes provided by the latter that will be needed when running the client.

  4. Creating your own JAXB plugin

    Checking the source code within the CXF XJC and JAXB2 Basics plugins can provide guidance, in particular the source for any plugins that provide functionality similar to what you are looking for. As with these third party plugins, within the pom.xml you'll probably need to add a new dependency for your plugin to the CXF codegen plugin, and if your plugin generates references to classes that will subsequently be needed at runtime, dependencies to the SOAP client as well.


Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.