首页 > 解决方案 > 为什么/何时 Executions.getCurrent() 为空?- 如何调试它?

问题描述

我试图了解zk.ui.Executions.getCurrent() 是什么以及它何时为 null。我在异步操作期间收到一条日志错误消息,说“服务器推送无法在不执行的情况下启动”,并已将其追踪到 Executions.getCurrent() 为空。

我正在使用 ZK 8.5.0。使用 Spring 框架 4,我也有一个多线程应用程序。发布代码真的很困难,但我可以告诉你,这发生在实现 Runnable 接口的类中的 start() 方法(在 run() 方法之前运行)期间。我试图逐行调试它- Executions.getCurrent() 总是有一个值。我试图通过在异步操作正在进行但没有运气的情况下关闭选项卡或刷新页面来以某种方式强制它变为空。它导致了另一个错误,即找不到具有给定 ID 的桌面。我应该在这里添加相关的堆栈跟踪:

java.lang.IllegalStateException: Server Push cannot be started without execution
      at org.zkoss.zk.ui.impl.DesktopImpl.enableServerPush0(DesktopImpl.java:1510)
      at org.zkoss.zk.ui.impl.DesktopImpl.enableServerPush(DesktopImpl.java:1470)
      at org.zkoss.zk.ui.impl.DesktopImpl.enableServerPush(DesktopImpl.java:1455)
      at c.p.t.e.LongOperation.enableServerPushForThisTask(LongOperation.java:172)
      at c.p.t.e.LongOperation.start(LongOperation.java:117)
      at c.p.t.c.MyController.myExport(MyController.java:332)

这意味着我正在为桌面启用 ServerPush,并且在大多数情况下这是正确的。我试图找出可能导致此失败的原因...确切的错误发生在私有布尔 enableServerPush0(ServerPush sp, boolean enable) 内的 org.zkoss.zk.ui.impl.DesktopImpl.java (l.1510) {...}。

public class DesktopImpl implements Desktop, DesktopCtrl, java.io.Serializable {
... 
private boolean enableServerPush0(ServerPush sp, boolean enable) {
        if (_sess == null)
            throw new IllegalStateException("Server push cannot be enabled in a working thread");

        final boolean serverPushAlreadyExists = _spush != null;

        if (serverPushAlreadyExists != enable) {
            final Integer icnt = (Integer) _sess.getAttribute(ATTR_PUSH_COUNT);
            int cnt = icnt != null ? icnt.intValue() : 0;
            if (enable) {
                if (Executions.getCurrent() == null)
                    throw new IllegalStateException("Server Push cannot be started without execution");
...
}

我知道我没有提供足够的信息来实际调试我的代码。如果有人能指出我正确的方向,我将不胜感激。我应该尝试什么?任何可能导致 Executions.getCurrent() 变为空的用例?

标签: zk

解决方案


您应该在 servlet 线程中启用服务器推送,例如在 composer 或 ViewModel 中。在您长时间运行的线程中,在调用 zk 组件 API 之前激活。

Executions.activate(desktop);
//logic to update UI
label.setValue(message);
Executions.deactivate(desktop);

推荐阅读