1

I'm trying to specify a implementation class for an XSD-Type. Here's a minimal example schema:

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test" 
        xmlns:tns="rd.test" elementFormDefault="qualified"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
  <complexType name="DocumentType">
    <annotation>
      <appinfo>
        <jaxb:class implClass="rd.DocumentEx" />
      </appinfo>
    </annotation>
    <sequence>
      <element name="element" type="tns:DocumentType" />
    </sequence>
    <attribute name="title" type="string" />
  </complexType>
<element name="document" type="tns:DocumentType"/>
</schema>

I'm using the standard xjc-tool from the Java JDK (1.7) for now (but I've also tested with maven-jaxb2-plugin, with the same results).

For a short test I used the following XML-document:

<?xml version='1.0' standalone='yes' ?>
<document title="testDocument">
  <element title="testElement" />
</document>

When I run the following test program, the results differ for the top-level document element (testDocument) and the contained child element (testElement). The root is of type "DocumentType", i.e. ignoring the specified implClass-directive, whereas the element is of type "DocumentEx", which is the expected result. In the generated ObjectFactory the appropriate instantiation seems correct, but it seems to be not used for the rootElement:

  public DocumentType createDocumentType() {
    return new DocumentEx();
  }

Here is the test program:

InputStream inp=new FileInputStream(new File("test.xml"));
JAXBContext jaxbContext = JAXBContext.newInstance("test.rd");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

JAXBElement el = (JAXBElement)unmarshaller.unmarshal(inp);
Object obj = el.getValue();
System.out.println("doc: " + obj);
// result: "doc: test.rd.DocumentType@d1c5bb0"

DocumentType doc = (DocumentType)obj;
Object obj2=doc.getElement();
System.out.println("obj2: " + obj2);
// result: "obj2: rd.DocumentEx@d1c5bb0"

I get the same result, if I specify the implClass for the element instead of for the complexType.

Why is the implClass ignored for the root-element? Any ideas and hints are appreciated!


Extension to clarify my intention:

I don't want to reference an existing, jaxb-annotated class, but use the auto-generated DocumentType-Class as base class for extionsion with additional attributes and methods. For a later direct marshalling back to XML, I have to keep the relation to the XSD-Type. Therefore the implClass-directive actually is the appropriate (as far as I know) way to instrument the jaxb-generation of the type-classes.

And it's working perfectly for the inner elements (the 'element' with title 'testElement' inside the document-tag)!! Unfortunately the unmarshaller does NOT use the implClass-specified class for instantiating the root-element correctly. See the result-comments in the program excerpt above (doc vs. obj2).

raindrop
  • 21
  • 3
  • possible duplicate of [Why is the ObjectFactory not used during unmarshalling?](http://stackoverflow.com/questions/26439184/why-is-the-objectfactory-not-used-during-unmarshalling) – lexicore Jan 21 '15 at 10:48
  • unfortunately it isn't. It just answers the question, why the ObjectFactory seems not to be used, but it doesn't answer (at least not to me), why the implClass works fine for an element inside another element, but not for the rootElement?! – raindrop Jan 21 '15 at 11:47
  • Thanks @lexicore for the hint The mentioned workaround with specifying a factoryClass and -method indeed circumvent the problem at first glance. Unfortunately this is not applicable as the appropriate DocumentType-Class will be automatically generated and therefore it's not good if there's the need for a manual modification. And nevertheless, the implClass is working perfectly for the element of the same type inside document without a manual specification of the factoryClass. And that's what I don't understand?! – raindrop Jan 21 '15 at 12:45
  • Did you ever find a solution for this? – Adrian Sep 17 '20 at 16:24

1 Answers1

0

For the behaviour you are looking for I believe you want to specify ref and not impl:

<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test"
        xmlns:tns="rd.test" elementFormDefault="qualified"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
    <complexType name="DocumentType">
        <annotation>
            <appinfo>
                <jaxb:class ref="rd.DocumentEx" />
            </appinfo>
        </annotation>
        <sequence>
            <element name="element" type="tns:DocumentType" />
        </sequence>
        <attribute name="title" type="string" />
    </complexType>
    <element name="document" type="tns:DocumentType"/>
</schema>

This tells JAXB to use the rd.DocumentEx class for the DocumentType complex type. Now a DocumentType class is not created, and the createDocument method on the ObjectFactory looks like this:

@XmlElementDecl(namespace = "rd.test", name = "document")
public JAXBElement<DocumentEx> createDocument(DocumentEx value) {
    return new JAXBElement<DocumentEx>(_Document_QNAME, DocumentEx.class, null, value);
}

From section 7.7.1 of the JAXB 2.2 specification:

• implClass if specified, is the name of the implementation class for className and must include the complete package name. Note that this customization only impacts the return value for className’s factory method. This customization is ignored when new is used to create instances of a schema-derived Value class.

• ref if specified, is the name of the value class that is provided outside the schema compiler. This customization causes a schema compiler to refer to this external class, as opposed to generate a definition. It must include the complete package name. This attribute is mutually exclusive with the className attribute and the implClass attribute.

Community
  • 1
  • 1
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thanks you for your answer! Unfortunately you misunderstood my intention (and I see, that I didn't made it clear enough). As you point out, using the 'ref' directive expects my class DocumentEx to be annotated for JAXB, which isn't the case as it is just an specialization of the auto-generated DocumentType-Class. According to your excerpt from the specification it seems to me, that maybe the rootElement is instantiated differently (using 'new' which ignores the value class) than inner elements, but if this is correct, why that?! (Edited question to point out better my intention) – raindrop Jan 21 '15 at 17:06