JAXB unmarshal对于嵌套对象始终为null值

3

我有一个web服务,通过编写其WSDL和基础XSD来定义它,并且使用JAXB / xjc生成了Java服务器代码类/ Java绑定。

一切看起来都很好,服务正在正常运行...但是对于每个请求(在接收时看起来格式良好),当通过我的Java代码访问时,嵌套元素似乎总是为null。

有人能想出为什么customerId.getCustomer()始终返回null吗?

我的XSD(部分):

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

生成的类 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;
  }
}

生成的id类看起来很相似,我认为并没有什么特别之处。在我的请求处理程序中,我得到了以下提取内容:

处理程序:

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

最后是一个请求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>

我已经去掉了SOAP信封和主体标签,因为这不会引起任何问题。 有人能看出我做错了什么吗?(我很确定我做错了...) 感谢你的努力!


是的,这是我从服务器日志中获取的完整输出。 - Schlangi
但是我认为我的观点是正确的,根据我的 XSD,输出是有效的文档,不是吗?那么,我应该在哪里继续研究呢?针对(X)文件:这个服务已经运行了几个月,只有一个简单的区别:我没有嵌套元素 - 我更改了命名空间,因为公司更名。 - Schlangi
@BlaiseDoughan:当我创建一个新的Id并将customerId.customer设置为此值时,完整输出为<?xml version="1.0" encoding="UTF-8" standalone="yes"?><get_customer_request xmlns="http://example.com/tip/pro"><customer name="xy" id="1"/></get_customer_request> - 在我看来似乎没问题。 - Schlangi
在你的输出中,customer 元素位于 example.com/tip/pro 命名空间中。这意味着在你的请求中它应该有 m 前缀。 - bdoughan
@BlaiseDoughan: 在我的请求中为客户元素加上m:前缀时,解析程序会抱怨他发现了m:customer并期望是customer。到目前为止,我认为在没有m:的情况下应该是正确的,但我对此感到困惑,因为它们都应该在同一个命名空间中,并明确提到应该也可以工作,不是吗? - Schlangi
显示剩余8条评论
1个回答

3

第一部分

当我创建一个新的ID并将customerId.customer设置为此值时,完整输出如下:

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

根据这些信息,您的JAXB映射似乎期望customer元素在example.com/tip/pro命名空间中,并且您的请求文档应该是:

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

第二部分

在我的请求中,如果将m:前缀添加到客户元素中,解析器会抱怨找到了m:customer并期望找到customer。

这意味着您的XML模式与您的映射不匹配。如果您希望customer元素在命名空间中,请将您的XML模式更改为以下内容:

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

了解JAXB和命名空间的更多信息,请参见:


1
感谢您清晰的回答和有用的链接。我会尝试这个方法并回来将您的答案标记为解决方案,我相信它能够解决我的问题。 - Schlangi
我在这个客户身上有一个充满其他优先事项的月份,所以这个问题必须等待。但最终你的答案引导我找到了解决方案。 - Schlangi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接