IDEMPIERE-4206 Session timeout shown sometimes when changing roles

Simplify Serverpush Code - remove retries and warning that just slow down
things and doesn't really help.
Change Role - With session invalidated and all components removed, there
isn't need to destroy desktop.
This commit is contained in:
hengsin 2020-04-03 20:06:07 +08:00
parent 346baa7b77
commit 61098bdf3c
8 changed files with 31 additions and 109 deletions

View File

@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.adempiere.webui.AdempiereWebUI;
import org.atmosphere.cpr.AtmosphereResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -63,7 +62,6 @@ public class AtmosphereServerPush implements ServerPush {
private ExecutionCarryOver _carryOver;
private final Object _mutex = new Object();
private List<Schedule<Event>> schedules = new ArrayList<>();
private long lastPiggyBack = 0;
public AtmosphereServerPush() {
String timeoutString = Library.getProperty("fi.jawsy.jawwa.zk.atmosphere.timeout");
@ -164,7 +162,6 @@ public class AtmosphereServerPush implements ServerPush {
@SuppressWarnings("unchecked")
@Override
public void onPiggyback() {
lastPiggyBack = System.currentTimeMillis();
Schedule<Event>[] pendings = null;
synchronized (schedules) {
if (!schedules.isEmpty()) {
@ -188,36 +185,11 @@ public class AtmosphereServerPush implements ServerPush {
if (Executions.getCurrent() == null) {
//schedule and execute in desktop's onPiggyBack listener
scheduler.schedule(task, event);
boolean ok = false;
try {
ok = commitResponse();
commitResponse();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
if (!ok) {
long l = lastPiggyBack;
for(int i = 0; i < 3 && !ok; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e1) {}
if (l == lastPiggyBack) {
try {
ok = commitResponse();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
} else {
ok = true;
}
}
if (!ok) {
Desktop d = desktop.get();
log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : ""));
if (d != null) {
AdempiereWebUI.increaseScheduleFailures(d);
}
}
}
} else {
// in event listener thread, use echo to execute async
synchronized (schedules) {

View File

@ -53,8 +53,10 @@ public class ZkAtmosphereHandler implements AtmosphereHandler {
if (session.getWebApp() instanceof WebAppCtrl) {
WebAppCtrl webAppCtrl = (WebAppCtrl) session.getWebApp();
Desktop desktop = webAppCtrl.getDesktopCache(session).getDesktopIfAny(dtid);
if (desktop == null)
log.warn("Could not find desktop: " + dtid);
if (desktop == null) {
if (log.isDebugEnabled())
log.debug("Could not find desktop: " + dtid);
}
return new Either<String, Desktop>("Could not find desktop", desktop);
}
return new Either<String, Desktop>("Webapp does not implement WebAppCtrl", null);
@ -124,9 +126,10 @@ public class ZkAtmosphereHandler implements AtmosphereHandler {
Either<String, AtmosphereServerPush> serverPushEither = getServerPush(resource);
String error = serverPushEither.getLeftValue();
if (error != null && serverPushEither.getRightValue() == null) {
log.warn("Bad Request. Error="+error+", Request="+resource.getRequest().getRequestURI());
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().write(error);
if (log.isDebugEnabled())
log.warn("Bad Request. Error="+error+", Request="+resource.getRequest().getRequestURI());
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
response.getWriter().write("");
response.getWriter().flush();
return;
}

View File

@ -66,8 +66,6 @@ import org.zkoss.zk.ui.event.ClientInfoEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.sys.DesktopCache;
import org.zkoss.zk.ui.sys.SessionCtrl;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Window;
@ -120,8 +118,6 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
private ConcurrentMap<String, String[]> m_URLParameters;
public static final String SERVERPUSH_SCHEDULE_FAILURES = "serverpush.schedule.failures";
private static final String ON_LOGIN_COMPLETED = "onLoginCompleted";
public AdempiereWebUI()
@ -384,18 +380,16 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
desktop.enableServerPush(false);
Session session = logout0();
DesktopCache desktopCache = ((SessionCtrl)session).getDesktopCache();
//clear context, invalidate session
Env.getCtx().clear();
session.invalidate();
desktop.setAttribute(DESKTOP_SESSION_INVALIDATED_ATTR, Boolean.TRUE);
//redirect to login page
Executions.sendRedirect("index.zul");
if (desktopCache != null)
desktopCache.removeDesktop(Executions.getCurrent().getDesktop());
Executions.sendRedirect("index.zul");
}
public void logoutAfterTabDestroyed(){
Desktop desktop = Executions.getCurrent().getDesktop();
if (desktop.isServerPushEnabled())
@ -550,14 +544,14 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
if (desktop.isServerPushEnabled())
desktop.enableServerPush(false);
Session session = logout0();
DesktopCache desktopCache = ((SessionCtrl)session).getDesktopCache();
logout0();
//clear context
Env.getCtx().clear();
//invalidate session
((SessionCtrl)session).invalidateNow();
httpRequest.getSession(false).invalidate();
desktop.setAttribute(DESKTOP_SESSION_INVALIDATED_ATTR, Boolean.TRUE);
//put saved context into new session
Map<String, Object> map = new HashMap<String, Object>();
@ -568,14 +562,7 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
newSession.setAttribute(SAVED_CONTEXT, map);
properties.setProperty(SessionContextListener.SERVLET_SESSION_ID, newSession.getId());
//redirect must happens before removeDesktop below, otherwise you get NPE
Executions.getCurrent().sendRedirect("index.zul");
//remove old desktop
if (desktopCache != null) {
desktop.setAttribute(DESKTOP_SESSION_INVALIDATED_ATTR, Boolean.TRUE);
desktopCache.removeDesktop(desktop);
}
Executions.getCurrent().sendRedirect("index.zul");
}
@Override
@ -593,32 +580,5 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
uploadSetting.append(",maxsize=").append(size);
}
return uploadSetting.toString();
}
/**
* Increase server push schedule failures count
* @param d
*/
public static void increaseScheduleFailures(Desktop d) {
Integer count = (Integer) d.getAttribute(SERVERPUSH_SCHEDULE_FAILURES);
if (count != null)
count = Integer.valueOf(count.intValue()+1);
else
count = Integer.valueOf(1);
d.setAttribute(SERVERPUSH_SCHEDULE_FAILURES, count);
}
/**
*
* @param d
* @return server push schedule failures count
*/
public static int getScheduleFailures(Desktop d) {
int failures = 0;
Object attr = d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES);
if (attr != null && attr instanceof Integer)
failures = ((Integer)attr).intValue();
return failures;
}
}
}

View File

@ -220,6 +220,8 @@ public final class AEnv
MSession session = MSession.get(Env.getCtx(), false); // finish
if (session != null)
session.logout();
Env.setContext(Env.getCtx(), "#AD_Session_ID", (String)null);
//
}

View File

@ -25,7 +25,6 @@ import java.util.Properties;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import org.adempiere.webui.AdempiereWebUI;
import org.adempiere.webui.ValuePreference;
import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.component.AutoComplete;
@ -66,6 +65,7 @@ import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zk.ui.sys.SessionCtrl;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zk.ui.util.DesktopCleanup;
import org.zkoss.zul.Comboitem;
@ -919,7 +919,15 @@ ContextMenuListener, IZoomableEditor
private void refreshLookupList() {
Desktop desktop = editor.getComponent().getDesktop();
int failures = AdempiereWebUI.getScheduleFailures(desktop);
boolean alive = false;
if (desktop.isAlive() && desktop.getSession() != null) {
SessionCtrl ctrl = (SessionCtrl) desktop.getSession();
alive = !ctrl.isInvalidated();
}
if (!alive) {
((ITableDirEditor)editor.getComponent()).cleanup();
return;
}
Executions.schedule(desktop, new EventListener<Event>() {
@Override
public void onEvent(Event event) {
@ -929,10 +937,6 @@ ContextMenuListener, IZoomableEditor
} catch (Exception e) {}
}
}, new Event("onResetLookupList"));
int f = AdempiereWebUI.getScheduleFailures(desktop);
if (f > failures) {
((ITableDirEditor)editor.getComponent()).cleanup();
}
}
@Override

View File

@ -93,7 +93,6 @@ public class RolePanel extends Window implements EventListener<Event>, Deferrabl
protected Combobox lstRole, lstClient, lstOrganisation, lstWarehouse;
protected Label lblRole, lblClient, lblDef, lblOrganisation, lblWarehouse, lblDate;
protected WDateEditor lstDate;
protected Button btnOk, btnCancel;
/** Context */
protected Properties m_ctx;
@ -351,16 +350,6 @@ public class RolePanel extends Window implements EventListener<Event>, Deferrabl
lstDate.setValue(new Timestamp(System.currentTimeMillis()));
lstDate.getComponent().setId("loginDate");
btnOk = new Button();
btnOk.setId("btnOk");
btnOk.setLabel("Ok");
btnOk.addEventListener("onClick", this);
btnCancel = new Button();
btnCancel.setId("btnCancel");
btnCancel.setLabel("Cancel");
btnCancel.addEventListener("onClick", this);
// initial client - Elaine 2009/02/06
UserPreference userPreference = SessionManager.getSessionApplication().getUserPreference();
String initDefault = userPreference.getProperty(UserPreference.P_CLIENT);

View File

@ -325,7 +325,7 @@ public class SessionContextListener implements ExecutionInit,
}
}
public static void addDesktopId(int AD_Session_ID, String dtid)
public static synchronized void addDesktopId(int AD_Session_ID, String dtid)
{
String key = getSessionDesktopListKey(AD_Session_ID);
@SuppressWarnings("unchecked")

View File

@ -30,7 +30,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import org.adempiere.webui.AdempiereWebUI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.zk.au.out.AuEcho;
@ -203,14 +202,7 @@ public class WebSocketServerPush implements ServerPush {
if (Executions.getCurrent() == null) {
//schedule and execute in desktop's onPiggyBack listener
scheduler.schedule(task, event);
boolean ok = echo();
if (!ok) {
Desktop d = desktop.get();
log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : ""));
if (d != null) {
AdempiereWebUI.increaseScheduleFailures(d);
}
}
echo();
} else {
// in event listener thread, use echo to execute async
synchronized (schedules) {