DougBreaux 270007SMYJ Visits (6813)
JAXB and Boolean
It turns out that by default, JAXB 2.2, the level in Java 7, generates the wrong kinds of getters for Boolean (wrapper object) fields. It generates isXXX() getters instead of getXXX() getters. And according to the JavaBeans spec, only boolean primitives are supposed to do that.
The fix is to use a JAXB compiler option, "-en
In the JAX-WS <wsimport> Ant task, it looks like this:
<target name="wsimport"> <wsimport sour
This causes getXXX() methods to be generated instead of isXXX() methods. (I found myself thinking it would be nice if both styles of getters were produced, but I admit I don't know if that would violate some other specification or convention.)
xs:boolean with minOccurs="0"
Related is the fact that, with this version of JAXB, XML schema types that have minOccurs=0 get generated as "wrapper" classes (e.g. Boolean) instead of primitives (boolean). This is so that the value can be null if the XML element is missing or empty.
Based on some non-null-safe legacy code that I'm migrating, it *seems* that earlier versions of JAXB behaved differently, at least under WebSphere 6.1: either using primitives or otherwise returning a default value on empty.
A different issue we saw with JAX-WS/JAXB under WAS 8.5.5/Java7, was that xs:string values with xsi:nil="true", were sometimes returning null rather than empty string. (Specifically, on the second and subsequent unmarshals. See forum thread.)
WebSphere 8.5.5 has an optimization option, com.
DougBreaux 270007SMYJ Visits (5156)
As a follow-up to Part 1, here are some additional considerations for generating JAX-WS code.
The wsdlLocation property for wsimport (whether from the command-line or from Ant) is placed in the generated JAX-WS @WebServiceClient class. It's placed both in that class annotation and in the static initializer block.
If you do not specify this option, the generated code will reference the absolute "file:" path to the .wsdl file on the local machine, which obviously won't work when deployed anywhere else. Alternative ways to deal with this are:
Option 3 seems to me the cleanest and simplest with our current projects' directory conventions, so this is what I plan to use. For example:
Client vs. Server
wsimport will generate:
Of these, item 2 is not necessary for a JAX-WS service. In fact, the existence of a client class could be confusing.
An alternative to using wsimport for the service code is to generate it with RAD tooling, which if you specify that you're creating a service, will not create the client class. This will also create a "stub" service implementation class, which wsimport does not do.
The generated service implementation class will be annotated with @WebService with name and targetNamespace attributes that match those of the generated interface described in item 1. Additional attributes for the serviceName and portName will be added as well (matching the <wsdl:service> and <wsdl:binding> elements, respectively).
Strangely (to my thinking) this generated class does not actually implement the Java interface.
However, relying on RAD tooling rather than scripting may be considered to reduce the repeatability of future builds, so it might be preferable to use the wsimport approach, delete the generated client proxy, and manually create the @WebService class with the proper annotation attributes and proper methods.
In either case, the @WebService implementation class will have actual calls to business code manually added to it, so once it's generated it should not be overwritten by any future process. Thus, perhaps the better approach is to initially create the service with RAD tooling, then subsequently use wsimport if WSDL changes require code to be regenerated.
Generated Code and Source Control
An earlier convention on our project was to generate the JAX-WS client code as part of the normal build process, every time the application is built. This is a reasonable, "ideal" approach since none of this code is "source" in the conventional sense. That is, it doesn't need to be tracked for human edits or backed up for recovery purposes.
However, since theoretically behaviors could change with newer code generations, it does seem safer to version-control this code. This would also allow easy recovery of previous versions of generated code if that became necessary.
Doing so would also
Finally, even with version-controlled generated code, having scripted methods to generate the code is still useful. This ensures that code generation options are documented and repeatable. Thus, we will be creating Ant targets even if they're not used as part of the default target and automated build process.
JAX-WS 2.2 is the latest version, and it's supported by WebSphere 8.5. However, it appears to sort-of want Java 7.
wsimport can either be run as a script or from Ant.
The script is part of the SDK now, even included with J2SE. The
The Ant task is actually provided by Sun classes, but they are included in WebSphere's jars as well. The
The jars required to run the Ant task are found in the WebS
If you want to try JAX-WS 2.2. under Java 6, you also need from the WebS
Create an Ant taskdef like this:
<!-- Ant task definition for wsimport -->
A sample <wsimport> task looks like this:
References and Articles
Edit: Update for newer WebSphere fixpacks
A colleague discovered that with the latest copies of the two "plugins" jars, the wsimport task no longer works. Sure enough, com.
Instead, however, the class com.