Eclipse RCP application - how to detect when application is idle? - java

I am writing an Eclipse RCP application that will have other plugin contributions besides my own, and need to determine when the application is idle (i.e. no activity for a period of time, application is minimized, etc.), and when that changes (i.e. application is brought back to the foreground, a mouse is clicked, etc.).
The problem I'm having is that I was going to capture all application keystrokes and mouse moves/clicks...using that to reset a timer, and when the timer is hit, then some idle processing can occur (i.e. informing a server of the idleness - and then again when we switch to active - nothing intensive). However, the application window shell does not receive child events for the various views, etc. so either I'm missing something, or this is the wrong approach.
Can anyone offer a solution? I'm not looking for system-wide idleness - just application idleness.
Thanks.

The Eclipse IDE already has something similar to perform Garbage Collection, take a look at the class org.eclipse.ui.internal.ide.application.IDEIdleHelper in Bundle org.eclipse.ui.ide.application

Maybe that
display.addFilter(SWT.MouseDown, new Listener() {
#Override
public void handleEvent(Event event) {
}
});
is what you're looking for (you can add other events, too)?
This is executed before event handling is done component wise...
But its use is not generally recommended - it should be a very restricted use case, so.

You can use the fact that the readAndDispatch method will return false when there are no more messages to process. Something like this:
long lastActivityAt = 0;
int idleThresholdSecs = 5;
while (true)
{
while (display.readAndDispatch())
{
lastActivityAt = System.nanoTime();
}
if (System.nanoTime() - lastActivityAt > idleThresholdSecs * 1000 * 1000 * 1000)
{
// we have been idle for at least "idleThresholdSecs"
...
}
else
{
Thread.sleep(50);
}
}

Related

Start performing an action every minute after getting to a web page

I am developing a Java web application using Spring.
What I would like to do is that after the user gets to a page, the code starts running a function every 10 seconds, keeping track on the time the last action was performed.
I tried to do so with a Scheduler but it starts running immediately - and not only after the user gets to a page.
#Scheduled(fixedRate = 60000)
public void run(String param) {
//just an example of action to be performed repeatedly
System.out.println("Previously performed action was " + new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(previousActionTime)) + " with " + param);
//update previousActionTime
previousActionTime.setSeconds(previousActionTime.getSeconds() + 10);
}
Moreover I don't know what it is a convenient way to store the time when the last action automated action was performed.
The scheduler should be somehow activated when browsing to the page:
#RequestMapping(value = "/hellopage", method = { RequestMethod.POST, RequestMethod.GET })
public String hellopage(HttpServletRequest request, HttpServletResponse response) {
// Activate scheduler
run(request.getParameter("param1"))
...
}
The scheduler (or whatever performs the automated actions) should stop as soon as the user gets again to the same web page triggering the automated actions and should run in background not blocking any other code from execution (to be precise, I cannot simply put a while loop with Sys.sleep in the function mapped to the page URL request why the page should do other things)
Any help?
Consider using ScheduledExecutorService.scheduleAtFixedRate for this as the Spring scheduler are independent of any users' request (which you have already observed and noted in question).
You may use shutdownNow to terminate the scheduler once the users' session is no longer valid / a new request is received. To achieve this you could maintain cache of previous executor(s) with user id (or any relevant information) to identify the instance which should be invalidated.
As an alternative you could use Timer and TimerTask if more fine grained control is required (however not recommended as noted here)
There are two common ways of achieving this.
The first is to run your timer client-side, in JavaScript, and then runs an AJAX/websocket/whatever call. This has many advantages - once the user navigates away from your site, the timer will stop, and you're not tying up server-side resources so your application will scale much more cleanly. This is by far the cleanest solution if your timer is linked to a single user.
The second is to use a message queue; pop a message on the queue and have an asynchronous process checking those messages, ideally aggregating multiple client sessions in a single database request. You need to figure out how to detect sessions timing out and remove the message from the message queue.
This approach is best when your timer is looking at information that's not tightly connected to the current user.

JUnitTest for Karaf Startup

I want to write a JUnitTest, which ensures that my Karaf Server is started fine and all (needed) Bundles are installed and active.
For this I have a Test, calling a helper method "assertBundleState" which ensures, that the given Bundle is in the given State. The test looks like following:
#Test (timeout=30000L)
public void testBundlesStarted() throws Exception {
assertBundleState("bundle.Name", BundleLifecycleState.Active);
... <other bundles in similar way>
}
This worked fine in the past. The timeout was never reached.
Unfortunately I now have to load a bundle, which need a bit longer for startup. So the Bundles are not yet started, when the test is executed. And so the test fails.
I have tried it with a sleep in a BeforeClass method, but I am not really happy with this solution. Because I can't ensure that the given sleep time is enough on every machine at every time. So I am looking for some event-based solution to interact with Karaf.
#BeforeClass
public static void init() throws Exception {
Thread.sleep(120000L);
}
Does anybody have an idea how I can solve it in a better way?
Thanks
It sounds like assertBundleState can successfully determine whether the Karaf server has started and 'is ready'. But the issue is that you don't know how long to wait before checking this; if you don't wait long enough you risk a false negative, if you wait too long then your build elapsed time is falsely prolonged.
I presume you cannot register some sort of listener or callback hook which the Karaf server will invoke when it 'is ready'. Indeed, even if that was possible you would still have to cater for the failure case i.e. where the Karaf server does not start (and hence could never invoke a listener).
So, I think you just have to wait for the Karaf server to become available and hide the ugliness of Thread.sleep calls and the potential lost time in waiting too long. You could use Awaitility to tick those boxes. For example:
#Test
public void aTest() {
// run your test
// this will wait until Karaf is available for at most 10 seconds
// and will check every 100ms so if Karaf becomes available earlier
// than 10 seconds then the test will complete almost as soon as
// it becomes available but if Karaf does not become available
// within 10 seconds then the test will fail
await().atMost(10, SECONDS).until(karafIsAvailable());
// assert
// ...
}
private Callable<Boolean> karafIsAvailable() {
return new Callable<Boolean>() {
public Boolean call() throws Exception {
// return true if your condition has been met
// e.g. assertBundleState
return ...;
}
};
}

JavaFX Block the UI (and the code) until a server call is finished

This topic is around in countless articles of "not blocking the JavaFX UI during a long lasting call into something time consuming (server)". I know that and I googled and tried a lot.
Most of the "Internet" explains that long lasting calls caused by JavaFX events need to be made in an extra thread. After the thread is finished, you update the FX UI with the results via Platform.runLater(). Most of the FX Libraries encapsulate this with sophisticated code constructs (really cool stuff).
My current problem with it is: We are migrating a Swing rich client to JavaFX. It is a huge one, so we have to constantly include/replace JavaFX UI into it, until it is a full FX client.
There is some functionality in the client that does a server call and has to wait before the user can continue with his work.
The server uses JEE6 with stateless session beans and interfaces. The interfaces are known to the client and with a little library of our own, we implemented a little proxy hiding away the communication layer from the client.
The client just creates a "RemoteProxy" with the library then just calling the remote interface and the library propagates the call to the server. The method is called and the result or Exception transported back to the client. For the client this appears like a local call.
Here is the problem. A typical code fragment looks like this:
...
ServerRemoteInterface myServerRemoteProxy = Helper.getProxyForInterface(ServerRemoteInterface.class) ;
...
ComplexResult result = myServerRemoteProxy.doThingsOnServer(SerializableParameter p1 ...)
doSomethingUsefull() ;
The call to the server is triggered in the Swing UI thread (by a listener). It stops the execution of the program (Listener Code) although it is done in an extra thread. "doSomethingUsefull()" is called after the server got back. The developer does not have to take care about threading here.
How is it accomplished? By using the "Spin Library" (http://spin.sourceforge.net/).
It does some clever tricks with the Swing EDT.
An alternative would be to use a modal Dialog, but we decided not not have an extra window, but have a glasspane disabling some UI components instead.
So long explanation and short question...
Is there something similar for JavaFX helping us to seamlessly call a server, stop the program execution until it got back and NOT blocking the JavaFX UI? Best would be if it can work together with Java Swing parts of code.
EDIT... Adding an very compressed example for demonstration of the use with hidden JDialog.
We need the server remote interface. Any interface will do.
public interface ServerRemoteInterface
{
public String method1() ; // String result in our case for test purposes
public String method2() ; // Exceptions would also be possible.
}
Then we need the Proxy Invocation Handler
public class ServerProxy implements InvocationHandler
{
public Object result;
JDialog modalDialog = new JDialog((Frame)null, true);
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
ServerCallHelper serverThread = new ServerCallHelper(args, method) ;
modalDialog.setLocation(4000, 5000); // as if using Spin library. Here we use the dialog to block in a location off the screen.
serverThread.start();
modalDialog.setVisible(true) ;
return result;
}
class ServerCallHelper extends Thread
{
Object[] args;
Method method;
public ServerCallHelper(Object[] args, Method method)
{
this.args = args;
this.method = method;
}
public void run()
{
// do a server call via rmi or tunnel it via http, REST or whatever and provide the call parameters. On the server side there must be a receiver propagating the call to the wanted session bean.
// here we just do a simulation
try
{
Thread.sleep(3000);
} catch (InterruptedException e)
{
// interupt is ok here.
}
// now hand the result from the call back. we simulate a fix result
// We also could have caught the Exception and deal with it.
result = "Simulated Result" ;
// Since we are in the worker thread => inform EDT To close the dialog.
SwingUtilities.invokeLater(()->modalDialog.setVisible(false));
}
}
}
And finally some code to show the functionality
public class SampleUI extends JFrame
{
JButton serverCallButton = new JButton("Call server") ;
JLabel resultLabel = new JLabel("No result so far") ;
public SampleUI()
{
JPanel cont = new JPanel() ;
cont.add(serverCallButton) ;
cont.add(resultLabel) ;
this.setContentPane(cont);
serverCallButton.addActionListener((e)->processServerButtonCall());
}
private void processServerButtonCall()
{
ServerRemoteInterface serverAccess = (ServerRemoteInterface) Proxy.newProxyInstance(SampleUI.class.getClassLoader(), new Class[]{ServerRemoteInterface.class}, new ServerProxy());
String result = serverAccess.method1() ;
resultLabel.setText(result);
}
public static void main(String[] args)
{
SampleUI sampleUI = new SampleUI() ;
sampleUI.pack();
sampleUI.setVisible(true);
}
}
The example is very compressed but should show the principle. As a developer I do not have to take care that the call to the server is really a server call. To me it's like a local call. I do not even have to take care that I am in the EDT Thread, because i just am.
As I said it would work the same way in FX with a modal stage. I tried to set it to opaque 0.0 => It is not drawn anyway. This works.
The question remains: Are there ways to get around the extra JDialog or Stage ?
If I understood your intentions correctly, this is a use case for Future:
CompletableFuture.supplyAsync(() -> myServerRemoteProxy.doThingsOnServer(...))
.thenAccept(result -> doSomethingUseful(result));
Both the server call and doSomethingUseful will be executed in another thread, so you need to use Platform.runLater in doSomethingUseful if you want to access the scene graph.
Like Tomas said the solution is a nested Event Loop.
Currectly Java FX already has such an implementation:
com.sun.javafx.tk.Toolkit.getToolkit()
provides the methods enterNestedEventLoop and exitNestedEventLoop.
From the package name you can tell that it is sun(oracle) specific and should not be used. I read that people already asked Oracle to move it it "Platform" because it is a very useful feature.
Maybe we use it anyway :-)

inotify - how should I handle a full event queue?

I'm a Fedora user currently making use of inotify-java to implement directory polling. I have the following code snippet:
InotifyEventListener inel = new InotifyEventListener() {
#Override
public void filesystemEventOccurred (InotifyEvent ine) {
// code to handle - done
}
#Override
public void queueFull (EventQueueFull eqf) {
// this is the part when I'm not sure what I should do
}
}
You should perform the recovery actions specific to your application.
The "queue full" event happens if you're not retrieving events fast enough. Excess events are dropped, but you're notified of this.
You should think what would be the consequences for your application if you miss an event or two, and plan the recovery actions (e.g. clean the queue fast and do the rescan of the directory).

Activate a Java Servlet from another Java Servlet

My problem is this:Google App Engine allows cron jobs to be active for only 30 seconds before an DeadlineExceededException is thrown. And my app that isn't suited for the google app engine platform from this point of view, needs to call a time-consuming cron job.
One solution that I figured out was to calling another Servlet (Servlet2) and let that Servlet2 do the job for me, Servlet_2 would be a regular Java Servlet.To achieve that, I was thinking of creating a session from my cron job Servlet_1, call the other Servlet_2, test the session and then let the server do the jobs required and in the end invalidate the session.
The call from Servlet_1 should not be redirecting to Servlet_2, because that will put me back in square one again.
Now to my question: Do you think this will work? And if yes and an DeadlineExceededException acure, would the Servlet_2 stop from working as well, even if I put all the code in the destroy method of the Servlet_2?
my code:
//Servlet_1
try {
HttpSession session = request.getSession(true);
session.setAttribute("referingPage", "server is calling");
request.getRequestDispatcher("/Servlet_2.do").forward(request, response);
}catch(DeadlineExceededException e) {
e.printStackTrace();
}
//Servlet_2
#Override
public void destroy() {
HttpSession session = request.getSession(true);
String value = (String)session.getAttribute("referringPage");
if(value.equals("server is calling")) {
// Do the time demanding stuff
}
session.invalidate();
}
Would be grateful for an answer!
You only have 30 seconds to produce finish execution and there's no way around that. Doing a forward doesn't spawn a new thread or anything, it's still executing within the 30 second time limit.
I'd try to figure out some way to serialize what you're doing, or pause it and stick your state in memcache. When you start processing again, check memcache to see if you need to pick up form where you left off.
Google App Engine is working on long running background processes, and I hope then come out with a solution soon. I'm in the same boat.
Mark
Why not use a task queue. You put a task on the queue - it works for 29 seconds and then stops but, before it stops, it puts another task on the queue. As long as the payload has a marker to indicate where to restart then you have a chained set of tasks that can run for as long as you want to consume (and pay for) CPU.

Categories

Resources