开发者

Inconsistent unmarshalling with MOXy

I'm using MOXy to unmarshal a relatively simple XML document, but I'm getting inconsistent behavior. The document consists of two elements with basic information (a name and date) followed by a list of records. The problem is that the name and date are unmarshalling correctly every time, however I frequently don't get any records (this has been validated with a unit test repeatedly using the same static data yet passing and failing with no observed predictability). All logging and assertions validate that everything looks good except that sometimes I get all 6 records, and sometimes I get 0 (never any other numbers). This inconsistent behavior makes absolutely no sense to me, any ideas? Am I missing an annotation or something which would ensure proper unmarshalling?

I have tried a few different versions of the eclipselink library, all with the same results (currently I'm loading 2.2.0 from the eclipselink maven repository).

Report Class

package com.company.report_parser.model;

import org.eclipse.persistence.oxm.annotations.XmlPath;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@XmlRootElement(name="feedback")
public class SpecificAggregateReport extends AggregateReport {
    @XmlPath("submitter/org_name/text()")
    protected void setPartnerName(String partnerName) {
        super.setPartnerName(partnerName);
    }

    @XmlPath("date_range/end/text()")
    protected void setDate(String date) {
        super.setDate(date);
    }

    public List<AggregateRecord> getRecords() {
        return super.getRecords();
    }
    @XmlPath("authstats/record")
    @XmlElement(type=SpecificAggregateRecord.class) // This is the element class which implements the AggregateRecord Interface used in the List
    protected void setRecords(List<AggregateRecord> records) {
        super.setRecords(records);
    }
}

Record Class package com.company.report_parser.model;

import org.eclipse.persistence.oxm.annotations.XmlPath;

public class SpecificAggregateRecord extends AggregateRecord {
    @XmlPath("row/@source_ip")
    protected void setSourceIp(String sourceIp) {
        super.setSourceIp(sourceIp);
    }

    @XmlPath("row/@count")
    protected void setCount(String count) {
        super.setCount(count);
    }

    @XmlPath("identities/@envelope_from")
    protected void setSmtpFrom(String envelope_from) {
        super.setSmtpFrom(envelope_from);
    }

    @XmlPath("identities/@header_from")
    protected void setHeaderFromDomain(String header_from) {
        super.setHeaderFromDomain(header_from);
    }

    @XmlPath("auth_results/dkim/@result")
    protected void setDkimResult(String result) {
        super.setDkimResult(result);
    }

    @XmlPath("auth_results/dkim/@d")
    protected void setDkimDomain(String d) {
        super.setDkimDomain(d);
    }

    @XmlPath("auth_results/spf/@result")
    protected void setSpfResult(String result) {
        super.setSpfResult(result);
    }
}

Sample Data

<开发者_C百科;?xml version="1.0" encoding="UTF-8" ?>
<feedback>
  <submitter>
    <org_name>specific</org_name>
    <email>support@specific.com</email>
  </submitter>
  <date_range>
    <begin>20110511</begin>
    <end>20110511</end>
  </date_range>
  <report_id>682417472261065178</report_id>
  <authstats>
    <record>
      <row source_ip="184.106.220.108" count="8" policy_domain="test.net" policy="none" action_taken="none" />
      <identities envelope_from="test.net" header_from="test.net" />
      <auth_results>
        <dkim result="neutral" d="test.net" />
        <spf domain="test.net" identity="spf_envelope_from" result="pass" />
      </auth_results>
    </record>
    <record>
      <row source_ip="50.56.76.41" count="6" policy_domain="test.net" policy="none" action_taken="none" />
      <identities envelope_from="test.net" header_from="test.net" />
      <auth_results>
        <dkim result="neutral" d="test.net" />
        <spf domain="test.net" identity="spf_envelope_from" result="softfail" />
      </auth_results>
    </record>
    <record>
      <row source_ip="50.56.76.41" count="6" policy_domain="test.net" policy="none" action_taken="none" />
      <identities envelope_from="test.net" header_from="test.net" />
      <auth_results>
        <dkim result="none" d="" />
        <spf domain="test.net" identity="spf_envelope_from" result="softfail" />
      </auth_results>
    </record>
    <record>
      <row source_ip="184.106.220.108" count="6" policy_domain="test.net" policy="none" action_taken="none" />
      <identities envelope_from="test.net" header_from="test.net" />
      <auth_results>
        <dkim result="pass" d="test.net" />
        <spf domain="test.net" identity="spf_envelope_from" result="pass" />
      </auth_results>
    </record>
    <record>
      <row source_ip="50.56.76.41" count="8" policy_domain="test.net" policy="none" action_taken="none" />
      <identities envelope_from="test.net" header_from="test.net" />
      <auth_results>
        <dkim result="pass" d="test.net" />
        <spf domain="test.net" identity="spf_envelope_from" result="softfail" />
      </auth_results>
    </record>
    <record>
      <row source_ip="184.106.220.108" count="6" policy_domain="test.net" policy="none" action_taken="none" />
      <identities envelope_from="test.net" header_from="test.net" />
      <auth_results>
        <dkim result="none" d="" />
        <spf domain="test.net" identity="spf_envelope_from" result="pass" />
      </auth_results>
    </record>
  </authstats>
</feedback>


Issue

The inconsistent behaviour is due to properties being overridden in the child class. MOXy considers the properties in both the parent class and child class to be mapped and depending on the order processed you are seeing one behaviour or the other.

Solution #1

You need to tell MOXy that the parent properties are not mapped, you can do this by specifying @XmlAccessorType(XmlAccessType.NONE) on the AggregateRecord and AggregateReport classes:

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;

@XmlAccessorType(XmlAccessType.NONE)
public class AggregateRecord {
   ...
}

Then specifying @XmlAccessorType(XmlAccessType.PROPERTY) on the SpecificAggregateRecord and SpecificAggregateReport classes:

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;

@XmlAccessorType(XmlAccessType.PROPERTY)
public class SpecificAggregateRecord extends AggregateRecord {

Solution #2

If you are overriding the accessors on the subclass solely for the purpose of applying a mapping you may want to consider using MOXy's external mapping file instead. Below is an example:

  • http://bdoughan.blogspot.com/2010/12/extending-jaxb-representing-annotations.html

Please let me know if you are interested in exploring this option.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜