рüф*_*ффп 4 java cxf jaxb unmarshalling cxf-codegen-plugin
我调用一个网络服务,它可以定期在其合同中添加一些元素。
示例:SOAP 响应正文包含:
<picture>
<active>true</active>
<code>172</code>
<label>Nikon D3200 Black</label>
<downloadEnabled>true</downloadEnabled>
</picture>
<picture>
<active>false</active>
<code>177</code>
<label>Nikon D5200 Red</label>
<downloadEnabled>true</downloadEnabled>
<extraField>none</extraField>
</picture>
Run Code Online (Sandbox Code Playgroud)
我的 CXF 生成的 JAXB Bean 如下所示:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "pictureListJAXB", propOrder = {
"active",
"code",
"label",
"downloadEnabled",
"extraField"
})
public class PictureListJAXB {
protected boolean active;
protected String code;
protected String label;
protected boolean downloadEnabled;
@XmlElement(nillable = true)
protected String extraField
// And Getters / Setters comes here after
}
Run Code Online (Sandbox Code Playgroud)
JAXB bean 是使用 Maven 插件cxf-codegen-plugin版本 2.6.2(来自 apache.cxf)生成的。
现在我想知道是否有一个解决方案可以使我的 Bean 在 SOAP 响应中出现新元素时具有容错能力:
<picture>
<active>true</active>
<code>172</code>
<label>Nikon D3200 Black</label>
<downloadEnabled>true</downloadEnabled>
<newUnmappedElement>anything irrelevant</newUnmappedElement>
</picture>
Run Code Online (Sandbox Code Playgroud)
现在,当我收到这样的回复时,我得到了一个Unmarshalling Error因为这个新元素。
我的 JAXB 包含我想要管理的最小字段,但我希望 bean 能够处理新元素并忽略它们。
有没有办法在不重新生成 JAXB Bean 的情况下做到这一点?(现在我必须重新生成 Bean 并发布我的项目)
我检查了 CXF 选项(和 xjc),但在文档(和谷歌)中没有找到任何内容。解组操作也是ReferentialService由 CXF 生成的,然后选择修改这部分的生成就足够了。
以下是使用 CXF 生成的类调用 Web 服务的代码:
public ReferentialService getReferentialService(String resource, String auth) throws RuntimeException {
// These two classes are generated by CXF
Referential referential;
ReferentialService referentialService;
// Get the resource URL in form http://myserver:port/remote-backend/resource?wsdl
referential = new Referential(new URL(MyConfigUtil.getWSDL(resource)));
referentialService = referential.getReferentialServicePort();
BindingProvider bp = (BindingProvider) referentialService;
// Get the endpoint URL in form http://myserver:port/remote-backend/resource
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, MyConfigUtil.getWebServiceEndPoint(resource));
// Add SOAP credentials
String username = HttpBasicAuthHelper.getUsername(auth);
String password = HttpBasicAuthHelper.getPassword(auth);
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, username);
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password);
return referentialService;
}
Run Code Online (Sandbox Code Playgroud)
和电话:
// Throws Exception just for the sample code
public InputStream listPictures(QueryDTO request, String resource, String auth) throws Exception {
InputStream is = null;
if (request != null) {
// This is the WS Call which failed with unmarshal error
List<PictureListJAXB> result = getReferentialService(resource, auth).getPictures(request);
// Some code to convert JAXB into a XML stream
is = convertObjectToXmlStream(result);
}
return is;
}
Run Code Online (Sandbox Code Playgroud)
更新:我看到这篇文章,我的感觉是一样的:如果在没有 CXF 的情况下单独使用,JAXB 将忽略未映射的元素。通过使用cxf-codegen-plugin,情况并非如此。
我终于通过查看另一篇文章找到了答案,但由于我没有像文章中那样使用声明性方式,这让我猜测我应该能够在绑定提供程序上添加一些属性。
我对代码的修改是在方法中添加这些属性,BindingProvider如下所示getReferentialService:
bp.getRequestContext().put("schema-validation-enabled", "true");
bp.getRequestContext().put("jaxb-validation-event-handler", new ValidatorHandler());
Run Code Online (Sandbox Code Playgroud)
为了测试,我刚刚创建了一个内部类ValidatorHandler:
private class ValidatorHandler extends DefaultValidationEventHandler {
@Override
public boolean handleEvent(ValidationEvent event) {
if (event.getSeverity() == ValidationEvent.WARNING) {
return super.handleEvent(event);
} else if (event.getSeverity() == ValidationEvent.ERROR
&& event.getMessage().startsWith("unexpected element")) {
return true;
} else {
throw new RuntimeException(event.getMessage()
+ " [line:" + event.getLocator().getLineNumber() + "]");
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过这样做,我不需要修改生成的 bean (JAX-B) 并使用它们,因为它们是默认生成的。
| 归档时间: |
|
| 查看次数: |
5016 次 |
| 最近记录: |