@XmlAnyElement不会解组到特定的Java类型,而是停在JAXBElement

时间:2015-01-10 00:13:06

标签: java xml web-services jaxb xmlanyelement

要了解如何使用@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,unmarshaller会急切地将此元素解组为JAXB对象。但是,我观察到的是JAXB只将我的对象解析为JAXBElement而不是一直进入SimpleObj

如果您能告诉我如何从SimpleObj中获取ServiceResult,我将非常感激。

更新

以下是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
}

1 个答案:

答案 0 :(得分:1)

我无法重现您所看到的问题。下面是一些与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());
        }
    }

}

运行演示代码的输出显示,在SimpleObj注释的字段中是@XmlAnyElement(lax=true)的实例。

class forum27871349.SimpleObj
class forum27871349.SimpleObj

更新#1

  

在旁注中,我已经阅读了关于@XmlAnyElement和的博客文章   我从来没有见过你必须包含@XmlSeeAlso({SimpleObj.class})   你的任何一个例子。

我不确定为什么我从未在我的示例中使用@XmlSeeAlso

  

然而,在我的情况下,如果我没有这个,我会有错误   在这种情况下,可以说Class ***或者它的任何超类。   如果你能告诉我是否有办法让所有人成功,那就太棒了   不使用@XmlSeeAlso

的消费者已知的这些类

当您自己创建JAXBContext时,您只需要在@XmlSeeAlso注释中包含您引用的任何内容,作为用于引导JAXBContext的类的一部分。< / p>

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

在您无法直接访问JAXBContext的JAX-WS(或JAX-RS)设置中,我建议您使用@XmlSeeAlso注释,就像您所做的那样。


更新#2

  

关于@XmlAnyElement,从文档中,我想如果   unmarshaller无法将元素解组为JAXB对象或   JAXBElement对象,我至少会得到一个DOM节点。

当您使用@XmlAnyElement(lax=true)映射属性时,将发生以下情况:

  1. 如果元素对应于类的@XmlRootElement,那么您将获得该类的实例。
  2. 如果元素对应于@XmlElementDecl上的类的ObjectFactory或使用@XmlRegistry注释的另一个类,那么您将获得包含在{{的实例中的该类的实例1}}。
  3. 如果JAXB在元素和类之间没有关联,那么它会将它转换为DOM JAXBElement
  4. 我将在下面举例说明。

    <强>的ObjectFactory

    Element

    <强>演示

    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());
            }
        }
    
    }