-
FEATURED COMPONENTS
First time here? Check out the FAQ!
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
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.
@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.
@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
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
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
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.
Asked: 2020-04-23 16:39:24 +0800
Seen: 25 times
Last updated: May 08 '20
Error: java.lang.NoClassDefFoundError
Error: Could not initialize class sun.net.www.protocol.http.HttpURLConnection
ArrayIndexOuOfBoundsException showing Messagebox
error PWC2788: setAttribute: Non-serializable attribute with name javax.zkoss.zk.ui.Session
no grammar constraints (dtd or xml schema) detected for the document
ListModelList.clear() - Error in ZK Framework?