【问题标题】:Intercept SOAP RPC method response without EJB拦截没有 EJB 的 SOAP RPC 方法响应
【发布时间】:2016-05-04 17:43:02
【问题描述】:

我正在为一家公司进行项目改造,他们希望在前端/客户端和后端/服务器之间拆分系统(更像是前端和数据库服务器之间的中间人),我应该使用 JAX-WS RPC 并维护当前的功能。

通过维护功能,它们意味着某些方法应该返回 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. 即使我能够拦截返回服务器端,我怎么能在客户端呢?
  3. 如果我可以使用 SOAPHandlers,如何避免因尝试返回 null 而引发 SOAP 错误?

【问题讨论】:

  • 您是否尝试过使用处理程序jax-ws.java.net/articles/handlers_introduction.html
  • @VirtualTroll 如前所述,我怎样才能避免引发故障?我已经尝试过了,但是如果方法返回 null(甚至不是 handleFault),则不会调用处理程序,它只是将通知直接发送到客户端...
  • 您能提供在 JBoss 或 Tomcat 上声明 Web 服务的方式吗?最后但并非最不重要的一点是,您可能想探索 aspectJ(您可以在其中定位方法的终止)
  • 还有一件事:你的 web 服务是用 @SOAPBinding(style = Style.DOCUMENT) 还是 @SOAPBinding(style = Style.RPC) 注释的?
  • @VirtualTroll RPC,根据他们的要求。此外,我确实尝试切换到 DOCUMENT,但这也需要非重载方法,这反过来会破坏依赖于现有方法的当前代码。我想我会准备一个我目前拥有的基本样本并尽快更新我的帖子。 WS 通过 sun-jaxws.xml 声明,指向实现类,实现类通过“实现”指向 SEI。

标签: java tomcat jakarta-ee soap jax-ws


【解决方案1】:

由于我也遇到了 JAXB 不处理接口的问题,所以我最终做的是使用 @XmlJavaTypeAdapter 注释来启用(有选择地,因为每个返回值和实际上可能为 null 的参数都需要注释)从和以一种hackjob的方式返回null。我为Serializable 对象创建了一个通用的适配器,并为其他类型的Objects 采用了相同的方法:

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 似乎在调用适配器时急切地转换编码的类型,因此即使要编组的对象不是预期的类/接口的实例,它也会编译得很好,并且只在运行时抛出异常。

我不建议这样做,因为它需要注释每一个方法/参数或包,并且会在第一个没有注释但收到 null 的地方中断。 这个适配器仍然适用于我需要使用接口的情况,并且实现类也实现 Serializable,尽管有些情况仍然需要特定的适配器,但这通常是经过深思熟虑的代码。

部分由于 this 的 hackness 和注释所有内容的麻烦,我设法说服公司放弃 SOAP RPC 绑定,因此我能够在没有 this 的情况下使用 null 参数和返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    相关资源
    最近更新 更多