I have the following situation:
There is a tree structure for logical expressions which is used in our application and defined by a four class hierarchie:
Node is an abstract super class
OrNode is a sub class of Node representing OR
AndNode is a sub class of Node representing AND
Leaf is a sub class of Node representing a leaf node holding some data
Now the tree structure should be transfered to a web service which will do some operation on the tree (e.g. evaluating the result by gathering some other information)
The signature of that WS-Operation could be look like the following:
public TheResult evaluateTree(Node tree);
We are using JAX-WS and generate the web services classes with wsimport. First, there are no classes generated for OrNode, AndNode and Leaf. So, we added them manually. We convert the classes used on the client side to the generated classes created by wsimport. Next we want to call the web service operation with the converted tree as parameter. But here an exception occurs saying something like:
javax.xml.ws.soap.SOAPFaultException: javax.xml.bind.UnmarshalException - with linked exception: [javax.xml.bind.UnmarshalException: Unable to create an instance of InterfaceEntities.Node - with linked exception: [java.lang.InstantiationException]]
Here are the Wrapper classes added by us and generated classes:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OrNode")
public class OrNode
extends Node
{
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AndNode")
public class AndNode
extends Node
{
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "leaf")
public class Leaf
extends Node
{
...
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "node", propOrder = {
"children",
"resultSet",
})
@XmlSeeAlso({
Leaf.class,
OrNode.class,
AndNode.class
})
public abstract class Node {
...
}
EDIT:
Here is the generated XML-File when using Marshaller
as described in Blaise Doughan's blog (see answer below):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:treeInfo xmlns:ns2="http://webservice.api.process/">
<tree xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:OrNode">
<children xsi:type="ns2:leaf">
<!-- some fields holding values -->
</children>
<children xsi:type="ns2:leaf">
<!-- some fields holding values -->
</children>
</tree>
<!-- some fields holding values -->
</ns2:treeInfo>
It is a simple tree consisting of one orNode and two leaf nodes, treeInfo represents the class holding the Node/tree object with some other information. It is marked as the XmlRootElement with the corresponding annotation.
Did we miss anything?
Thanks in advance!
I've found the problem. We are using several web services, for each we generate the wrapper classes via wsimport
. And some webservices are using the node
class. Now, as I mentioned in my question, we had to implement some wrapper classes manually as they were not auto generated by wsimport
, i.e. we had to add wrapper classes for the OrNode
and AndNode
. You also have to add the XmlSeeAlso
element to the super class so that it knows its sub classes. We added the XmlSeeAlso
element for one web service but missed it for the other one. This caused the exception mentioned above.
If you are in development, a quick fix is to simply remove the abstract
key word from the class definition of the "abstract
" class. If the class is no longer abstract
, it will no longer throw the error. This may be a hack that you want to fix before releasing your code into production, but it can enable you to keep developing other aspects of your application before you resolve the deeper problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With