JAXB 抱怨命名空间在它应该存在的时候存在
JAXB complains about a namespace being present when it should be there
我有一组单元测试,可以将存储的 XML 文件解组为 JAXB 对象。他们在工作。这些测试使用 PowerMock (1.6.6),因为 CUT(被测代码)中的一个细节需要 "whenNew" 子句。
我决定对对象工厂背后的抽象进行更改,这让我可以转向纯 Mockito。
当我这样做时,在测试期间将 XML 文件解组为 JAXB 对象时,我开始遇到莫名其妙的问题。它只是没有将某些元素存储到 JAXB 对象中。
执行解组的方法如下所示:
protected JAXBElement<?> unmarshallToObject(Node node, Class<?> nodeClassType) throws ServiceException {
try {
return getUnmarshaller().unmarshal(node, nodeClassType);
} catch (JAXBException ex) {
baseLogger.error(null, ex, "JAXB Exception while un-marshalling");
throw new ServiceException(UslErrCodes.BACKEND_APP.createServiceErr(BackendConfig.USL.getId(),
"JAXB Exception while un-marshalling"), ex);
}
}
我将其更改为以下内容以获取更多信息:
protected JAXBElement<?> unmarshallToObject(Node node, Class<?> nodeClassType) throws ServiceException {
try {
Unmarshaller unmarshaller = getUnmarshaller();
unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler());
return unmarshaller.unmarshal(node, nodeClassType);
} catch (JAXBException ex) {
baseLogger.error(null, ex, "JAXB Exception while un-marshalling");
throw new ServiceException(UslErrCodes.BACKEND_APP.createServiceErr(BackendConfig.USL.getId(),
"JAXB Exception while un-marshalling"), ex);
}
}
我发现解组过程拒绝将某些元素存储在 JAXB 实例中,因为它出现 xml 模式错误。
例如,更改此代码后,我看到如下消息。我在这里指的是名称空间“http://namespace1.xsd”,这显然不是它的原始名称,但在这些示例中显示该特定名称空间的所有地方,我都使用这个 "namespace1.xsd" 名称。
JAXB Exception while un-marshalling:unexpected element (uri:"http://namespace1.xsd", local:"securityFeeRequired"). Expected elements are <{}securityFeeRequired>,<{}proprietarySegmentFlag>,<{}Treatment>,<{}creditScoreMessage>,<{}ServiceEligibility>,<{}warningMessage>,<{}creditScoreResult>,<{}creditBand>
如您所见,XML 文档指出该元素在命名空间中,但“{}”似乎暗示不需要命名空间。
这是生成的 JAXB 的摘录 class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "creditScoreResult", "creditScoreMessage", "warningMessage",
"securityFeeRequired", "treatment", "creditBand", "proprietarySegmentFlag", "serviceEligibility" })
public static class FooResult implements Serializable {
private static final long serialVersionUID = 1L;
protected String creditScoreResult;
protected String creditScoreMessage;
protected String warningMessage;
protected boolean securityFeeRequired;
这里是来自同一包的生成 "package-info" 的 @XmlSchema 注释:
@XmlSchema(namespace="http://namespace1.xsd", elementFormDefault=XmlNsForm.QUALIFIED)
因此,在收到此错误后,我决定尝试进行 "this couldn't possibly work" 更改。
我更改了 XML 文件,因此这是类似的摘录:
<ExecuteFooResponse xmlns:ns1="http://namespace1.xsd" xmlns:ns2="http://namespace2.xsd">
<FooResult>
<securityFeeRequired>false</securityFeeRequired>
<Treatment><code>A001</code>
<message>No additional fee is required at this time</message>
</Treatment>
<ServiceEligibility>
<productCode>BAR</productCode>
<serviceEligibilityIndicator>true</serviceEligibilityIndicator>
</ServiceEligibility>
</FooResult>
<Response>
<ns2:code>0</ns2:code>
<ns2:description>Success</ns2:description>
</Response>
</ExecuteFooResponse>
我所做的唯一更改是 "namespace1.xsd" 的命名空间前缀。据我所知,它因“”(空白)而失败,这是正确的。我将其更改为 "ns1",但仅在声明中。我显然没有在元素主体中引用该前缀。这使测试通过。
请恢复我的理智。
问题最终是测试使用的 XML 文档实际上不是架构有效的。他们有导致验证失败的细微问题,但这些问题是其他开发人员故意放置的,因为他们发现如果没有这些错误,PowerMock 测试将无法通过。我仍在尝试弄清楚为什么 PowerMock 只能处理处于该状态的文件,但我的文档现在是模式有效的,并且 Mockito 测试正在运行。
我有一组单元测试,可以将存储的 XML 文件解组为 JAXB 对象。他们在工作。这些测试使用 PowerMock (1.6.6),因为 CUT(被测代码)中的一个细节需要 "whenNew" 子句。
我决定对对象工厂背后的抽象进行更改,这让我可以转向纯 Mockito。
当我这样做时,在测试期间将 XML 文件解组为 JAXB 对象时,我开始遇到莫名其妙的问题。它只是没有将某些元素存储到 JAXB 对象中。
执行解组的方法如下所示:
protected JAXBElement<?> unmarshallToObject(Node node, Class<?> nodeClassType) throws ServiceException {
try {
return getUnmarshaller().unmarshal(node, nodeClassType);
} catch (JAXBException ex) {
baseLogger.error(null, ex, "JAXB Exception while un-marshalling");
throw new ServiceException(UslErrCodes.BACKEND_APP.createServiceErr(BackendConfig.USL.getId(),
"JAXB Exception while un-marshalling"), ex);
}
}
我将其更改为以下内容以获取更多信息:
protected JAXBElement<?> unmarshallToObject(Node node, Class<?> nodeClassType) throws ServiceException {
try {
Unmarshaller unmarshaller = getUnmarshaller();
unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler());
return unmarshaller.unmarshal(node, nodeClassType);
} catch (JAXBException ex) {
baseLogger.error(null, ex, "JAXB Exception while un-marshalling");
throw new ServiceException(UslErrCodes.BACKEND_APP.createServiceErr(BackendConfig.USL.getId(),
"JAXB Exception while un-marshalling"), ex);
}
}
我发现解组过程拒绝将某些元素存储在 JAXB 实例中,因为它出现 xml 模式错误。
例如,更改此代码后,我看到如下消息。我在这里指的是名称空间“http://namespace1.xsd”,这显然不是它的原始名称,但在这些示例中显示该特定名称空间的所有地方,我都使用这个 "namespace1.xsd" 名称。
JAXB Exception while un-marshalling:unexpected element (uri:"http://namespace1.xsd", local:"securityFeeRequired"). Expected elements are <{}securityFeeRequired>,<{}proprietarySegmentFlag>,<{}Treatment>,<{}creditScoreMessage>,<{}ServiceEligibility>,<{}warningMessage>,<{}creditScoreResult>,<{}creditBand>
如您所见,XML 文档指出该元素在命名空间中,但“{}”似乎暗示不需要命名空间。
这是生成的 JAXB 的摘录 class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "creditScoreResult", "creditScoreMessage", "warningMessage",
"securityFeeRequired", "treatment", "creditBand", "proprietarySegmentFlag", "serviceEligibility" })
public static class FooResult implements Serializable {
private static final long serialVersionUID = 1L;
protected String creditScoreResult;
protected String creditScoreMessage;
protected String warningMessage;
protected boolean securityFeeRequired;
这里是来自同一包的生成 "package-info" 的 @XmlSchema 注释:
@XmlSchema(namespace="http://namespace1.xsd", elementFormDefault=XmlNsForm.QUALIFIED)
因此,在收到此错误后,我决定尝试进行 "this couldn't possibly work" 更改。
我更改了 XML 文件,因此这是类似的摘录:
<ExecuteFooResponse xmlns:ns1="http://namespace1.xsd" xmlns:ns2="http://namespace2.xsd">
<FooResult>
<securityFeeRequired>false</securityFeeRequired>
<Treatment><code>A001</code>
<message>No additional fee is required at this time</message>
</Treatment>
<ServiceEligibility>
<productCode>BAR</productCode>
<serviceEligibilityIndicator>true</serviceEligibilityIndicator>
</ServiceEligibility>
</FooResult>
<Response>
<ns2:code>0</ns2:code>
<ns2:description>Success</ns2:description>
</Response>
</ExecuteFooResponse>
我所做的唯一更改是 "namespace1.xsd" 的命名空间前缀。据我所知,它因“”(空白)而失败,这是正确的。我将其更改为 "ns1",但仅在声明中。我显然没有在元素主体中引用该前缀。这使测试通过。
请恢复我的理智。
问题最终是测试使用的 XML 文档实际上不是架构有效的。他们有导致验证失败的细微问题,但这些问题是其他开发人员故意放置的,因为他们发现如果没有这些错误,PowerMock 测试将无法通过。我仍在尝试弄清楚为什么 PowerMock 只能处理处于该状态的文件,但我的文档现在是模式有效的,并且 Mockito 测试正在运行。