I am connecting to Pusher server using JAVA code and the issue is the client (using Java Client library) disconnects after few seconds of making connection to the server and it does not reconnect itself.
Also, the connection status at the java-client shows is CONNECTED, as shown in the onConnectionStateChange() callback method but in the background it seems like it stays disconnected because when I tried pushing a request from the server java client did not receive anything but on reconnect (manually) I get the request.
Code:
#Component
#Slf4j
public class PosWebSocketClient {
private Pusher pusher;
private boolean isConnected = false;
private String pusherAppKey;
private Timer timer;
private Date activeTime;
private boolean isUserLoggedIn = false;
private PusherOptions pusherOptions;
public synchronized void init(String pusherAppKey) {
log.info("Initializing Pusher");
pusher = new Pusher(pusherAppKey/* , pusherOptions() */);
this.pusherAppKey = pusherAppKey;
this.isUserLoggedIn = true;
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
log.info("State changed to " + change.getCurrentState() + " from "
+ change.getPreviousState());
if (change.getCurrentState() == ConnectionState.CONNECTED) {
isConnected = true;
} else {
isConnected = false;
}
log.info("isConnected {}", isConnected);
}
#Override
public void onError(String message, String code, Exception e) {
log.info("Error while connecting to the server with {} {} {}", message, code, e.getMessage());
log.error("Exception: - ",e);
}
}, ConnectionState.ALL);
Channel channel = pusher.subscribe("*****");
channel.bind("any-event-1", sendDataListener());
channel.bind("any-event-2", receiveOrderListener());
channel.bind("any-event-3", logOutListener());
channel.bind("any-event-4", getOrderStatusListener());
activeTime = new Date();
/*
* if (timer == null) { timer = new Timer(); timer.schedule(new MyTask(), 0,
* 1000 * 60 * 2); }
*/
}
class MyTask extends TimerTask {
public void run() {
long idleTimeInMinutes = (new Date().getTime() - activeTime.getTime()) / (1000 * 60);
log.info("Pusher Idle Time {} ", idleTimeInMinutes);
if (isUserLoggedIn && idleTimeInMinutes >= 10 && StringUtils.isNotBlank(pusherAppKey)) {
log.info("Pusher idle time is greater than 10 mins, initializing again");
disconnect();
init(pusherAppKey);
}
}
}
private SubscriptionEventListener logOutListener() {
return new SubscriptionEventListener() {
#Override
public void onEvent(PusherEvent pusherEvent) {
}
};
}
private SubscriptionEventListener sendDataListener() {
return new SubscriptionEventListener() {
#Override
public void onEvent(PusherEvent pusherEvent) {
log.info("Received SendData event");
}
};
}
private SubscriptionEventListener receiveOrderListener() {
log.info("Received FetchOrder event");
return new SubscriptionEventListener() {
}
};
}
private SubscriptionEventListener getOrderStatusListener() {
log.info("Received SendStatus event");
return new SubscriptionEventListener() {
}
};
}
public synchronized void disconnect() {
// Disconnect from the service (or become disconnected my network conditions)
if (pusher != null && pusher.getConnection() != null) {
log.info("Disconnecting Pusher");
Channel channel = pusher.getChannel("*****");
channel.unbind("any-event-1", sendDataListener());
channel.unbind("any-event-2", receiveOrderListener());
channel.unbind("any-event-3", logOutListener());
channel.unbind("any-event-4", getOrderStatusListener());
pusher.unsubscribe("*****");
pusher.disconnect();
}
}
public void restart() {
if (StringUtils.isNotBlank(pusherAppKey)) {
log.info("Restarting Pusher");
disconnect();
this.init(this.pusherAppKey);
}
}
/*
* private PusherOptions pusherOptions() { if (pusherOptions == null) {
* pusherOptions = new PusherOptions();
* pusherOptions.setMaxReconnectionAttempts(1000000); } return pusherOptions; }
*/
public boolean isConnected() {
return isConnected;
}
private void setPusherStatus() {
activeTime = new Date();
}
public void userLoggedOut() {
this.isUserLoggedIn = false;
}
}
The maven dependency used is
<dependency>
<groupId>com.pusher</groupId>
<artifactId>pusher-java-client</artifactId>
<version>2.0.0</version>
</dependency>
Can anyone please have a look and let me know the issue with the code or dependency or any property I am missing while making connection to the server ? TIA.
Related
I am new to xmpp/asmack in android, i'm looking for a method to listen on my own user state and presence changes on the server.
My target it's restore connection if lost.
I'm using presence by roster, which helps me getting the friends presence but actually not the current user itself.
Any help would be appreciated :)
Best regards,
You have to enable a ReconectionManager.
Example:
XmppManager.config = XMPPTCPConnectionConfiguration.builder()
.setServiceName(serverName)
.setHost(server)
.setPort(port)
.build();
connection = new XMPPTCPConnection(config);
ConnectionListener connectionListener = new ConnectionListener(){...}; //
connection.addConnectionListener( connectionListener );
int RECONNECTION_ATTEMPT_SECONDS = 60;
ReconnectionManager.getInstanceFor(connection).enableAutomaticReconnection();
ReconnectionManager.getInstanceFor(connection).setFixedDelay( RECONNECTION_ATTEMPT_SECONDS );
ReconnectionListener looks like this:
public class ReconnectionListener implements ConnectionListener
{
#Override
public void reconnectionSuccessful()
{
System.out.println( "Connection to chat server restored - You are again online" );
//additional foo when connection restored
}
#Override
public void reconnectionFailed( Exception e )
{
System.out.println("Impossible to reconnect, Chat Server seems to be still unavailable" );
}
#Override
public void reconnectingIn( int seconds )
{
System.out.println( "reconnectingIn fired "+seconds);
}
#Override
public void connectionClosedOnError( Exception e )
{
System.out.println("Connection closed, Chat Server become unavailable" );
//additional foo when connection lost (message to user ?)
}
#Override
public void connectionClosed()
{
// "XMPP connection was closed.");
System.out.println( "Connection closed, Chat Server become unavailable");
}
#Override
public void connected( XMPPConnection connection )
{
System.out.println("connected fired - reconnection management enabled");
}
#Override
public void authenticated( XMPPConnection connection, boolean resumed )
{
System.out.println("authenticated fired");
}
}
If that helped, please don't forget to accept the answer :)
To realize the automatic reconnection, you should utilize the ReconnectionManager, and implement the interface ConnectionListener to get the notification.
Details can be refered in https://ramzandroidarchive.wordpress.com/2016/03/14/handling-connection-break-issue-in-smack-4-1/
There exist another way to reconnect by using a timer:
public class TaxiConnectionListener implements ConnectionListener {
private Timer tExit;
private String username;
private String password;
private int logintime = 2000;
#Override
public void connectionClosed() {
Log.i("TaxiConnectionListener", "disconnect");
XmppConnection.getInstance().closeConnection();
tExit = new Timer();
tExit.schedule(new timetask(), logintime);
}
#Override
public void connectionClosedOnError(Exception e) {
Log.i("TaxiConnectionListener", "failed to disconnect");
boolean error = e.getMessage().equals("stream:error (conflict)");
if (!error) {
XmppConnection.getInstance().closeConnection();
tExit = new Timer();
tExit.schedule(new timetask(), logintime);
}
}
class timetask extends TimerTask {
#Override
public void run() {
username = Utils.getInstance().getSharedPreferences("taxicall",
"account", MainActivity.context);
password = Utils.getInstance().getSharedPreferences("taxicall",
"password", MainActivity.context);
if (username != null && password != null) {
Log.i("TaxiConnectionListener", "logining");
if (XmppConnection.getInstance().login(username, password)) {
Log.i("TaxiConnectionListener", "logined");
} else {
Log.i("TaxiConnectionListener", "reconnect");
tExit.schedule(new timetask(), logintime);
}
}
}
}
#Override
public void reconnectingIn(int arg0) {
}
#Override
public void reconnectionFailed(Exception arg0) {
}
#Override
public void reconnectionSuccessful() {
}
}
You need add a connection listener in your logining method:
TaxiConnectionListener connectionListener = new TaxiConnectionListener();
getConnection().addConnectionListener(connectionListener);
Remove listener in disconnection method:
connection.removeConnectionListener(connectionListener);
My scheme: ajax long polling to Tomcat. Tomcat executes selenium "operations".
Im trying to execute selenium scenario from tomcat.
Its working ok but i need to get logs back to js client.
Javascript client partially receives messages from server when selenium working.
Inside some selenium operations im using Thread.sleep(). Maybe mistakes because of this ?
Please tell me why messages partially received (i think) by client
Here is ServerInfoLogger. BaseLogger outputs messages to console and file
public class ServerInfoLogger extends BaseLogger {
public ServerSession clientServerSession;
protected void logToClient(String message) {
super.log(message);
sendMessage(message);
}
// Server.serverSession and Server.clientServerSession not null but messages partially not received by client
private void sendMessage(String message) {
// send message to client
if (Server.serverSession!=null && Server.clientServerSession!=null) {
Server.clientServerSession.deliver(Server.serverSession, "/message", message);
} else {
System.err.println("Server error. Server.serverSession=" + Server.serverSession + " clientServerSession=" + clientServerSession);
}
}
}
Here is selenium scenario
public class Task extends ServerInfoLogger {
public static boolean datesAvailable = false;
private TaskParser parser = new TaskParser();
protected ArrayList<Step> steps = new ArrayList<>();
private WebDriver webDriver;
protected int currentStepIndex = 0;
protected Step currentStep;
private WebDriverFactory webDriverFactory = new WebDriverFactory();
private int currentTryout = 1;
private int maxTryouts = 40;
public Task(ServerSession clientServerSession, String taskData) {
this.clientServerSession = clientServerSession;
logToClient("new task"); // client always receives this message
steps = parser.parse(taskData);
logToClient("steps parsed. total: "+steps.size()); // client always receives this message
start();
}
protected void start() {
createWebDriver();
startStep();
}
protected void startStep() {
currentStep = steps.get(currentStepIndex);
currentStep.setWebDriver(webDriver);
currentStep.clientServerSession = clientServerSession;
boolean stepComplete = false;
try {
stepComplete = currentStep.start();
} catch (StepException e) {
logToClient(e.getMessage()+" step id: "+e.getStepId());
e.printStackTrace();
}
log("step complete = "+stepComplete);
if (stepComplete) {
onStepComplete();
} else {
onStepError();
}
}
private void onStepError() {
currentTryout++;
if (currentTryout > maxTryouts) {
destroyWebDriver();
logToClient("Max tryouts reached"); // client never receives this message
} else {
logToClient("Step not complete. Restarting task. currentTryout=" + currentTryout); // client partially receives this message
restart();
}
}
private void onStepComplete() {
currentStepIndex++;
if (currentStepIndex < steps.size()) {
startStep();
} else {
destroyWebDriver();
taskComplete();
}
}
private void destroyWebDriver() {
webDriver.quit();
webDriver = null;
}
private void taskComplete() {
logToClient("Task complete !!!"); // client **never** receives this message
TaskEvent taskEvent = new TaskEvent(TaskEvent.TASK_COMPLETE);
EventDispatcher.getInstance().dispatchEvent(taskEvent);
}
public void restart() {
logToClient("Task restart");
try {
setTimeout(Application.baseOperationWaitSecondsUntil);
new SwitchToDefaultContentOperation().execute();
} catch(OperationException exception) {
logToClient("Cannot get default content"); // client partially receives this message
}
currentStepIndex = 0;
startStep();
}
private void setTimeout(int seconds) {
webDriver.manage().timeouts().implicitlyWait(seconds, TimeUnit.SECONDS);
}
private void createWebDriver() {
webDriver = webDriverFactory.getDriver(BrowserType.CHROME).getDriver();
}
public int getCurrentStepIndex() {
return currentStepIndex;
}
}
Here is creation of logger
private void createLogger() {
Date currentDate = new Date();
String logFilePostfix = currentDate.getMonth()+"_"+currentDate.getDate()+"-"+currentDate.getHours()+"_"+currentDate.getMinutes()+"_"+currentDate.getSeconds();
logger = Logger.getLogger(appName);
logger.setUseParentHandlers(false);
FileHandler fh;
SimplestFormatter formatter = new SimplestFormatter();
try {
fh = new FileHandler("C:\\consultant\\logs\\log_"+logFilePostfix+".txt");
logger.addHandler(fh);
fh.setFormatter(formatter);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Selenium operation with Thread.sleep()
public class SwitchToMainFrameOperation extends BaseOperation {
private WebElement mainIframe;
private WebDriverWait wait;
#Override
public boolean execute() throws OperationException {
switchToRoot();
sleepThread();
log("switchToMainIFrame by xPath "+Page.getMainIframeXPath()); // log to console and file
wait = new WebDriverWait(webDriver, Application.baseOperationWaitSecondsUntil);
try {
mainIframe = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(Page.getMainIframeXPath())));
webDriver.switchTo().frame(mainIframe);
log("main frame switch OK"); // log to console and file
} catch(StaleElementReferenceException exception) {
log("main frame switch error. StaleElementReferenceException - trying again"); // log to console and file
wait = null;
sleepThread();
execute();
}
return true;
}
private void switchToRoot() {
log("switch to root");
webDriver.switchTo().defaultContent();
}
private void sleepThread() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I am looking for a java code for MQTT client that subscribes to a given topic, every message published on that topic should reach the client only once.I have written many codes and in all the cases messages are delivered properly to the client when it is connected to the broker but if the subscribed client disconnects from the broker for some time and then again connects back, it does not receive the messages that were sent during the time that it was not connected and I have set the clean session flag also as false but still its not working, the code that I used is given below
import org.fusesource.hawtbuf.*;
import org.fusesource.mqtt.client.*;
/**
* Uses an callback based interface to MQTT. Callback based interfaces
* are harder to use but are slightly more efficient.
*/
class Listener {
public static void main(String []args) throws Exception {
String user = env("APOLLO_USER", "admin");
String password = env("APOLLO_PASSWORD", "password");
String host = env("APOLLO_HOST", "localhost");
int port = Integer.parseInt(env("APOLLO_PORT", "61613"));
final String destination = arg(args, 1, "subject");
MQTT mqtt = new MQTT();
mqtt.setHost(host, port);
mqtt.setUserName(user);
mqtt.setPassword(password);
mqtt.setCleanSession(false);
mqtt.setClientId("newclient");
final CallbackConnection connection = mqtt.callbackConnection();
connection.listener(new org.fusesource.mqtt.client.Listener() {
long count = 0;
long start = System.currentTimeMillis();
public void onConnected() {
}
public void onDisconnected() {
}
public void onFailure(Throwable value) {
value.printStackTrace();
System.exit(-2);
}
public void onPublish(UTF8Buffer topic, Buffer msg, Runnable ack) {
System.out.println("Nisha Messages : " + msg);
System.out.println("Nisha topic" + topic);
System.out.println("Nisha Receive acknowledgement : " + ack);
String body = msg.utf8().toString();
if("SHUTDOWN".equals(body)) {
long diff = System.currentTimeMillis() - start;
System.out.println(String.format("Received %d in %.2f seconds", count, (1.0*diff/1000.0)));
connection.disconnect(new Callback<Void>() {
#Override
public void onSuccess(Void value) {
System.exit(0);
}
#Override
public void onFailure(Throwable value) {
value.printStackTrace();
System.exit(-2);
}
});
} else {
if( count == 0 ) {
start = System.currentTimeMillis();
}
if( count % 1000 == 0 ) {
System.out.println(String.format("Received %d messages.", count));
}
count ++;
}
}
});
connection.connect(new Callback<Void>() {
#Override
public void onSuccess(Void value) {
System.out.println("connected in :::: ");
Topic[] topics = {new Topic(destination, QoS.AT_MOST_ONCE)};
connection.subscribe(topics, new Callback<byte[]>() {
public void onSuccess(byte[] qoses) {
}
public void onFailure(Throwable value) {
value.printStackTrace();
System.exit(-2);
}
});
}
#Override
public void onFailure(Throwable value) {
value.printStackTrace();
System.exit(-2);
}
});
// Wait forever..
synchronized (Listener.class) {
while(true)
Listener.class.wait();
}
}
private static String env(String key, String defaultValue) {
String rc = System.getenv(key);
if( rc== null )
return defaultValue;
return rc;
}
private static String arg(String []args, int index, String defaultValue) {
if( index < args.length )
return args[index];
else
return defaultValue;
}
}
Am I doing something wrong here?
it does not receive the messages that were sent during the time that it was not connected
MQTT does not retain all messages. If the client goes offline, undelivered messages are lost. The retain mechanism retains only the last message published to a topic.
You can read more in the specs point 3.3.1.3 RETAIN
user-a sends a subscription request to user-b. Subscription mode has been set to accept_all. Also, packet listener has been registered for both the users.
When user-a sends a request to user-b this method is called :
private void searchUser(java.awt.event.ActionEvent evt) {
try {
String userToSearch = jTextField1.getText();
if(!xmppParamInit) {
initUXmppP();
xmppParamInit = true;
}
Presence subscribe = new Presence(Presence.Type.subscribe);
userToSearch += "#localhost";
subscribe.setTo(userToSearch);
ofConnection.sendPacket(subscribe); // Send the 'subscribe' packet
}catch(Exception exc) {
exc.printStackTrace();
}
}
Prior to this method, following are called :
private void startPLThread() { // start packet-listener-thread
Runnable r = new Runnable() {
#Override
public void run() {
startPL();
}
};
new Thread(r,"packet listener thread").start();
}
private void startPL() {
PacketListener pListener = new PacketListener() {
#Override
public void processPacket(Packet packet) {System.out.println("Inside process packet");
if(packet instanceof Presence) {
Presence presence = (Presence) packet;
Presence subscription = new Presence(Presence.Type.subscribe);
subscription.setTo(presence.getFrom());
System.out.println("presence.getFrom : " + presence.getFrom());
ofConnection.sendPacket(subscription);
}
}
};
PacketFilter pFilter = new PacketFilter() {
#Override
public boolean accept(Packet packet) {
return true;
}
};
ofConnection.addPacketListener(pListener, pFilter);
}
The problem is user-a can see user-b in his roster but user-b cannot see user-a in its roster. I do not understand the reason for this. What could be the problem ?
Subscription mode has been set to accept_all in this method that is called from within search user :
private void initUXmppP() { // Initialize user-xmpp-parameters
Roster roster = ofConnection.getRoster();
roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
}
It is a GUI application and I tried keeping both the users online
I have an application in Eclipse RCP where I want to fire a function called 'LogOutUser()' if the user leaves his/ her application idle for, say, five minutes.
How do I go about doing this?
I don't know if the RCP framework supports this internally. However, I wrote my own "helper" class, which is a singleton client session manager. Eclipse won't know natively how you connect to your datasource. In my case I am connecting using EJB3 calls and listening to JMS queues and topics.
My class was written to detect when the datasource or "server" went down. It would also reconnect when the server came up. The server inactivity is detected by listening to heartbeat DTO's sent by the server. This feedback is useful to present to the user. I have adapted this class to cater for user interface inactivity.
The class is quite simple. It is a singleton, so it can be called simply at any point in your client-side RCP application. The heartbeat uses an observer and so you will have to add a HeartBeatEventListener to hook into this functionality. You can adapt the class to do the same for the user interface inactivity. However, I have just provided an updateUserInterfaceActivity() method which you must call when there is user activity. Perhaps this can be hooked into a global mouse and a global keyboard event handler.
I have also added a TrayItem to update the user...
Here is the class:
package com.kingsleywebb.clientsessionmanagement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.swt.widgets.TrayItem;
import com.kingsleywebb.clientsessionmanagement.entity.HeartbeatDTO;
public class ClientSessionManagement implements HeartbeatEventListener {
private static final Image IMG_CONNECTED = null; // Set this to a "connected image"
private static final Image IMG_DISCONNECTED = null; // Set this to a "disconnected image"
private static final long CONNECTION_INACTIVITY_TIME_MS = 30000L; // 30 seconds
private static final long USER_INTERFACE_INACTIVITY_TIME_MS = 300000L; // 5 minutes
private static final Log LOG = LogFactory.getLog(ClientSessionManagement.class);
private static ClientSessionManagement theInstance = null;
private static long connectionTimestamp = 0;
private static long userInterfaceActivityTimestamp = 0;
private synchronized static void createInstance() {
if (theInstance == null) {
theInstance = new ClientSessionManagement();
}
}
public static ClientSessionManagement getInstance() {
if (theInstance == null) {
createInstance();
}
return theInstance;
}
private ClientSessionManagement() {
this.connectionListenerList = new ArrayList<ConnectionListener>();
updateConnectionTimestamp();
Cron cron = new Cron();
Thread cronThread = new Thread(cron);
cronThread.start();
}
private boolean connected = true;
private ToolTip toolTipConnected;
private ToolTip toolTipDisconnected;
private TrayItem trayItem = null;
private String appName = null;
private String version = null;
private String whiteLabel = null;
private String userName = null;
private String deskName = null;
private String serverName = null;
private String userMnemonic = null;
private MenuItem miShowPopups;
private MenuItem miSoundBeep;
private List<ConnectionListener> connectionListenerList;
private void updateConnectionTimestamp() {
ClientSessionManagement.connectionTimestamp = System.currentTimeMillis();
}
private synchronized long getLastHeartbeatInMsAgo() {
return System.currentTimeMillis() - ClientSessionManagement.connectionTimestamp;
}
public synchronized void updateHeartbeat() {
updateConnectionTimestamp();
}
public synchronized void checkHeartbeatInterval() {
if (getLastHeartbeatInMsAgo() < CONNECTION_INACTIVITY_TIME_MS) {
showConnected();
}
else {
showDisconnected();
}
}
private void updateUserInterfaceActivityTimestamp() {
ClientSessionManagement.userInterfaceActivityTimestamp = System.currentTimeMillis();
}
private synchronized long getLastUserInterfaceActivityInMsAgo() {
return System.currentTimeMillis() - ClientSessionManagement.userInterfaceActivityTimestamp;
}
public synchronized void updateUserInterfaceActivity() {
updateUserInterfaceActivityTimestamp();
}
public synchronized void checkUserInterfaceActivityInterval() {
if (getLastUserInterfaceActivityInMsAgo() > USER_INTERFACE_INACTIVITY_TIME_MS) {
logoutUser();
}
}
private void logoutUser() {
// Implement logout functionality here
}
private void showConnected() {
if (!connected) {
connected = true;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// Update icon
if (trayItem != null) {
trayItem.setImage(ClientSessionManagement.IMG_CONNECTED);
trayItem.getToolTip().setVisible(false);
trayItem.setToolTip(toolTipConnected);
trayItem.getToolTip().setVisible(true);
}
// Update hover tooltip
updateHoverTooltip();
}
});
notifyConnectionListeners();
}
}
private void showDisconnected() {
if (connected) {
connected = false;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// Update icon
if (trayItem != null) {
trayItem.setImage(ClientSessionManagement.IMG_DISCONNECTED);
trayItem.getToolTip().setVisible(false);
trayItem.setToolTip(toolTipDisconnected);
trayItem.getToolTip().setVisible(true);
}
// Update hover tooltip
updateHoverTooltip();
}
});
notifyConnectionListeners();
}
}
private void updateHoverTooltip() {
if (trayItem != null) {
// Application info
String applicationInfo = null;
if (appName != null && version != null && whiteLabel != null) {
// appName* | version | whitelabel
applicationInfo = " Application: " + " " + appName + " " + version + " [" + whiteLabel + "]\r\n";
}
// User info
String userInfo = null;
if (userName != null && deskName != null && serverName != null) {
userInfo = " User: " + " " + userName + " (" + deskName + ") on " + serverName + "\r\n";
}
// Connection info
String connectionInfo = connected ? " Server Connected" : " SERVER DISCONNECTED!!!";
String status = connectionInfo + "\r\n\r\n" + (applicationInfo != null ? applicationInfo : "") +
(userInfo != null ? userInfo : "");
trayItem.setToolTipText(status);
LOG.info(status);
}
}
public void setTrayItem(Shell shell, TrayItem trayItem) {
this.trayItem = trayItem;
/*
* Property files to persist these settings - removed for simplicity
*
* final WorkstationProperties p = WorkstationProperties.getInstance();
* boolean showNotificationPopups = !"No".equalsIgnoreCase(p.getProperty("notifications.showNotificationPopups"));
* boolean soundNotificationBeep = !"No".equalsIgnoreCase(p.getProperty("notifications.soundNotificationBeep"));
*/
boolean showNotificationPopups = true;
boolean soundNotificationBeep = true;
final Menu menu = new Menu (shell, SWT.POP_UP);
miShowPopups = new MenuItem (menu, SWT.CHECK);
miShowPopups.setSelection(showNotificationPopups);
miShowPopups.setText("Show Notification Popups");
miShowPopups.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event event) {
LOG.info("notifications.showNotificationPopups = " + miShowPopups.getSelection());
// Property files to persist these settings - removed for simplicity
//p.setProperty("notifications.showNotificationPopups", miShowPopups.getSelection() ? "Yes" : "No");
}
});
miSoundBeep = new MenuItem (menu, SWT.CHECK);
miSoundBeep.setSelection(soundNotificationBeep);
miSoundBeep.setText("Play Notification Beep");
miSoundBeep.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event event) {
LOG.info("notifications.soundNotificationBeep = " + miSoundBeep.getSelection());
// Property files to persist these settings - removed for simplicity
//p.setProperty("notifications.soundNotificationBeep", miSoundBeep.getSelection() ? "Yes" : "No");
}
});
this.trayItem.addListener (SWT.MenuDetect, new Listener () {
public void handleEvent (Event event) {
menu.setVisible (true);
}
});
toolTipConnected = new ToolTip(shell, SWT.BALLOON);
toolTipConnected.setText((appName != null ? appName : "<Application Name>") + " Status");
toolTipConnected.setMessage("Connected to server.");
toolTipConnected.setLocation(600, 600);
toolTipConnected.setVisible(false);
toolTipDisconnected = new ToolTip(shell, SWT.ICON_WARNING);
toolTipDisconnected.setText((appName != null ? appName : "<Application Name>") + " Status");
toolTipDisconnected.setMessage("DISCONNECTED from server.");
toolTipDisconnected.setLocation(500, 500);
toolTipDisconnected.setVisible(false);
this.trayItem.setToolTip(toolTipConnected);
}
public boolean isShowPopups() {
return miShowPopups.getSelection();
}
public boolean isSoundBeep() {
return miSoundBeep.getSelection();
}
public void setAppName(String appName) {
this.appName = appName;
}
public void setVersion(String version) {
this.version = version;
}
public void setWhiteLabel(String whiteLabel) {
this.whiteLabel = whiteLabel;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setDeskName(String deskName) {
this.deskName = deskName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
updateHoverTooltip();
}
public String getUserMnemonic() {
return userMnemonic;
}
public void setUserMnemonic(String userMnemonic) {
this.userMnemonic = userMnemonic;
}
public void heartbeatArrived(HeartbeatDTO heartbeatDTO) {
updateHeartbeat();
}
public boolean isConnected() {
return connected;
}
public boolean addConnectionListener(ConnectionListener connectionListener) {
return connectionListenerList.add(connectionListener);
}
public boolean removeConnectionListener(ConnectionListener connectionListener) {
return connectionListenerList.remove(connectionListener);
}
public void notifyConnectionListeners() {
for (Iterator<ConnectionListener> i = connectionListenerList.iterator(); i.hasNext();) {
ConnectionListener connectionListener = i.next();
if (connected) {
connectionListener.connected();
}
else {
connectionListener.disconnected();
}
}
}
/**
*
* #author Kingsley Webb
*
* Check heartbeat interval periodically display warning to user accordingly.
*/
class Cron implements Runnable {
public void run() {
// Wait 15s extra before 1st check
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
LOG.error(e);
}
while (true) {
// Check every 5s - increase for better performance, but you get the idea...
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
LOG.error(e);
}
checkHeartbeatInterval();
checkUserInterfaceActivityInterval();
}
}
}
}
Some other supporting classes:
package com.kingsleywebb.clientsessionmanagement;
public interface ConnectionListener {
public void connected();
public void disconnected();
}
package com.kingsleywebb.clientsessionmanagement;
import com.kingsleywebb.clientsessionmanagement.entity.HeartbeatDTO;
public interface HeartbeatEventListener {
public void heartbeatArrived(HeartbeatDTO heartbeatDTO);
}
If you take a look in the bundle org.eclipse.ui.ide.application there is a class org.eclipse.ui.internal.ide.application.IDEIdleHelper which tries to perform gc after a interval of user inactivity. Probably you can reuse the logic that detects the inactivity
I usually use a Display.addFilter(eventType, listener) for the event types that should keep the session alive combined with a Display.timerExec(milliseconds, runnable) that is run periodically and tests for the last interesting event.
I use milliseconds = 5000 so the period is 5 min up to 5 min 5 sec before the user is logged out (or whatever...). Also I listener for the SWT event types (in 3.7) KeyDown, KeyUp, MouseDown, MouseUp, MouseVerticalWheel, MouseHorizontalWheel MouseDoubleClick, Touch, Gesture, Activate, Iconify, Deiconify, Move, and Resize.