我试图了解什么是 zk.ui.Executions.getCurrent()以及何时为空。在异步操作过程中,我收到一条日志错误消息,内容为“无法执行而无法启动服务器推送”,并且已将其追溯到Executions.getCurrent()为空。
我正在使用ZK 8.5.0。使用Spring Framework 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,并且在大多数情况下,此操作可以正确完成。我正在尝试找出可能导致此失败的原因... 确切的错误发生在私有boolean 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()变为空的用例?
答案 0 :(得分:0)
ZK将AJAX请求数据包装到Execution对象中,并将该对象传递给处理事件的整个过程。
应用服务器会为每个AJAX请求生成一个Servlet线程,因此Execution
在此线程中可用。如果运行除Servlet线程以外的单独线程,则无法执行。在这样的线程中,如果要更新UI(调用ZK组件设置器),则需要启用服务器并等待执行。请阅读The Developer's reference / server push。
答案 1 :(得分:0)
您应该启用服务器推送servlet线程,例如在作曲家或ViewModel中。在长时间运行的线程中,在调用zk组件API之前先激活它。
Executions.activate(desktop);
//logic to update UI
label.setValue(message);
Executions.deactivate(desktop);