java - 使用 EclipseLink JAXB (MOXy) 解码 XML 时出现 DescriptorException "Missing class indicator field from database row"异常

标签 java jaxb eclipselink moxy

我在使用 Moxy 编码(marshal)/取消编码(marshal) Salesforce 出站消息 XML 时遇到问题。我得到的异常(exception)是:

javax.xml.bind.JAXBException
 - with linked exception:
[Exception [EclipseLink-44] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class indicator field from database row [UnmarshalRecord()].
Descriptor: XMLDescriptor(service.salesforce.model.SObject --> [])]

我的类(class)是:

@XmlSeeAlso({Account.class, Opportunity.class})
@XmlDiscriminatorNode("@type")
public abstract class SObject {
  public abstract String getId();
  public abstract void setId(String id);
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlDiscriminatorValue("sf:Opportunity")
public class Opportunity extends SObject {

  @XmlElement(name = "Id", namespace = "urn:sobject.enterprise.soap.sforce.com")
  private String id;

  @XmlElement(name = "AccountId", namespace = "urn:sobject.enterprise.soap.sforce.com")
  private String accountId;

  @XmlElement(name = "StageName", namespace = "urn:sobject.enterprise.soap.sforce.com")
  private String stageName;

  @XmlElement(name = "Agreement_Date_Signed__c", namespace = "urn:sobject.enterprise.soap.sforce.com")
  private Date agreementDateSigned;

  @XmlElement(name = "Agreement_Date_Start__c", namespace = "urn:sobject.enterprise.soap.sforce.com")
  private Date agreementDateStart;

  @XmlElement(name = "Payment_Method__c", namespace = "urn:sobject.enterprise.soap.sforce.com")
  private String paymentMethod;

  // getters and setters...
}

我尝试解码的 XML 是:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:out="http://soap.sforce.com/2005/09/outbound" xmlns:urn="urn:sobject.enterprise.soap.sforce.com">
   <soapenv:Header/>
   <soapenv:Body>
      <out:notifications>
         <out:OrganizationId>123456789123456789</out:OrganizationId>
         <out:ActionId>123456789123456789</out:ActionId>
         <out:SessionId>sessId</out:SessionId>
         <out:EnterpriseUrl>http://www.enterpriseexample.com</out:EnterpriseUrl>
         <out:PartnerUrl>http://www.partnerexample.com</out:PartnerUrl>
         <out:Notification>
            <out:Id>987654321987654321</out:Id>
            <out:sObject xsi:type="sf:Opportunity" xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
               <urn:Id>121212121212121212</urn:Id>
               <urn:AccountId>121212121212121212</urn:AccountId>
               <urn:Agreement_Date_Signed__c>2012-01-01T08:34:56Z</urn:Agreement_Date_Signed__c>
               <urn:Agreement_Date_Start__c>2012-02-01</urn:Agreement_Date_Start__c>
               <urn:StageName>Booking</urn:StageName>
            </out:sObject>
         </out:Notification>
      </out:notifications>
   </soapenv:Body>
</soapenv:Envelope>

有什么想法吗?

最佳答案

注意:我是EclipseLink JAXB (MOXy) JAXB 2 (JSR-222) 的领导者和成员专家组。

由于您使用 xsi:type 属性作为鉴别器节点作为继承指示符,因此我建议使用标准 JAXB 机制,而不是 MOXy 的 @XmlDecriminatorNode/@XmlDecriminatorValue 扩展。

SObject

package forum987537;

import javax.xml.bind.annotation.XmlSeeAlso;

@XmlSeeAlso({Account.class, Opportunity.class})
public abstract class SObject {
  public abstract String getId();
  public abstract void setId(String id);
}

机会

package forum987537;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="Opportunity")
public class Opportunity extends SObject {

    private String id;

    @Override
    public String getId() {
        return id;
    }

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

}

通知

package forum987537;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Notification", namespace="http://soap.sforce.com/2005/09/outbound")
public class Notification {

    private SObject sObject;

    @XmlElement(namespace="http://soap.sforce.com/2005/09/outbound")
    public SObject getsObject() {
        return sObject;
    }

    public void setsObject(SObject sObject) {
        this.sObject = sObject;
    }

}

包信息

@XmlSchema(
    namespace="urn:sobject.enterprise.soap.sforce.com", 
    elementFormDefault=XmlNsForm.QUALIFIED,
    xmlns={
        @XmlNs(prefix="out", namespaceURI = "http://soap.sforce.com/2005/09/outbound"),
        @XmlNs(prefix="sf", namespaceURI = "urn:sobject.enterprise.soap.sforce.com"),
    })
package forum987537;

import javax.xml.bind.annotation.*;

演示

package forum987537;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

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

        Notification notification = new Notification();
        Opportunity opportunity = new Opportunity();
        opportunity.setId("ABC123");
        notification.setsObject(opportunity);

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

}

输出

<?xml version="1.0" encoding="UTF-8"?>
<out:Notification xmlns:sf="urn:sobject.enterprise.soap.sforce.com" xmlns:out="http://soap.sforce.com/2005/09/outbound">
   <out:sObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="sf:Opportunity">
      <sf:id>ABC123</sf:id>
   </out:sObject>
</out:Notification>

了解更多信息

关于java - 使用 EclipseLink JAXB (MOXy) 解码 XML 时出现 DescriptorException "Missing class indicator field from database row"异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9875378/

相关文章:

mysql - 将部署在 Glassfish 上的 JSF Web 应用程序连接到本地 MySQL 数据库

java - 如何让从 WSDL 生成的 Java 类实现接口(interface)

java - 类层次结构的 JAXB 注释

from子句中的jpa eclipselink子查询

java - HQL - 更新查询不起作用

xml - xsd -xml 正则表达式验证不适用于使用 JAXB 的我

java - EclipseLink - 并发异常 - signalAttemptedBeforeWait

应用程序启动方法中的Javafx错误异常未指定 Controller

java - 如何在java中检查匹配模式

java - 建议非常快(微秒)的 java 日志记录?