Schlangi
Schlangi

Reputation: 1155

JAXB unmarshal has always null value for nested object

I have a web-service, defined by writing its WSDL and underlaying XSD, and the java server code classes / java bindings were generated using JAXB/xjc.

Everything looks fine service is running properly... but for every request (looking well-formed after receiving when looking on log-output) the nested elements seem to be always null when accessing through my java code.

Can someone figure out why customerId.getCustomer() always returns null?

My XSD (partly):

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:tip="http://example.org/tip" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example.org/tip/pro">

<complexType name="id">
  <attribute name="id" type="int" use="required"/>
  <attribute name="name" type="string" use="optional"/>
</complexType>

<complexType name="customer_id">
  <sequence>
    <element name="customer" type="tip:id" minOccurs="0"/>
  </sequence>
</complexType>

<element name="get_customer_request" type="tip:customer_id"/>

</schema>

The generated class CustomerId:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "customer_id", propOrder = {"customer"})
public class CustomerId {
  protected Id customer;

  public Id getCustomer() {
    return customer;
  }

  public void setCustomer(Id value) {
    this.customer = value;
  }
}

The generated class for Id look similar, I don't think there is something special. In my request handler I got the following extract:

Handler:

JAXBElement<?> request = requestHandler.unmarshallRequest(inputStream);
Object jaxbClass = request.getDeclaredType();
expectedClass = CustomerId.class;
// next line does not throw exception with given XML
if (jaxbClass != expectedClass) throw new IllegalArgumentException();

CustomerId customerId = (CustomerId)request.getValue();
if (customerId == null) {
  logInfo("customerId: null");
} else if (customerId.getCustomer() == null) {
  // this is the part that always will be executed... why?
  logInfo("customerId.customer: null");
} else {
  logInfo("customer id: " + customerId.getCustomer().getId());
  // return mbean.getCustomer(customerId);
}

And finally an example request XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<m:get_customer_request xmlns:m="http://example.org/tip/pro">
  <customer id="0" name="help"/>
</m:get_customer_request>

I stripped out SOAP envelope and body tags, since this is not causing any trouble. Can anyone see, what I am doing wrong? (I am pretty sure, I do...) Thanks for your effords!

Upvotes: 3

Views: 8592

Answers (1)

bdoughan
bdoughan

Reputation: 148977

PART 1

When I create a new Id and set customerId.customer with this, the full output is

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<get_customer_request xmlns="example.com/tip/pro">
    <customer name="xy" id="1"/>
</get_customer_request>

Based on this information it appears that your JAXB mappings expect the customer element to be in the example.com/tip/pro namespace, and your request document should be:

<?xml version="1.0" encoding="ISO-8859-1"?>
<m:get_customer_request xmlns:m="http://example.org/tip/pro">
  <m:customer id="0" name="help"/>
</m:get_customer_request>

PART 2

When putting m: prefix to customer element in my request, the parser complains that he found m:customer and expected customer.

This means that your XML schema does not match your mappings. If you expect the customer element to be in the namespace you can change your XML schema to the following:

<?xml version="1.0" encoding="UTF-8"?>
<schema 
    xmlns:tip="http://example.org/tip" 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://example.org/tip/pro"
    elementFormDefault="qualified">

    ...

</schema>

For more information on JAXB and namespaces see:

Upvotes: 3

Related Questions