0

Max listeners in EventQueue?

asked 2020-04-23 16:39:24 +0800

AndreyK gravatar image AndreyK
155 3

updated 2020-05-01 03:58:29 +0800

I use this solution for communicate between browser tabs in application:

1st tab - main tab. Creates

eq = EventQueues.lookup("mainTimerPub", EventQueues.SESSION, true);
    lsnr = new EventListener<MainTimerEvent>() {
      @Override
      public void onEvent(MainTimerEvent mainTimerEvent) throws Exception {
        processEvent(mainTimerEvent);
      }
    };
eq.subscribe(lsnr);

Next, I use tabs, opened in "_blank", that creates in init() method:

@Init
  public void init() {
      mainTimerEventEventListener = new EventListener<MainTimerEvent>() {
        @Override
        public void onEvent(MainTimerEvent mainTimerEvent) throws Exception {
          processEvent(mainTimerEvent);
        }
      };
//      eq = EventQueues.lookup("mainTimerPub", EventQueues.SESSION, false);
      eq = EventQueues.lookup("mainTimerPub", Sessions.getCurrent(), false);
      eq.subscribe(mainTimerEventEventListener);
...
}

Problem that I cant open more 4, sometimes 5 tabs. Application became busy till i close one of them. Why? Can I work with more tabs or not?

Without this I dont have limitation to open tabs

UPD1: reproduced at zkfiddle. https://zkfiddle.org/sample/g5c66b/2-ZK-Event-Queue-MultiTabs-Bug-Example after 5-6 opened i get https://gyazo.com/39332f17624b7736e57903f787d9a0c2 it continues until i close one of them

delete flag offensive retag edit

7 Answers

Sort by ยป oldest newest most voted
0

answered 2020-04-24 15:05:10 +0800

MDuchemin gravatar image MDuchemin
1688 1 5
ZK Team

Hi there,

EventQueues should be overloaded with 4 or 5 tabs. I'd guess it would be either a priority / timing condition between 2 tabs interfering with eachother, or reaching the limit of desktop per session

You could put some breakpoints / debug logs in these events to see when they are invoked.

If your time fires very often, and the event has a delay (like checking from databased, etc), you might be in a situation where resolving every event takes longer than the time tick. This might make the application wait indefinitely, as it would be always in a processing state.

link publish delete flag offensive edit

Comments

If you can reproduce this with a short code, posting a zkfiddle would be useful to debug it.

MDuchemin ( 2020-04-24 15:05:54 +0800 )edit

@MDuchemin. Reproduced it. Updated post. In my app config "limit desktops" do nothing. Without EventQueue i dont get this error.

AndreyK ( 2020-05-01 03:59:41 +0800 )edit
0

answered 2020-05-04 17:44:29 +0800

MDuchemin gravatar image MDuchemin
1688 1 5
ZK Team

@AndreyK thanks for the fiddle, it was very useful understanding your situation :)

You are running out of available connections at the browser level. Browsers will only allow a limited number of concurent connections to the same domain name. (Chrome is 6, IE11 is 12, etc) This is not technically a ZK issue, but it comes from a ZK spec.

Each tab opened is subscribing to a SESSION level event queues. Session level event queues are automatically async queues, and automatically enable server-push for their page. See the eventqueues page here

Depending on your container and your project configuration, enabling server-push may cause a CometServerPush to be enabled for the page. It allows the server to send updates to the client without user activity. To do so, the client always has a "waiting on updates" connection opened to the server. For each tab opened, you create another "waiting on server" connection, which occupy an available connection slot on the web container (web server).

Your options to solve this are easy: If you need the async update, you will want to move to WebSocket server push, or as a fallback to PollingServerPush. These options support more connections per browser.

If you don't need the async, you can just have a "refresh on user activity" functionality on your page, with the content being refreshed manually by the user.

link publish delete flag offensive edit
0

answered 2020-05-06 15:37:47 +0800

AndreyK gravatar image AndreyK
155 3

updated 2020-05-06 15:48:58 +0800

@MDuchemin. Thank you very much for the answer! I am using ZK 8.0.5 version and tomcat server. My task - synchronize session time between tabs and do autosave/notification for user. I see that WebSocket comes with 8.5 version, and i cant just update without check and fix other moments (isn't it? For example with WebSocketWebAppInit listener i get errors like https://gyazo.com/79d6890f5881474450e6fc30a550ba8c and etc). If I understood correctly, you suggest using WebSocket channels (https://www.zkoss.org/wiki/ZKDeveloper'sReference/Integration/Miscellenous/WebsocketChannel#MVVMExample_2) and not to use EventQueues in this case? So, as I see now, VM with main timer will send messages to MVVM with websocket and get back from others to refresh timer. It will help not create new connections as it happens with EventQueues

link publish delete flag offensive edit
0

answered 2020-05-06 18:31:06 +0800

MDuchemin gravatar image MDuchemin
1688 1 5
ZK Team

Hi AndreyK,

Update between 8.0.5 and 8.5 shouldn't be too painful. If you have a custom theme, you may need to update it though, as I believe there are new components during this version update.

Regarding websocket: There are 2 different features, Websocket Server push and Websocket channels In this case, I was referring to Websocket server push, which doesn't require you to rewrite your event queues It is just a different implementation of server push, which is the underlying mecanism used by event queues in Session scope to deliver updates to the client without having to wait from client activity. Websocket channels are a useful tool, but they are out of this topic, as they are an entirely different feature.

In order to use Websocket Server Push, you will need a few things:

  • check your tomcat version: Apache Tomcat Version table You need to use AT LEAST tomcat 7 (for servlet spec 3.0, which matches WebSocket spec 1.1)

  • Check you web.xml servlet version You will need to run an application using servlet 3.0 or higher

  • apply the WebSocketWebAppInit listener in zk.xml

Regarding the servlet API version: You can change it in web.xml, or using the web.servlet-3.xml located in WEB-INF. This is servlet config, not ZK, so it's somewhat out of scope for this forum. Just see this post if you need more details

link publish delete flag offensive edit
0

answered 2020-05-06 18:32:55 +0800

MDuchemin gravatar image MDuchemin
1688 1 5
ZK Team

if evereything goes well, you should see this in the developer tools, network panel:

websocket success

link publish delete flag offensive edit
0

answered 2020-05-07 21:36:59 +0800

AndreyK gravatar image AndreyK
155 3

updated 2020-05-08 11:48:35 +0800

cor3000 gravatar image cor3000
5173 2 7
ZK Team

Seems in my case need more tuning for Spring, cause i have errors like these: https://gyazo.com/9f8de0e29d6b5631eaa49ad312c6ff1f with Service singleton and https://gyazo.com/79d6890f5881474450e6fc30a550ba8c with scope

@Service
@Scope(value= WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.TARGET_CLASS)
public class CurrentUserController {

And this only at start. Will try it little later

link publish delete flag offensive edit
0

answered 2020-05-08 10:56:47 +0800

cor3000 gravatar image cor3000
5173 2 7
ZK Team

Yes those errors are a common effect with Session or Request scoped Proxies and websockets. (https://stackoverflow.com/questions/31916727/request-or-session-scope-in-spring-websocket)

Websocket messages don't create an HttpServletRequest, and hence don't invoke Springs RequestContextFilter (or similar). ZK generates a "Fake" HttpRequest for a similar purpose, when using websockets, which has a chance to serve a similar purpose in spring. The ExecutionInit/Cleanup interfaces can serve as a kind of filter to set the information needed by spring bean proxies before and reset them after a request (in ZK abstracted by the Execution interface).

Here my prototypic implementation (not tested)

package zk.example;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.zkoss.zk.ui.Execution;
import org.zkoss.zk.ui.util.ExecutionCleanup;
import org.zkoss.zk.ui.util.ExecutionInit;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

public class RequestContextExecutionListener implements ExecutionInit, ExecutionCleanup {

    private static final String RESET_FLAG = RequestContextExecutionListener.class.getName() + ".RESET_FLAG";

    @Override
    public void init(Execution exec, Execution parent) throws Exception {
        if(parent == null && RequestContextHolder.currentRequestAttributes() == null) {
            exec.setAttribute(RESET_FLAG, true);
            RequestContextHolder.setRequestAttributes(
                    new ServletRequestAttributes((HttpServletRequest) exec.getNativeRequest()));
        };
    }

    @Override
    public void cleanup(Execution exec, Execution parent, List<Throwable> errs) throws Exception {
        if(parent == null && exec.removeAttribute(RESET_FLAG) != null) {
            RequestContextHolder.resetRequestAttributes();
        }
    }
}

It performs similar operations as springs own RequestContextFilter

It can be configured in your zk.xml using a <listener> element.

I could imagine this requires some fine tuning, if you have additional questions please contact our support directly.

link publish delete flag offensive edit
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow
1 follower

RSS

Stats

Asked: 2020-04-23 16:39:24 +0800

Seen: 22 times

Last updated: May 08

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More