在没有 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。

我的问题是:

  1. 默认情况下它们不使用 EJB,因此本身没有拦截器。是否有一些实现可以同时适用于 Tomcat 和 JBoss?
  2. 即使我能够拦截 return 服务器端,我怎么能在客户端拦截呢?
  3. 如果我可以使用 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 而没有这个.