The error message in the title of this blog entry seems to be causing a lot of people in the world a lot of problems. In this blog entry, I hope to be able to reproduce the problem and solve it, once and for all, for everyone everywhere, using a great tool to support you in doing so, i.e., NetBeans IDE.
Let's start with this WSDL, which is useful in this context since it lets us reproduce the problem and then solve it:
Now you should see this:
Hurray! We've reproduced several JAXB binding problems. Let's now focus on solving them.
The biggest problem in solving these kinds of problems is that you're now going to go to Google and etc. There's hundreds (thousands, maybe) of developers who have encountered these kinds of problems over the years, there are many different solutions, each depending on the specific conflicts in the specific WSDL file, hence each solution being relevant for a subset of problems only. For example, in some scenarios, the -XautoNameResolution flag is helpful, while in others it isn't. It simply depends on the kind of JAXB binding problem you're dealing with.
The best thing to do is to start here, in the official documentation:
When you put the error message into a search in the official documentation above, you'll see this:
When schemas contain similar looking element/type names, they can result in "Two declarations
cause a collision in the ObjectFactory class" errors. To be more precise, for each of all
types and many elements (exactly what elements get a factory and what doesn't is bit
tricky to explain), XJC produces one method on the ObjectFactory class in the
same package. The ObjectFactory class is created for each package that XJC generates
some files into. The name of the method is derived from XML element/type names, and the error
is reported if two elements/types try to generate the same method name."
The first solution given for the above problem, right below the paragraph above in the documentation, is this:
"If the collision is coming from two different
schemas with different target namespaces, then you can easily avoid the collision by compiling
them into different Java packages. To do this, use <schemabindings> customization
on two schemas and specify the package name."
An awesome contributor to this discussion on the NetBeans users mailing list, where this has been discussed over the past weeks, is Matthias Bläsing. He provided a solution that includes the binding customization referred to above. I used that approach to make this YouTube screencast today:
However, though the above fixes the ObjectFactory problem, the end of the YouTube screencast ends with a bit of a hack where I search through various files and rewrite bits of names to other names, which could be handled more gracefully. Matthias Bläsing to the rescue again who tells me that my approach with the rewriting is probably going to be wrong in the end: "Depending on what you changed in the XSD, the result might compile, but not work, as the elements are not recognized on the receiving side. The approach via customization is that I don't change the data definition, but only its mapping to the Java side."
So, hurray, Matthias has provided a new binding file which solves all the problems simultaneously:
<?xml version="1.0" encoding="UTF-8"?>
<jxb:package name="moebius.data" />
<jxb:typeName suffix="Type" />
<jxb:class name="PersistentObjectOfInt2" />
<jxb:class name="PersistentObjectOfString2" />
Alternatively, download it here:
Download the above file and put it anywhere in your project, e.g., in the META-INF folder, where the 'jax-ws-catalog.xml' file is found. Name the file 'binding.xml' or whatever you like:
Select the file and press Alt-Shift-L, which copies the file's full path to the clipboard. In NetBeans IDE, right-click on the 'MoebiusIntegration' node within the 'Web Service References' node and choose 'Edit Web Service Attributes':
Next, when the dialog opens, click the 'WSDL Customization' tab, scroll all the way down to 'External Binding Files', click Add, read the helpful information, click Yes, press Ctrl-V to paste the clipboard content into the Open dialog, and click Open. You should now see this:
Click OK. Then Click OK again. After a few seconds of processing, you should now see this and be able to expand the node as shown below:
But that's not all! Guess what? Not only do you now have all the client code... and not only are all the JAXB binding problems solved... you can drag all those red-bulleted nodes you see above, which represent classes, into your own Java code. For example, this is what my main method looks like initially:
Now I put my mouse on 'AddHardwareServiceOrder', which is the first node underneath 'CustomBinding_IMoebusIntegration':
Then I drag the mouse anywhere within my own class and when I release the mouse I see this:
Also notice that everything throughout the project, generated code and everything else, compiled. In other words, I now have a solid starting point for interacting with a service made available by the WSDL with which I started.
In upcoming blog entries, I'll look more closely at the binding.xml file and explain, via explanations received from Matthias Bläsing, what the entries in it mean, how it is hooked into the build process (and also how it can be done via Maven instead of Ant) and help understand the binding file's content. For the moment, you can simply take it and then adapt it to your own needs. Hope the above helps all those people out there struggling with these specific binding problems with JAXB.