1

I can't seem to get all the JAXB magic right with regard to the abstract super-class generated from a substitution group. I'm using the reference implementation of JAXB.

Here's the class hierarchy:

+ DatasourceAbstract
  +----- DatasourceQuery
  +------DatasourceStatic

Given that (as documented below) I have provided the class and all its subclasses to JAXBContext explicitly, it's a mystery to me as to why they are "not known".

If more information is needed, let me know. I provided everything I thought relevant, but didn't want to overload the post.

Error (somewhat edited for clarity):

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Invalid @XmlElementRef : Type "class com.escholar.reports.reportXML.DatasourceAbstract" or any of its subclasses are not known to this context.
this problem is related to the following location:
    at protected java.util.LinkedList com.escholar.reports.reportXML.Data.dataSourceSubstitutionGroupHead
    at com.escholar.reports.reportXML.Data
    at protected com.escholar.reports.reportXML.Data com.escholar.reports.reportXML.ReportJAXB.data
    at com.escholar.reports.reportXML.ReportJAXB
    at public com.escholar.reports.reportXML.ReportJAXB com.escholar.reports.reportXML.ObjectFactory.createReportResourceJAXB()
    at com.escholar.reports.reportXML.ObjectFactory

at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(Unknown Source)
    .....  Partially ellided stacktrace ............
at javax.xml.bind.JAXBContext.newInstance(Unknown Source)
at com.escholar.reports.utilities.reportsamples.ReportXMLGenerator.main(ReportXMLGenerator.java:69)

JAXBContext Creation

Here's where I create the JAXB Context (the line that triggers the above exception):

JAXBContext jc = 
    JAXBContext.newInstance(
        com.escholar.reports.reportXML.ObjectFactory.class, 
        com.escholar.reports.reportXML.DatasourceAbstract.class, 
        com.escholar.reports.reportXML.DatasourceStatic.class, 
        com.escholar.reports.reportXML.DatasourceQuery.class);

DatasourceAbstract class

And here's the class it's complaining about. Note that I also used @XmlSeeAlso to identify the subclasses.

package com.escholar.reports.jaxb;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "DatasourceAbstract")
@XmlSeeAlso({
    DatasourceStatic.class,
    DatasourceQuery.class
})
public abstract class DatasourceAbstract {

    @XmlAttribute(name = "Name")
    @XmlSchemaType(name = "anySimpleType")
    protected String name;

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }
}

Reference to DatasourceAbstract

Here's where DatasourceAbstract is referenced:

package com.escholar.reports.jaxb;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "dataSourceSubstitutionGroupHead"
})
@XmlRootElement(name = "Data")
public class Data {

    @XmlElementRef(name = "DataSourceSubstitutionGroupHead", type = JAXBElement.class)
    protected List<JAXBElement<?>> dataSourceSubstitutionGroupHead;

    public List<JAXBElement<?>> getDataSourceSubstitutionGroupHead() {
        if (dataSourceSubstitutionGroupHead == null) {
            dataSourceSubstitutionGroupHead = new ArrayList<JAXBElement<?>>();
        }
        return this.dataSourceSubstitutionGroupHead;
    }
}
DaBlick
  • 898
  • 9
  • 21

2 Answers2

0

When creating a JAXBContext on a model generated from an XML schema you should do it on the package name of the generated model and not the individual classes. This will help ensure that the JAXBContext is pulling in all the necessary classes.

JAXBContext jc = JAXBContext.newInstance("com.escholar.reports.reportXML");
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • First, thanks for the quick response Blaise. You are the clearcut "patron saint of JAXB newbies [and pros even]". I made that change but I still get the same problem. If you have any further suggestions (or need more info - I've surely not provided much) I'd be all ears. I know there are some package-level annotations. XJC does not seem to have generated any though, so there aren't any in mine. – DaBlick Feb 01 '13 at 23:00
  • @DaBlick - Your stack trace has the package `com.escholar.reports.reportXML`,but your question has the package `com.escholar.reports.jaxb`. Are there two models in play here? – bdoughan Feb 02 '13 at 01:35
  • Hmmm... I don't think so. I think the error there is in my stackoverflow post, not in the code. Basically I used xjc to generate the java classes and those all ended up in reports.jaxb. I accidentally included the original classes in my post but in the actual project there are no references to (nor definitions in) anything the com.escholar.reports.jaxb. I have confirmed this via an Eclipse textual search for the string "reports.jaxb". I can confirm that there is a definition for the class com.escholar.reports.reportXML in the project. – DaBlick Feb 04 '13 at 15:17
  • I can also confirm that `com.escholar.reports.jaxb` is not in the classpath nor build path. – DaBlick Feb 04 '13 at 15:23
  • @DaBlick - Is it possible to update your question with enough info so that I can try to recreate your error? – bdoughan Feb 04 '13 at 19:57
  • 1
    it turns out that adding an `@XmlRootElement` to `DatasourceAbstract` (and its subclasses) causes things to work. Now this isn't an ideal solution because `DatasourceAbstract` is abstract and thus, we should never see a `` tag. I'd be happy to zip/email you the package this is in, because I'd like to understand it. But since I'm back in business, it's not urgent. Don't want to abuse your very gracious willingness to help. – DaBlick Feb 04 '13 at 22:25
  • @DaBlick - You can email me at: `blaise.doughan` AT `gmail` DOT `com`. – bdoughan Feb 04 '13 at 22:32
  • Thanks as always. It actually isn't very easy for me to extract a compilable/executable example. The reason is because the JAXB models extend super classes and implement interfaces that are NOT in the JAXB model. While the JAXB classes are self-contained, their super-classes/interfaces are not and I think they ultimately bring almost every thing else in the project in via the dependence graph (imports). However, I will zip up as much as I can and email it to you. – DaBlick Feb 06 '13 at 14:55
  • Please know that I recognize this is not a suitable way to document a bug. But please remember, at this point in time, resolving this is not critical/necessary. If you feel that trying to divine the problem from a non-executable example is not the best use of your time, that's fine. I'm not "stuck" anymore and appreciate your gracious help. – DaBlick Feb 06 '13 at 14:58
0

I faced with the same problem and so I share my solution:

@XmlSeeAlso()

Because the lazy loading of sub class, it seams impossible for JAXB to use sub class at right time.

My base abstract class is FieldMapping and the inherited are FileFieldMapping and DatabaseFieldMapping (I omit implementation here for brevity).

@XmlRootElement(name = "fieldMapping")
@XmlSeeAlso({DatabaseFieldMapping.class, 
FileFieldMapping.class})
public abstract class FieldMapping {

}

@XmlRootElement(name = "fileFieldMapping")
public class FileFieldMapping extends FieldMapping {
}

@XmlRootElement(name = "databaseFieldMapping")
public class DatabaseFieldMapping extends 
FieldMapping 
{
}

You can find more here and here

Massimo
  • 137
  • 1
  • 4