users@jaxb.java.net

How to force JAXBElement<?> as data type

From: Claus Nagel <claus.nagel_at_gmail.com>
Date: Wed, 22 Oct 2008 19:53:11 +0200

Hi all -

I have a schema A like follows:

[schema A, namespace="a"]
<xs:schema xmlns="A">
  ...
  <xs:complexType name="Person">
    <xs:sequence>
      ...
      <xs:element ref="_PersonHook" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="_PersonHook" type="xs:anyType" abstract="true"/>
  ...
</xs:schema>
[/schema A]

The purpose of the abstract element "A:_PersonHook" is to augment the
type "A:Person" with additional property elements without the need for
subclassing. For example, there could be another schema B as follows:

[schema B, namespace "B"]
<xs:schema xmlns="B">
  <xs:import "schemaA"/>
  ...
  <xs:element name="personName" type="xs:string"
substitutionGroup="A:_PersonHook"/>
  ...
</xs:schema>
[/schema B]

A corresponding instance documents could look like this:

[XML instance]
...
<A:Person>
  <B:personName>name</B:personName>
</A:Person>
...
[/XML instance]

By this means, A:Person can be augmented by arbitrary elements from
different namespaces.

And now to JAXB:
In my project, I am just working with schema A. If I generate Java
classes from A using xjc (2.1.8), this results in the following class
for Person:

[Java class Person]
public class Person {
  protected List<Object> personHook;

  public List<Object> get_PersonHook() { ... }
}
[/Java class]

The data type "Object" is not really helpful. However, if I feed xjc
both with schemas A and B, I get the following code for Person:

[Java class Person]
public class Person {
  protected List<JAXBElement<?>> personHook;

  public List<JAXBElement<?>> get_PersonHook() { ... }
}
[/Java class]

That's exactly what I want to have! By this means I can declare my
"hooks" using @XmlElementDecl to inject elements from different
namespaces into A:Person.
So it seems that xjc needs the information that "A:_PersonHook" is the
head of a substitutionGroup in order to correctly map it to
JAXBElement<?>. However, I just have schema A in my project.

So here comes my question: How can I force xjc to map A:_PersonHook to
a JAXBElement<?> and not just to Object if I have just schema A at
hand? The problem is, that schema A is lacking the information that
A._PersonHook is the head of a substitutionGroup... Well, at least
this is my guess...

At the moment I am doing a hack: I create an artifical schema B for
all my "hooks" in schema A (there are quite a lot of them!). By this
means, xjc generates JAXBElement<?>s. The generated classes for B are
deleted right after xjc has finished.

I am sure there is a smarter way to handle this!
Thanks for suggestions and advice,
Claus