java - JAXB: Can't unmarshal JAXBElement<?>, getting ElementNSImpl instead -
related jaxb: how implement jaxb-compatible variant wrapper class?, tried use jaxbelement
represent "variant" or "any-type".
marshalling went fine, during unmarshalling, jaxb
tries assign elementnsimpl
jaxbelement
field.
test code
(copy+paste+run)
import static java.lang.system.*; import java.io.*; import java.util.*; import javax.xml.bind.*; import javax.xml.bind.annotation.*; import javax.xml.namespace.*; import org.junit.*; public class _jaxbelementproblem { @xmlrootelement @xmltype @xmlaccessortype(xmlaccesstype.none) static class myobject { public static final qname variant_name = new qname("qqq"); @xmlanyelement(lax = true) private jaxbelement<object> single = null; @xmlelementwrapper(name = "elements") @xmlanyelement(lax = true) final list<jaxbelement<object>> elements = new linkedlist<jaxbelement<object>>(); @suppresswarnings("unused") private myobject() { } public myobject(object o) { single = new jaxbelement<object>(variant_name, object.class, o); } public object getsingle() { return single.getvalue(); } public list<object> getelements() { list<object> ret = new linkedlist<object>(); (jaxbelement<?> e : elements) { ret.add(e.getvalue()); } return ret; } @override public string tostring() { return "myobject (single=" + single.getvalue() + "; elements: " + getelements() + ")"; } } private static final jaxbcontext c; private static final marshaller m; private static final unmarshaller u; static { try { c = jaxbcontext.newinstance(myobject.class); m = c.createmarshaller(); u = c.createunmarshaller(); m.setproperty(marshaller.jaxb_formatted_output, boolean.true); } catch (jaxbexception ex) { throw new error(ex); } } private void testmarshalunmarshal(object root) throws exception { out.println("\nmarshalled - - - - - - - - - - - - - - - - - - - -"); stringwriter sw = new stringwriter(); m.marshal(root, sw); out.println(sw.tostring() + "\n"); out.println("\nunmarshalled - - - - - - - - - - - - - - - - - - - -"); object reunmarshalled = u.unmarshal(new stringreader(sw.tostring())); out.println(reunmarshalled + "\n"); } @before public void before() { out.println("\n= = = = = = = = = = = = = = = = = = = ="); } @test public void test1() throws exception { myobject root = new myobject(integer.valueof(12345)); testmarshalunmarshal(root); } @test public void test2() throws exception { myobject sub = new myobject(integer.valueof(12345)); myobject root = new myobject(sub); testmarshalunmarshal(root); } @test public void test3() throws exception { myobject osub = new myobject(integer.valueof(12345)); list<myobject> osubs = arrays.aslist(new myobject("sub-1"), new myobject("sub-2"), new myobject("sub-3")); myobject root = new myobject(osub); (myobject o : osubs) { root.elements.add(new jaxbelement<object>(myobject.variant_name, object.class, o)); } testmarshalunmarshal(root); } }
test output
(as can see, unmarshalling doesn't take place)
= = = = = = = = = = = = = = = = = = = = marshalled - - - - - - - - - - - - - - - - - - - - <?xml version="1.0" encoding="utf-8" standalone="yes"?> <myobject> <qqq xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/xmlschema" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">12345</qqq> <elements/> </myobject> unmarshalled - - - - - - - - - - - - - - - - - - - - = = = = = = = = = = = = = = = = = = = = marshalled - - - - - - - - - - - - - - - - - - - - <?xml version="1.0" encoding="utf-8" standalone="yes"?> <myobject> <qqq xsi:type="myobject" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <qqq xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/xmlschema">12345</qqq> <elements/> </qqq> <elements/> </myobject> unmarshalled - - - - - - - - - - - - - - - - - - - - = = = = = = = = = = = = = = = = = = = = marshalled - - - - - - - - - - - - - - - - - - - - <?xml version="1.0" encoding="utf-8" standalone="yes"?> <myobject> <qqq xsi:type="myobject" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <qqq xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/xmlschema">12345</qqq> <elements/> </qqq> <elements> <qqq xsi:type="myobject" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <qqq xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/xmlschema">sub-1</qqq> <elements/> </qqq> <qqq xsi:type="myobject" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <qqq xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/xmlschema">sub-2</qqq> <elements/> </qqq> <qqq xsi:type="myobject" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <qqq xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/xmlschema">sub-3</qqq> <elements/> </qqq> </elements> </myobject> unmarshalled - - - - - - - - - - - - - - - - - - - -
unmarshalling exceptions
java.lang.illegalargumentexception: can not set javax.xml.bind.jaxbelement field my._jaxbelementproblem$myobject.single com.sun.org.apache.xerces.internal.dom.elementnsimpl @ sun.reflect.unsafefieldaccessorimpl.throwsetillegalargumentexception(unsafefieldaccessorimpl.java:146) @ sun.reflect.unsafefieldaccessorimpl.throwsetillegalargumentexception(unsafefieldaccessorimpl.java:150) @ sun.reflect.unsafeobjectfieldaccessorimpl.set(unsafeobjectfieldaccessorimpl.java:63) @ java.lang.reflect.field.set(field.java:657) @ com.sun.xml.internal.bind.v2.runtime.reflect.accessor$fieldreflection.set(accessor.java:234) @ com.sun.xml.internal.bind.v2.runtime.reflect.accessor.receive(accessor.java:160) @ com.sun.xml.internal.bind.v2.runtime.unmarshaller.unmarshallingcontext.endelement(unmarshallingcontext.java:507) @ com.sun.xml.internal.bind.v2.runtime.unmarshaller.saxconnector.endelement(saxconnector.java:145) @ com.sun.org.apache.xerces.internal.parsers.abstractsaxparser.endelement(abstractsaxparser.java:601) @ com.sun.org.apache.xerces.internal.impl.xmldocumentfragmentscannerimpl.scanendelement(xmldocumentfragmentscannerimpl.java:1782) @ com.sun.org.apache.xerces.internal.impl.xmldocumentfragmentscannerimpl$fragmentcontentdriver.next(xmldocumentfragmentscannerimpl.java:2938) @ com.sun.org.apache.xerces.internal.impl.xmldocumentscannerimpl.next(xmldocumentscannerimpl.java:648) @ com.sun.org.apache.xerces.internal.impl.xmlnsdocumentscannerimpl.next(xmlnsdocumentscannerimpl.java:140) @ com.sun.org.apache.xerces.internal.impl.xmldocumentfragmentscannerimpl.scandocument(xmldocumentfragmentscannerimpl.java:511) @ com.sun.org.apache.xerces.internal.parsers.xml11configuration.parse(xml11configuration.java:808) @ com.sun.org.apache.xerces.internal.parsers.xml11configuration.parse(xml11configuration.java:737) @ com.sun.org.apache.xerces.internal.parsers.xmlparser.parse(xmlparser.java:119) @ com.sun.org.apache.xerces.internal.parsers.abstractsaxparser.parse(abstractsaxparser.java:1205) @ com.sun.org.apache.xerces.internal.jaxp.saxparserimpl$jaxpsaxparser.parse(saxparserimpl.java:522) @ com.sun.xml.internal.bind.v2.runtime.unmarshaller.unmarshallerimpl.unmarshal0(unmarshallerimpl.java:200) @ com.sun.xml.internal.bind.v2.runtime.unmarshaller.unmarshallerimpl.unmarshal(unmarshallerimpl.java:173) @ javax.xml.bind.helpers.abstractunmarshallerimpl.unmarshal(abstractunmarshallerimpl.java:137) @ javax.xml.bind.helpers.abstractunmarshallerimpl.unmarshal(abstractunmarshallerimpl.java:194) @ my._jaxbelementproblem.testmarshalunmarshal(_jaxbelementproblem.java:84) @ my._jaxbelementproblem.test3(_jaxbelementproblem.java:119)
running example:
(hint: jaxbhelper utils-apl-derived, short forms of unmarshalling , marshalling routines)
import static org.junit.assert.assertequals; import java.util.arrays; import java.util.list; import javax.xml.bind.annotation.xmlaccesstype; import javax.xml.bind.annotation.xmlaccessortype; import javax.xml.bind.annotation.xmlelement; import javax.xml.bind.annotation.xmlelements; import javax.xml.bind.annotation.xmlrootelement; import javax.xml.bind.annotation.xmltype; import org.junit.test; import org.omnaest.utils.xml.jaxbxmlhelper; public class jaxbanyelementtest { @xmltype @xmlaccessortype(xmlaccesstype.field) protected static class testsubentity { /* ********************************************** variables ********************************************** */ @xmlelement private string fieldstring = null; @xmlelement private int fieldinteger = -1; /* ********************************************** methods ********************************************** */ /** * @see testsubentity */ public testsubentity() { super(); } /** * @see testsubentity * @param fieldstring * @param fieldinteger */ public testsubentity( string fieldstring, int fieldinteger ) { super(); this.fieldstring = fieldstring; this.fieldinteger = fieldinteger; } /** * @return fieldstring */ public string getfieldstring() { return this.fieldstring; } /** * @param fieldstring * fieldstring set */ public void setfieldstring( string fieldstring ) { this.fieldstring = fieldstring; } /** * @return fieldinteger */ public int getfieldinteger() { return this.fieldinteger; } /** * @param fieldinteger * fieldinteger set */ public void setfieldinteger( int fieldinteger ) { this.fieldinteger = fieldinteger; } @override public int hashcode() { final int prime = 31; int result = 1; result = prime * result + this.fieldinteger; result = prime * result + ( ( this.fieldstring == null ) ? 0 : this.fieldstring.hashcode() ); return result; } @override public boolean equals( object obj ) { if ( == obj ) { return true; } if ( obj == null ) { return false; } if ( !( obj instanceof testsubentity ) ) { return false; } testsubentity other = (testsubentity) obj; if ( this.fieldinteger != other.fieldinteger ) { return false; } if ( this.fieldstring == null ) { if ( other.fieldstring != null ) { return false; } } else if ( !this.fieldstring.equals( other.fieldstring ) ) { return false; } return true; } } @xmlrootelement @xmlaccessortype(xmlaccesstype.field) protected static class testentity { @xmlelements({ @xmlelement(name = "int", type = integer.class), @xmlelement(name = "string", type = string.class), @xmlelement(name = "testsubentity", type = testsubentity.class), @xmlelement(name = "other") }) private list<object> anyelementlist = null; /** * @return anyelementlist */ public list<object> getanyelementlist() { return this.anyelementlist; } /** * @param anyelementlist * anyelementlist set */ public void setanyelementlist( list<object> anyelementlist ) { this.anyelementlist = anyelementlist; } /* (non-javadoc) * @see java.lang.object#hashcode() */ @override public int hashcode() { final int prime = 31; int result = 1; result = prime * result + ( ( this.anyelementlist == null ) ? 0 : this.anyelementlist.hashcode() ); return result; } /* (non-javadoc) * @see java.lang.object#equals(java.lang.object) */ @override public boolean equals( object obj ) { if ( == obj ) { return true; } if ( obj == null ) { return false; } if ( !( obj instanceof testentity ) ) { return false; } testentity other = (testentity) obj; if ( this.anyelementlist == null ) { if ( other.anyelementlist != null ) { return false; } } else if ( !this.anyelementlist.equals( other.anyelementlist ) ) { return false; } return true; } } @suppresswarnings("cast") @test public void test() { // final testentity testentity = new testentity(); // final list<object> anyelementlist = arrays.aslist( (object) "a", integer.valueof( 1 ), boolean.valueof( true ), new testsubentity( "field1", 1 ) ); testentity.setanyelementlist( anyelementlist ); // final string objectasxml = jaxbxmlhelper.storeobjectasxml( testentity ); system.out.println( objectasxml ); // final testentity objectfromxml = jaxbxmlhelper.loadobjectfromxml( objectasxml, testentity.class ); assertequals( testentity, objectfromxml ); } }
output:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <testentity> <string>a</string> <int>1</int> <other xsi:type="xs:boolean" xmlns:xs="http://www.w3.org/2001/xmlschema" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">true</other> <testsubentity> <fieldstring>field1</fieldstring> <fieldinteger>1</fieldinteger> </testsubentity> </testentity>
Comments
Post a Comment