S1187
(S Ali)
August 30, 2016, 5:34pm
1
I have seen some old posts and this
link
but cannot seem to get the detach() event.
I am using the code below to initialize the servlet params and then build a little UI.
What I was expecting is that if I closed my browser, eventyually after 15 seconds or more, I would get
the detach event triggered, But that does not seem to happen.
I read in other threads that it does not work with @Push or websockets etc. I tried removing @Push but it still does not get called.
Am I doing something wrong ? Or is my assumption that this method should be called when a browser closes incorrect ?
Thanks for any help.
@SuppressWarnings (“serial”)
@Theme (“demo”)
@PreserveOnRefresh
@Push (PushMode.AUTOMATIC)
public class DemoUI extends UI {
@WebServlet (value = “/*”, asyncSupported = true)
@VaadinServletConfiguration (productionMode = false, ui = DemoUI.class, heartbeatInterval=5, closeIdleSessions=true)
public static class Servlet extends VaadinServlet {
}
@Override
protected void init(VaadinRequest request) {
addDetachListener(new DetachListener() {
@Override
public void detach(DetachEvent event) {
System.err.println("Detach Event = "+event.getConnector().getConnectorId());
}
});
// UI Code here
}
}
S1187
(S Ali)
August 30, 2016, 6:10pm
2
Some more info :- I am running my code from within Eclipse using Tomcat 7.x (not sure if that makes any difference)
It looks like I do get the events, but only when I open a new browser request after the previous one has expired.
In fact with chrome, I simply need to type http://local and autocomplete brings up the URL (without loading it ) and that causes the old session to detach …
Is there any way around this ? Ideally I would like the server to detect the loss of hearbeat without having to wait for a new request,
Tatu2
(Tatu Lund)
March 15, 2017, 10:48am
4
Have you checked if this Add-On actually does what you are trying to do?
https://vaadin.com/directory/#!addon/cleanupservlet-add-on
Alexander444
(Alexander Cherepanov)
March 15, 2017, 11:00am
5
Well, i try to use minimal count of add-ons.
In this case i create service, that close timeouted UIs and Sessions.
public class VaadinServletWithListeners extends VaadinServlet {
private static ConcurrentHashMap<VaadinSession, Integer> mapVaadinSessionToCodOp = new ConcurrentHashMap<>();
@Override
protected void servletInitialized() throws ServletException {
super.servletInitialized();
VaadinService.getCurrent().addSessionInitListener((SessionInitListener) event -> {
VaadinSession session = event.getSession();
mapVaadinSessionToCodOp.put(session, 0);
String remoteAddr = event.getRequest().getRemoteAddr();
});
VaadinService.getCurrent().addSessionDestroyListener((SessionDestroyListener) event -> {
VaadinSession session = event.getSession();
mapVaadinSessionToCodOp.remove(session);
});
}
public static synchronized ConcurrentHashMap<VaadinSession, Integer> getMapVaadinSessionToCodOp(){
return mapVaadinSessionToCodOp;
}
}
[code]
public class SessionAndUICloser {
public void closeSessionsAndUIs() {
int defaultHeartbeatInterval = DefaultDeploymentConfiguration.DEFAULT_HEARTBEAT_INTERVAL;
int cleanupIntervalMillis = 3 * 1000 * defaultHeartbeatInterval;
// Close all timeouted UIs and Sessions
ConcurrentHashMap<VaadinSession, Integer> allSessionsWithCodOps = VaadinServletWithListeners.getMapVaadinSessionToCodOp();
Enumeration<VaadinSession> keys = allSessionsWithCodOps.keys();
while (keys.hasMoreElements()){
VaadinSession vaadinSession = keys.nextElement();
Collection<UI> uIs = vaadinSession.getUIs();
boolean hasAliveUIs = false;
for (UI ui : uIs){
if (System.currentTimeMillis() > ui.getLastHeartbeatTimestamp() + cleanupIntervalMillis){
ui.close();
} else {
hasAliveUIs = true;
}
}
if (!hasAliveUIs){
vaadinSession.close();
allSessionsWithCodOps.remove(vaadinSession);
}
}
}
}
[/code]SessionAndUICloser starts with SPRING-scheduler with period 60 sec.
Second Integer in Map - it is user id in my purposes.
Maybe this code has some bugs and memory leaks?