JAXB只有编组/解组根节点

时间:2009-09-25 15:39:51

标签: java jaxb ejb-3.0

我是JAXB的新手。我想要做的就是,给定一个现有的xml字符串封送它,然后在ejb中返回它。问题是以下代码似乎只适用于根节点,而不是子节点。我希望它适用于整个事情。如果有任何帮助,我没有改变通过提供方案生成的任何代码。任何指针都会有所帮助,谢谢。

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import org.netbeans.j2ee.wsdl.test.newwsdl.NewWSDLPortType;
import org.netbeans.xml.schema.newxmlschema.*;

@WebService(serviceName = "newWSDLService", portName = "newWSDLPort", endpointInterface = "org.netbeans.j2ee.wsdl.test.newwsdl.NewWSDLPortType", targetNamespace = "http://j2ee.netbeans.org/wsdl/test/newWSDL", wsdlLocation = "META-INF/wsdl/NewWebServiceFromWSDL/newWSDLWrapper.wsdl")
@Stateless
public class NewWebServiceFromWSDL implements NewWSDLPortType {

    public Root newWSDLOperation() {
        String xml = 
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        +"<ns0:root  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'"
        +"   xmlns:ns0='http://xml.netbeans.org/schema/newXmlSchema'"
        +"   xsi:schemaLocation='http://xml.netbeans.org/schema/newXmlSchema newXmlSchema.xsd'>"
        +"    <ns0:node>"
        +"        <ns0:name>asdf</ns0:name>"
        +"        <ns0:value>asdf</ns0:value>"
        +"        <ns0:date>2009-01-01</ns0:date>"
        +"    </ns0:node>"
        +"    <ns0:node>"
        +"        <ns0:name>asdf</ns0:name>"
        +"        <ns0:value>asdf</ns0:value>"
        +"        <ns0:date>2009-01-01</ns0:date>"
        +"    </ns0:node>"
        +"    <ns0:node>"
        +"        <ns0:name>asdf</ns0:name>"
        +"        <ns0:value>asdf</ns0:value>"
        +"        <ns0:date>2009-01-01</ns0:date>"
        +"    </ns0:node>"
        +"</ns0:root>";
        Root root = null;
        try {
            root = jaxbUnmarshalFromString(xml);
        } catch (Throwable ex) {
            Logger.getLogger(NewWebServiceFromWSDL.class.getName()).log(Level.SEVERE, null, ex);
        }
        return root;
    }

    private Root jaxbUnmarshalFromString(String str) throws javax.xml.bind.JAXBException {
        Root ret = null;
        javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(Root.class.getPackage().getName());
        javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
        ret = (Root) ((JAXBElement)unmarshaller.unmarshal(new java.io.StringReader(str))).getValue();

        return ret;
    }

}

这是方案:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://xml.netbeans.org/schema/newXmlSchema"
    xmlns:tns="http://xml.netbeans.org/schema/newXmlSchema"
    elementFormDefault="qualified">
    <xsd:complexType name="root">
        <xsd:sequence>
            <xsd:element name="node" type="tns:node" maxOccurs="unbounded" minOccurs="0"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="node">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="value" type="xsd:string"/>
            <xsd:element name="date" type="xsd:date"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="root" type="tns:root"/>
</xsd:schema>

从方案生成的类:

package org.netbeans.xml.schema.newxmlschema;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    private final static QName _Root_QNAME = new QName("http://xml.netbeans.org/schema/newXmlSchema", "root");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.netbeans.xml.schema.newxmlschema
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link Root }
     * 
     */
    public Root createRoot() {
        return new Root();
    }

    /**
     * Create an instance of {@link Node }
     * 
     */
    public Node createNode() {
        return new Node();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Root }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://xml.netbeans.org/schema/newXmlSchema", name = "root")
    public JAXBElement<Root> createRoot(Root value) {
        return new JAXBElement<Root>(_Root_QNAME, Root.class, null, value);
    }

}


package org.netbeans.xml.schema.newxmlschema;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;


/**    
 * <p>Java class for root complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="root">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="node" type="{http://xml.netbeans.org/schema/newXmlSchema}node" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "root", propOrder = {
    "node"
})
public class Root {

    protected List<Node> node;

    /**
     * Gets the value of the node property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the node property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getNode().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link Node }
     * 
     * 
     */
    public List<Node> getNode() {
        if (node == null) {
            node = new ArrayList<Node>();
        }
        return this.node;
    }

}


package org.netbeans.xml.schema.newxmlschema;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;


/**
 * <p>Java class for node complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="node">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="date" type="{http://www.w3.org/2001/XMLSchema}date"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "node", propOrder = {
    "name",
    "value",
    "date"
})
public class Node {

    @XmlElement(required = true)
    protected String name;
    @XmlElement(required = true)
    protected String value;
    @XmlElement(required = true)
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar date;

    /**
     * Gets the value of the name property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the value of the name property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setName(String value) {
        this.name = value;
    }

    /**
     * Gets the value of the value property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getValue() {
        return value;
    }

    /**
     * Sets the value of the value property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setValue(String value) {
        this.value = value;
    }

    /**
     * Gets the value of the date property.
     * 
     * @return
     *     possible object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public XMLGregorianCalendar getDate() {
        return date;
    }

    /**
     * Sets the value of the date property.
     * 
     * @param value
     *     allowed object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public void setDate(XMLGregorianCalendar value) {
        this.date = value;
    }

}

和WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="newWSDL" targetNamespace="http://j2ee.netbeans.org/wsdl/test/newWSDL"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://j2ee.netbeans.org/wsdl/test/newWSDL" xmlns:ns="http://xml.netbeans.org/schema/newXmlSchema" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype">
    <types>
        <xsd:schema targetNamespace="http://j2ee.netbeans.org/wsdl/test/newWSDL">
            <xsd:import namespace="http://xml.netbeans.org/schema/newXmlSchema" schemaLocation="newXmlSchema.xsd"/>
        </xsd:schema>
    </types>
    <message name="newWSDLOperationRequest"/>
    <message name="newWSDLOperationResponse">
        <part name="part1" type="ns:root"/>
    </message>
    <portType name="newWSDLPortType">
        <operation name="newWSDLOperation">
            <input name="input1" message="tns:newWSDLOperationRequest"/>
            <output name="output1" message="tns:newWSDLOperationResponse"/>
        </operation>
    </portType>
    <plnk:partnerLinkType name="newWSDL">
        <plnk:role name="newWSDLPortTypeRole" portType="tns:newWSDLPortType"/>
    </plnk:partnerLinkType>
</definitions>

以下肥皂电话:

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Header/>
    <S:Body>
        <ns2:newWSDLOperation xmlns:ns2="http://j2ee.netbeans.org/wsdl/test/newWSDL" xmlns:ns3="http://xml.netbeans.org/schema/newXmlSchema"/>
    </S:Body>
</S:Envelope>

返回:

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns3:newWSDLOperationResponse xmlns:ns2="http://xml.netbeans.org/schema/newXmlSchema" xmlns:ns3="http://j2ee.netbeans.org/wsdl/test/newWSDL">
            <part1/>
        </ns3:newWSDLOperationResponse>
    </S:Body>
</S:Envelope>

2 个答案:

答案 0 :(得分:0)

您在编组后吞下例外。

try {
     root = jaxbUnmarshalFromString(xml);
} catch (Throwable ex) {
     // !!! Exception caught here and not rethrown
     Logger.getLogger(NewWebServiceFromWSDL.class.getName()).log(Level.SEVERE, null, ex);
}
return root; // !!!root is null here 

我的猜测是,当你返回root时,root为null。记录您的异常时检查日志。

答案 1 :(得分:0)

我刚刚遇到一个问题,JAXB unmarshaller返回一个空的根音符。事实证明,在使用PowerMockito运行JUnit测试时,我只获得空的根节点。我想知道幕后发生的事情是否阻止了“真正的”unmarshaller的运行。