在没有 EJB 的情况下拦截 SOAP RPC 方法响应
Intercept SOAP RPC method response without EJB
我正在为一家公司进行项目改造,他们想在 front-end/client 和 back-end/server 之间拆分他们的系统(更像是前端和数据库服务器之间的中间人),我应该使用 JAX-WS RPC 并保持当前功能。
通过维护功能,它们意味着某些方法应该 return null,这是 WS-I 所禁止的。
在寻找可能的解决方案时,我偶然发现了这篇文章:http://victor-ichim.blogspot.com.br/2011/03/rpcliteral-and-null-object-pattern.html,它通过使用 EJB 拦截器拦截并用空对象替换空结果基本上解决了类似的问题。
围绕这个概念,我想像这样拦截结果,将 null 替换为字符串模板之类的东西,在客户端再次拦截它并将该模板替换回 null。
我的问题是:
- 默认情况下它们不使用 EJB,因此本身没有拦截器。是否有一些实现可以同时适用于 Tomcat 和 JBoss?
- 即使我能够拦截 return 服务器端,我怎么能在客户端拦截呢?
- 如果我可以使用 SOAPHandlers,我怎样才能避免引发 SOAP 错误以尝试 return null?
因为我也遇到了 JAXB 不处理接口的问题,所以我最终做的是使用 @XmlJavaTypeAdapter
注释来启用(有选择地,因为每个 return 和实际上可能为 null 的参数都需要待注释)以某种 hackjob 方式将值从 null 转换回 null。我为 Serializable
对象创建了一个通用的适配器,并对其他类型的 Object
对象采用了相同的方法:
public class SerializableAdapter extends XmlAdapter<String, Serializable>>{
private static final String NULL = "'NULL'"; // Will hopefully never collide
@Override
public Serializable unmarshal(String e) throws Exception {
if (e == NULL) {
return null;
}
byte [] eB = e.getBytes("ISO-8859-1");
InputStream iS = new ByteArrayInputStream(Base64.getDecoder().decode(eB));
ObjectInputStream oIS = new ObjectInputStream(iS);
return (Serializable) oIS.readObject();
}
@Override
public String marshal(Serializable o) throws Exception {
if (o == null) {
return NULL;
}
ByteArrayOutputStream bAOS = new ByteArrayOutputStream();
ObjectOutputStream oOS = new ObjectOutputStream(bAOS);
oOS.writeObject(o);
return Base64.getEncoder().encodeToString(bAOS.toByteArray());
}
}
然后用 @XmlJavaTypeAdapter(SerializableAdapter.class)
注释每个 Serializable
实例,因为使用包级 @XmlJavaTypeAdapters
由于某种原因不起作用,其他情况依此类推。 JAXB 似乎在调用适配器时热切地转换编码类型,因此即使要编组的对象不是预期 class/interface 的实例,它也能正常编译,并且仅在运行时抛出异常。
我不建议这样做,因为它需要注释每个 method/parameter 或包,并且会在第一个没有注释但尚未注释的received null. 这个适配器仍然为我需要使用接口的情况服务,并且实现 类 也实现 Serializable,尽管有些情况仍然需要特定的适配器,但这通常是考虑不周的代码。
部分是因为这个的技巧和注释所有东西的麻烦,我设法说服公司放弃 SOAP RPC 绑定,所以我能够有 null 参数和 returns 而没有这个.
我正在为一家公司进行项目改造,他们想在 front-end/client 和 back-end/server 之间拆分他们的系统(更像是前端和数据库服务器之间的中间人),我应该使用 JAX-WS RPC 并保持当前功能。
通过维护功能,它们意味着某些方法应该 return null,这是 WS-I 所禁止的。
在寻找可能的解决方案时,我偶然发现了这篇文章:http://victor-ichim.blogspot.com.br/2011/03/rpcliteral-and-null-object-pattern.html,它通过使用 EJB 拦截器拦截并用空对象替换空结果基本上解决了类似的问题。
围绕这个概念,我想像这样拦截结果,将 null 替换为字符串模板之类的东西,在客户端再次拦截它并将该模板替换回 null。
我的问题是:
- 默认情况下它们不使用 EJB,因此本身没有拦截器。是否有一些实现可以同时适用于 Tomcat 和 JBoss?
- 即使我能够拦截 return 服务器端,我怎么能在客户端拦截呢?
- 如果我可以使用 SOAPHandlers,我怎样才能避免引发 SOAP 错误以尝试 return null?
因为我也遇到了 JAXB 不处理接口的问题,所以我最终做的是使用 @XmlJavaTypeAdapter
注释来启用(有选择地,因为每个 return 和实际上可能为 null 的参数都需要待注释)以某种 hackjob 方式将值从 null 转换回 null。我为 Serializable
对象创建了一个通用的适配器,并对其他类型的 Object
对象采用了相同的方法:
public class SerializableAdapter extends XmlAdapter<String, Serializable>>{
private static final String NULL = "'NULL'"; // Will hopefully never collide
@Override
public Serializable unmarshal(String e) throws Exception {
if (e == NULL) {
return null;
}
byte [] eB = e.getBytes("ISO-8859-1");
InputStream iS = new ByteArrayInputStream(Base64.getDecoder().decode(eB));
ObjectInputStream oIS = new ObjectInputStream(iS);
return (Serializable) oIS.readObject();
}
@Override
public String marshal(Serializable o) throws Exception {
if (o == null) {
return NULL;
}
ByteArrayOutputStream bAOS = new ByteArrayOutputStream();
ObjectOutputStream oOS = new ObjectOutputStream(bAOS);
oOS.writeObject(o);
return Base64.getEncoder().encodeToString(bAOS.toByteArray());
}
}
然后用 @XmlJavaTypeAdapter(SerializableAdapter.class)
注释每个 Serializable
实例,因为使用包级 @XmlJavaTypeAdapters
由于某种原因不起作用,其他情况依此类推。 JAXB 似乎在调用适配器时热切地转换编码类型,因此即使要编组的对象不是预期 class/interface 的实例,它也能正常编译,并且仅在运行时抛出异常。
我不建议这样做,因为它需要注释每个 method/parameter 或包,并且会在第一个没有注释但尚未注释的received null. 这个适配器仍然为我需要使用接口的情况服务,并且实现 类 也实现 Serializable,尽管有些情况仍然需要特定的适配器,但这通常是考虑不周的代码。
部分是因为这个的技巧和注释所有东西的麻烦,我设法说服公司放弃 SOAP RPC 绑定,所以我能够有 null 参数和 returns 而没有这个.