JAXB unmarshal Collection (Set) -
i testing marshalling , unmarshalling following java objects:
framework class:
@xmlrootelement (name = "framework") @xmlaccessortype(xmlaccesstype.field) @entity public class framework implements comparable<framework>, serializable { private static final long serialversionuid = 1l; @xmltransient @id @generatedvalue(strategy = generationtype.auto) private long id; private string frameworkname; private string frameworkversion; private string frameworkdescription; @xmlelementwrapper(name = "framework-domains") private set<frameworkdomain> frameworkdomainlist = new hashset<>(); @xmlelementwrapper(name = "framework-comments") private set<comment> comments = new hashset<>();
(contains getters, setters , nuber of functions without additional annotation)
domain class:
@xmlrootelement(name = "domain") @xmlaccessortype(xmlaccesstype.field) @entity public class frameworkdomain implements comparable<frameworkdomain>, serializable { private static final long serialversionuid = 1l; @xmltransient @id @generatedvalue(strategy = generationtype.auto) private long id; private string domainname; private string domaindescription; @xmlelementwrapper(name = "domain-requirements") private set<requirement> domainrequirements = new hashset<>(); @xmlelementwrapper(name = "domain-comments") private set<comment> domaincomments = new hashset<>();
requirement class:
@xmlrootelement(name = "requirement") @xmlaccessortype(xmlaccesstype.field) @entity public class requirement implements comparable<requirement>, serializable { private static final long serialversionuid = 1l; @xmltransient @id @generatedvalue(strategy = generationtype.auto) private long id; private string requirementname; private string requirementdescription; private string requirementguidance; @xmlelementwrapper(name = "sub-requirements") private set<requirement> requirementsubrequirementlist = new hashset<>(); @xmlelementwrapper(name = "testing-procedures") private set<testingprocedure> requirementtestingprocedureslist = new hashset<>(); @xmlelementwrapper(name = "requirement-comments") private set<comment> comments = new hashset<>();
marshalling , unmarshaling code:
public static string exportframework(framework f) { java.io.stringwriter s = new java.io.stringwriter(); try { jaxbcontext jc = jaxbcontext.newinstance(framework.class); marshaller marshaller = jc.createmarshaller(); marshaller.setproperty(marshaller.jaxb_encoding, "utf-8"); marshaller.setproperty(marshaller.jaxb_formatted_output, true); marshaller.marshal(f, s); } catch (exception ex) { ex.printstacktrace(); } return s.tostring(); } public static framework importframework(java.io.inputstream xml) { intelicompliance.model.framework f = null; try { jaxbcontext jc = jaxbcontext.newinstance(framework.class); unmarshaller unmarshaller = jc.createunmarshaller(); f = (intelicompliance.model.framework) unmarshaller.unmarshal(xml); } catch (jaxbexception ex) { ex.printstacktrace(); } return f; }
when marshal object have created, generates following xml:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <framework> <frameworkname>pci dss</frameworkname> <frameworkversion>3.3</frameworkversion> <frameworkdescription>the payment card industry data security standard (pci dss) proprietary information security standard organizations handle branded credit cards major card schemes including visa, mastercard, american express, discover, , jcb.</frameworkdescription> <framework-domains> <frameworkdomainlist> <domainname>domain 1a</domainname> <domaindescription>build , maintain secure network , systems</domaindescription> <domain-requirements></domain-requirements> <domain-comments></domain-comments> </frameworkdomainlist> <frameworkdomainlist> <domainname>domain 2a</domainname> <domaindescription>protect cardholder data</domaindescription> <domain-requirements/> <domain-comments/> </frameworkdomainlist> <frameworkdomainlist> <domainname>domain 3a</domainname> <domaindescription>maintain vulnerability management program</domaindescription> <domain-requirements/> <domain-comments/> </frameworkdomainlist> <frameworkdomainlist> <domainname>domain 4a</domainname> <domaindescription>implement strong access control measures</domaindescription> <domain-requirements/> <domain-comments/> </frameworkdomainlist> <frameworkdomainlist> <domainname>domain 5a</domainname> <domaindescription>regularly monitor , test networks</domaindescription> <domain-requirements/> <domain-comments/> </frameworkdomainlist> <frameworkdomainlist> <domainname>domain 6a</domainname> <domaindescription>maintain information security policy</domaindescription> <domain-requirements/> <domain-comments/> </frameworkdomainlist> </framework-domains> <framework-comments/> </framework>
... expecting.
however, when try convert xml object, 1 of domains included in set - i.e. import (unmarshalling) process ignores xml nodes after first one.
does has idea why? or, doing wrong?
update have made progress changing:
private set<frameworkdomain> frameworkdomainlist = new hashset<>();
to:
private list<frameworkdomain> frameworkdomainlist = new linkedlist<>();
which imports children elements expected. however, prefer use set.
does jaxb treats set(s) different list(s)?
based on answer question :
what meant ensured every object not same return different hash.
your problem coming fact every object you're unmarshalling have same hashcode, hence set think every elements equals, , keep 1 (the last 1 jaxb processes, incidentally first one).
you should able confirm behavior adding hashset objects without ids, last 1 should kept.
it explain why list populated when you're switching linked list.
either use different hashcode method or marshall ids resolve problem.
keep in mind should override equals() method alongside hashcode() method, , ensure a.equals(b) , a.hashcode == b.hashcode yield same results.
Comments
Post a Comment