tags:

views:

745

answers:

1

I am new to JAXB. All I want to do is, given an existing xml string marshal it, and return it in an ejb. The problem is the following code only seems to work for the root node, and not the children. I would like it to work for the whole thing. If it is any help, I have not altered any of the code generated by feeding in the scheme. Any pointers would be helpful, thanks.

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

}

Here is the scheme:

<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>

Classes Generated from scheme:

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"&gt;
 *       &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"&gt;
 *       &lt;sequence>
 *         &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/&gt;
 *         &lt;element name="value" type="{http://www.w3.org/2001/XMLSchema}string"/&gt;
 *         &lt;element name="date" type="{http://www.w3.org/2001/XMLSchema}date"/&gt;
 *       &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;
    }

}

And 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"&gt;
    <types>
        <xsd:schema targetNamespace="http://j2ee.netbeans.org/wsdl/test/newWSDL"&gt;
            <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>

The following soap call:

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

Returns:

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

You swallow the exception after marshalling.

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

My guess is that root is null when you return it. Check your logs as your exception is logged.

Superfilin
Nothing in the logs. I walked through it in the debugger, and there is no exception thrown. root is not null at the return, but it's node object is.
Matthew Sowders
Hmm, ok. Strange. Can you post your generated classes?
Superfilin