Tron
Tron

Reputation: 59

Partial Unmarshalling with JAXB gives IllegalAnnotationexceptions

when partially unmarshalling an XML, I am receiving the following error message:

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 6 counts of IllegalAnnotationExceptions
Property id is present but not specified in @XmlType.propOrder
this problem is related to the following location:
    at public java.lang.String xmlFields.Example.getId()
    at xmlFields.Example
Property text is present but not specified in @XmlType.propOrder
this problem is related to the following location:
    at public java.lang.String xmlFields.Example.getText()
    at xmlFields.Example
Property type is present but not specified in @XmlType.propOrder
this problem is related to the following location:
    at public java.lang.String xmlFields.Example.getType()
    at xmlFields.Example
Property ID appears in @XmlType.propOrder, but no such property exists. Maybe you meant id?
this problem is related to the following location:
    at xmlFields.Example
Property Text appears in @XmlType.propOrder, but no such property exists. Maybe you meant text?
this problem is related to the following location:
    at xmlFields.Example
Property Type appears in @XmlType.propOrder, but no such property exists. Maybe you meant type?
this problem is related to the following location:
    at xmlFields.Example

at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:451)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:283)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1148)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:445)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at extractFromXML.ReadFromXML.convertToJavaObject(ReadFromXML.java:72)
at extractFromXML.ReadFromXML.main(ReadFromXML.java:97)

I have the follwing implementation (extracting only a part of the xml seem to work):

@XmlRootElement
@XmlType(propOrder={"ID", "Text", "Type"})
public class Example {

private String id; 
private String text;

public Example() {
    super();
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getText() {
    return text;
}

public void setText(String text) {
    this.text = text;
}

public String getType() {
    return type;
}

public void setType(String type) {
    this.type = type;
}

private String type;

}

And this is the part of the xml file:

......<ExampleOptions><Example> <ID>ETZH8</ID> <Text>hello</Text> <Type>VAR</Type> </Example></ExampleOptions>.......

Any ideas?

Thanks

UPDATE #1

I adapted the suggestions by Blaise, but still getting only null values:

Example [id=null, text=null, type=null, getId()=null, getText()=null, getType()=null, getClass()=class xmlFields.Example, hashCode()=18467372, toString()=xmlFields.Example@119ca2c]

UPDATE #2

This is my current code:

@XmlRootElement
@XmlType(propOrder={"id", "text", "type"})
public class Example {

private String id; 
private String text;
private String type;

public Example() {
super();
}

@XmlElement(name="ID")
public String getId() {
return id;
 }

public void setId(String id) {
this.id = id;
}

@XmlElement(name="Text")
public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

@XmlElement(name="Type")
public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

}

I can't publish the whole XML. It is a nested XML file.

UPDATE #3

The problem is, I only try to extract a part of my xml. Therefore, I have the following main function:

public static void main(String[] args) throws Exception {
try {
    XMLInputFactory xif = XMLInputFactory.newFactory();
    StreamSource xml = new StreamSource(POI_XML);
    XMLStreamReader xsr = xif.createXMLStreamReader(xml);
    xsr.nextTag();

    while(xsr.hasNext()) {
        if(xsr.isStartElement() && xsr.getLocalName().equals("Example")) {
            break;
        }
        xsr.next();
    }

    JAXBElement<Example> jb;
    try {
        JAXBContext context = JAXBContext.newInstance(Example.class);

        Unmarshaller um = context.createUnmarshaller();
        jb = um.unmarshal(xsr, Example.class);
        xsr.close();

        Example stations = jb.getValue();
        System.out.println(stations.toString());
    } catch (JAXBException e) {
        e.printStackTrace();
    }
} catch (FactoryConfigurationError e) {
    e.printStackTrace();
} catch (XMLStreamException e) {
    e.printStackTrace();
}

}

Moreover, I just tried to extract just an example of one deep path in the nested XML. It looks more than:

<ExampleOptions><Example> <ID>ETZH8</ID> <Text>hello</Text> <Type>VAR</Type> </Example></ExampleOptions><ConnectionCount>1</ConnectionCount><Info>abc</Info>.....

UPDATE #4

I just checked the marshalling example with the following error message:

Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; systemId: file:///D:/proj/ConvertXMLToPostgres/input2.xml; lineNumber: 1; columnNumber: 39; Vorzeitiges Dateiende.]

Upvotes: 1

Views: 2881

Answers (1)

bdoughan
bdoughan

Reputation: 149047

The propOrder is based on the field/property names and not the elements that they are mapped to. You just need to change your propOrder:

@XmlType(propOrder={"id", "text", "type"})

The stack trace also points you in this direction:

Property ID appears in @XmlType.propOrder, but no such property exists. Maybe you meant id?
this problem is related to the following location:
    at xmlFields.Example
Property Text appears in @XmlType.propOrder, but no such property exists. Maybe you meant text?
this problem is related to the following location:
    at xmlFields.Example
Property Type appears in @XmlType.propOrder, but no such property exists. Maybe you meant type?
this problem is related to the following location:
    at xmlFields.Example

For More Information

I have written more about this on my blog:


UPDATE #1

Thanks. I changed the code, but I am getting null values.

The element names in your XML don't match the default names that JAXB derives from your property names, so you will need to override it with an @XmlElement annotation.

@XmlElement("ID")
public String getId() {
    return id;
}

Debugging Tip:

When you run into an issue when unmarshalling, try populating your object model and marshalling it to XML to see what XML is expected.


UPDATE #2

Demo

When I run the following against your updated Example class everything works for me. Does it work for you as well?

import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Example.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StreamSource source = new StreamSource("input.xml");
        JAXBElement<Example> result =  unmarshaller.unmarshal(source, Example.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(result, System.out);
    }

}

Input/Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Example>
    <ID>ETZH8</ID>
    <Text>hello</Text>
    <Type>VAR</Type>
</Example>

UPDATE #3

When I run the Java code from your UPDATE #3 against the model from your UPDATE #2 with the following XML everything works:

<ExampleOptions><Example> <ID>ETZH8</ID> <Text>hello</Text> <Type>VAR</Type> </Example></ExampleOptions>

Can you update your code in UPDATE #3 to include System.out.println(xsr.getNamespaceURI()); to see if there are any namespaces in play?

        while(xsr.hasNext()) {
            if(xsr.isStartElement() && xsr.getLocalName().equals("Example")) {
                System.out.println(xsr.getNamespaceURI());
                break;
            }
            xsr.next();
        }

Upvotes: 1

Related Questions