簡體   English   中英

@XmlAnyElement不會解組為特定的Java類型,而是在JAXBElement處停止

[英]@XmlAnyElement does not unmarshal into specific Java type, but stop at JAXBElement

為了學習如何使用@XmlAnyElement ,我創建了以下測試服務:

@WebService(serviceName = "TestServices")
@Stateless()
public class TestServices {
    @WebMethod(operationName = "testMethod")
    public ServiceResult testMethod() {
        ServiceResult result = new ServiceResult();

        result.addObject(new SimpleObj(1, 2));
        result.addObject(new SimpleObj(3, 4));

        return result;
    }
}

SimpleObj是具有2個int字段的簡單類。 下面是ServiceResult類的代碼:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SimpleObj.class})
public class ServiceResult {
    @XmlAnyElement(lax = true)
    private List<Object> body;

    public void addObject(Object objToAdd) {
        if (this.body == null)
            this.body = new ArrayList();

        this.body.add(objToAdd);
    }

    // Getters and Setters
}

為了使用上述服務,我使用以下Main類創建了一個appclient:

public class Main {
    @WebServiceRef(wsdlLocation = "META-INF/wsdl/localhost_8080/TestServices/TestServices.wsdl")
    private static TestServices_Service service;
    private static TestServices         port;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        port = service.getAdminServicesPort();
        ServiceResult result = port.testMethod();

        for (Object o : result.getAny()) {
            System.out.println("TEST: " + o);
        }
    }
}

根據文檔,使用@XmlAnyElement ,解組器會急切將此元素解組到JAXB對象。 但是,我觀察到的是JAXB僅將我的對象解析為JAXBElement而不是完全解析為SimpleObj

如果您能向我展示如何從ServiceResult獲取SimpleObj ,我將不勝感激。

更新

下面是SimpleObj類:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SimpleObj {
    private int a;
    private int b;

    public SimpleObj() {}

    public SimpleObj(int a, int b) {
        this.a = a;
        this.b = b;
    }

    // Getters and Setters
}

我無法重現您看到的問題。 下面是一些直接與JAXB交互的演示代碼。

import java.io.*;
import javax.xml.bind.*;

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StringReader xml = new StringReader("<serviceResult><simpleObj/><simpleObj/></serviceResult>");
        ServiceResult result = (ServiceResult) unmarshaller.unmarshal(xml);

        for(Object item : result.getBody()) {
            System.out.println(item.getClass());
        }
    }

}

運行演示代碼的輸出顯示,它是在@XmlAnyElement(lax=true)注釋的字段中的SimpleObj實例。

class forum27871349.SimpleObj
class forum27871349.SimpleObj

更新1

在旁注中,我閱讀了您在@XmlAnyElement上的博客文章,而且從未見過您必須在任何示例中都包含@XmlSeeAlso({SimpleObj.class})。

我不確定為什么我在示例中從未使用@XmlSeeAlso

但是,在我的情況下,如果我沒有這個,我會得到這樣的錯誤:***類或其任何超類都不為該上下文所知。 如果您還可以告訴我是否有一種方法可以讓消費者在不使用@XmlSeeAlso的情況下了解所有這些類,那就太好了

當您自己創建JAXBContext ,只需要包含您在@XmlSeeAlso批注中引用的所有內容, @XmlSeeAlso作為用來引導JAXBContext的類的一部分。

JAXBContext jc = JAXBContext.newInstance(ServiceResult.class, SimpleObj.class);

在您沒有直接訪問JAXBContext的JAX-WS(或JAX-RS)設置中,我建議像您一樣使用@XmlSeeAlso批注。


更新#2

關於@XmlAnyElement,我從文檔中認為,如果解組器無法將元素解組到JAXB對象或JAXBElement對象中,則至少會得到一個DOM節點。

當您使用@XmlAnyElement(lax=true)映射屬性時,將發生以下情況:

  1. 如果該元素對應於類的@XmlRootElement ,則您將獲得該類的實例。
  2. 如果該元素對應於ObjectFactory上一個類的@XmlElementDecl或另一個帶有@XmlRegistry注釋的類,那么您將獲得該類的實例,該實例包裝在JAXBElement的實例中。
  3. 如果JAXB在元素和類之間沒有關聯,則它將把它轉換為DOM Element

我將在下面舉例說明。

的ObjectFactory

import javax.xml.namespace.QName;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="simpleObjJAXBElement")
    public JAXBElement<SimpleObj> createSimpleObj(SimpleObj simpleObj) {
        return new JAXBElement<SimpleObj>(new QName("simpleObjJAXBElement"), SimpleObj.class, simpleObj);
    }

}

演示

import java.io.*;
import javax.xml.bind.*;

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StringReader xml = new StringReader("<serviceResult><simpleObj/><unmapped/><simpleObjJAXBElement/></serviceResult>");
        ServiceResult result = (ServiceResult) unmarshaller.unmarshal(xml);

        for(Object item : result.getBody()) {
            System.out.println(item.getClass());
        }
    }

}

產量

class forum27871349.SimpleObj
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl
class javax.xml.bind.JAXBElement

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM