mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-04 20:28:00 +08:00
refs #1746 Synchronize time for desktop client
This commit is contained in:
parent
b0b94e155f
commit
68dadbb35a
@ -7,15 +7,11 @@
|
||||
package com.haulmont.cuba.desktop;
|
||||
|
||||
import com.haulmont.cuba.client.sys.MessagesClientImpl;
|
||||
import com.haulmont.cuba.core.app.ServerInfoService;
|
||||
import com.haulmont.cuba.core.global.*;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import com.haulmont.cuba.core.sys.remoting.ClusterInvocationSupport;
|
||||
import com.haulmont.cuba.desktop.exception.ExceptionHandlers;
|
||||
import com.haulmont.cuba.desktop.sys.DesktopAppContextLoader;
|
||||
import com.haulmont.cuba.desktop.sys.DesktopWindowManager;
|
||||
import com.haulmont.cuba.desktop.sys.MainWindowProperties;
|
||||
import com.haulmont.cuba.desktop.sys.MenuBuilder;
|
||||
import com.haulmont.cuba.desktop.sys.*;
|
||||
import com.haulmont.cuba.desktop.theme.DesktopTheme;
|
||||
import com.haulmont.cuba.desktop.theme.DesktopThemeLoader;
|
||||
import com.haulmont.cuba.gui.AppConfig;
|
||||
@ -495,7 +491,7 @@ public class App implements ConnectionListener {
|
||||
windowManager.setTabsPane(tabsPane);
|
||||
|
||||
initExceptionHandlers(true);
|
||||
initTimeZone();
|
||||
initClientTime();
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
@ -555,14 +551,10 @@ public class App implements ConnectionListener {
|
||||
}
|
||||
}
|
||||
|
||||
protected void initTimeZone() {
|
||||
DesktopConfig desktopConfig = configuration.getConfig(DesktopConfig.class);
|
||||
if (desktopConfig.isUseServerTimeZone()) {
|
||||
ServerInfoService serverInfoService = AppBeans.get(ServerInfoService.NAME);
|
||||
TimeZone serverTimeZone = serverInfoService.getTimeZone();
|
||||
TimeZone.setDefault(serverTimeZone);
|
||||
log.info("Time zone set to " + serverTimeZone);
|
||||
}
|
||||
protected void initClientTime() {
|
||||
ClientTimeSynchronizer clientTimeSynchronizer = AppBeans.get(ClientTimeSynchronizer.NAME);
|
||||
clientTimeSynchronizer.syncTimeZone();
|
||||
clientTimeSynchronizer.syncTime();
|
||||
}
|
||||
|
||||
public TopLevelFrame getMainFrame() {
|
||||
|
@ -69,6 +69,9 @@ public interface DesktopConfig extends Config {
|
||||
@DefaultBoolean(true)
|
||||
boolean isUseServerTimeZone();
|
||||
|
||||
/**
|
||||
* @return true if application should synchronize its time source with server time
|
||||
*/
|
||||
@Property("cuba.desktop.useServerTime")
|
||||
@DefaultBoolean(true)
|
||||
boolean isUseServerTime();
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
|
||||
* Haulmont Technology proprietary and confidential.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.desktop.sys;
|
||||
|
||||
import com.haulmont.cuba.core.app.ServerInfoService;
|
||||
import com.haulmont.cuba.core.global.Configuration;
|
||||
import com.haulmont.cuba.core.sys.AppContext;
|
||||
import com.haulmont.cuba.desktop.App;
|
||||
import com.haulmont.cuba.desktop.DesktopConfig;
|
||||
import com.haulmont.cuba.gui.executors.BackgroundTask;
|
||||
import com.haulmont.cuba.gui.executors.BackgroundWorker;
|
||||
import com.haulmont.cuba.gui.executors.TaskLifeCycle;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import javax.annotation.ManagedBean;
|
||||
import javax.inject.Inject;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Maintains desktop client time zone and time.
|
||||
* <p/>
|
||||
* Time zone is taken from server.
|
||||
* Time is synchronized after each login. Additionally it can be performed by scheduled task (using spring scheduler).
|
||||
* <p/>
|
||||
* All requests to server are performed in background thread to avoid delays in UI.
|
||||
*
|
||||
* @author Alexander Budarov
|
||||
* @version $Id$
|
||||
*/
|
||||
@ManagedBean(ClientTimeSynchronizer.NAME)
|
||||
public class ClientTimeSynchronizer {
|
||||
public static final String NAME = "cuba_ClientTimeSynchronizer";
|
||||
|
||||
protected static final int TIMEOUT_SEC = 60;
|
||||
|
||||
private Log log = LogFactory.getLog(ClientTimeSynchronizer.class);
|
||||
|
||||
@Inject
|
||||
protected ServerInfoService serverInfoService;
|
||||
@Inject
|
||||
protected Configuration configuration;
|
||||
@Inject
|
||||
protected BackgroundWorker backgroundWorker;
|
||||
@Inject
|
||||
protected DesktopTimeSource timeSource;
|
||||
|
||||
/**
|
||||
* @see com.haulmont.cuba.desktop.DesktopConfig#isUseServerTimeZone()
|
||||
*/
|
||||
public void syncTimeZone() {
|
||||
boolean useServerTimeZone = configuration.getConfig(DesktopConfig.class).isUseServerTimeZone();
|
||||
if (useServerTimeZone) {
|
||||
backgroundWorker.handle(new ObtainServerTimeZoneTask()).execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.haulmont.cuba.desktop.DesktopConfig#isUseServerTime()
|
||||
*/
|
||||
public void syncTime() {
|
||||
if (!AppContext.isStarted()) {
|
||||
return;
|
||||
}
|
||||
boolean useServerTime = configuration.getConfig(DesktopConfig.class).isUseServerTime();
|
||||
boolean connected = App.getInstance() != null && App.getInstance().getConnection() != null
|
||||
&& App.getInstance().getConnection().isConnected();
|
||||
|
||||
if (useServerTime && connected) {
|
||||
backgroundWorker.handle(new UpdateTimeOffsetTask()).execute();
|
||||
}
|
||||
}
|
||||
|
||||
protected class ObtainServerTimeZoneTask extends BackgroundTask<Void, Void> {
|
||||
protected ObtainServerTimeZoneTask() {
|
||||
super(TIMEOUT_SEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void run(TaskLifeCycle<Void> taskLifeCycle) throws Exception {
|
||||
TimeZone serverTimeZone = serverInfoService.getTimeZone();
|
||||
|
||||
TimeZone.setDefault(serverTimeZone); // works OK from any thread
|
||||
log.info("Time zone set to " + serverTimeZone);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected class UpdateTimeOffsetTask extends BackgroundTask<Void, Void> {
|
||||
public UpdateTimeOffsetTask() {
|
||||
super(TIMEOUT_SEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void run(TaskLifeCycle<Void> taskLifeCycle) throws Exception {
|
||||
long serverTime = serverInfoService.getTimeMillis();
|
||||
long timeOffset = serverTime - System.currentTimeMillis();
|
||||
|
||||
timeSource.setTimeOffset(timeOffset); // works OK from any thread
|
||||
log.info("Using server time, offset=" + timeOffset + "ms");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,18 +6,8 @@
|
||||
|
||||
package com.haulmont.cuba.desktop.sys;
|
||||
|
||||
import com.haulmont.cuba.core.app.ServerInfoService;
|
||||
import com.haulmont.cuba.core.global.Configuration;
|
||||
import com.haulmont.cuba.core.global.TimeSource;
|
||||
import com.haulmont.cuba.desktop.App;
|
||||
import com.haulmont.cuba.desktop.Connection;
|
||||
import com.haulmont.cuba.desktop.ConnectionListener;
|
||||
import com.haulmont.cuba.desktop.DesktopConfig;
|
||||
import com.haulmont.cuba.security.global.LoginException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -27,37 +17,14 @@ import java.util.Date;
|
||||
* @author krivopustov
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DesktopTimeSource implements TimeSource, ConnectionListener {
|
||||
public class DesktopTimeSource implements TimeSource {
|
||||
|
||||
protected Log log = LogFactory.getLog(getClass());
|
||||
|
||||
protected boolean useServerTime;
|
||||
|
||||
protected volatile long timeOffset;
|
||||
|
||||
@Inject
|
||||
protected ServerInfoService serverInfo;
|
||||
|
||||
public DesktopTimeSource() {
|
||||
App app = App.getInstance();
|
||||
if (app != null) // can be null in tests
|
||||
app.getConnection().addListener(this);
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setConfiguration(Configuration configuration) {
|
||||
useServerTime = configuration.getConfig(DesktopConfig.class).isUseServerTime();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void connectionStateChanged(Connection connection) throws LoginException {
|
||||
if (connection.isConnected() && useServerTime) {
|
||||
long serverTime = serverInfo.getTimeMillis();
|
||||
timeOffset = serverTime - System.currentTimeMillis();
|
||||
log.info("Using server time, offset=" + timeOffset + "ms");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Time offset (time difference between server and client machine).
|
||||
* It will be used to correct time obtained from system clock.
|
||||
*/
|
||||
// @GuardedBy(this)
|
||||
protected long timeOffset;
|
||||
|
||||
@Override
|
||||
public Date currentTimestamp() {
|
||||
@ -66,6 +33,15 @@ public class DesktopTimeSource implements TimeSource, ConnectionListener {
|
||||
|
||||
@Override
|
||||
public long currentTimeMillis() {
|
||||
return System.currentTimeMillis() + timeOffset;
|
||||
return System.currentTimeMillis() + getTimeOffset();
|
||||
}
|
||||
|
||||
/* Must be used to access time offset */
|
||||
protected synchronized long getTimeOffset() {
|
||||
return timeOffset;
|
||||
}
|
||||
|
||||
public synchronized void setTimeOffset(long timeOffset) {
|
||||
this.timeOffset = timeOffset;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user