Synchronize button action on richfaces - java

I want to execute only once the action linked to a button even if the user click several times on it.
There is my code :
public String myMethod() {
log.info("Call : myMethod");
if(getLock().tryLock()) {
try {
log.info("Lock");
}
finally {
log.info("unlock");
getLock.unlock();
return null;
}
}
else {
log.info("No permission");
return null;
}
}
My problem :
When I try this, the execution is the following :
Call : myMethod
Lock
Call : myMethod
No permission
unlock
Call : myMethod
Lock
unlock
It seems pretty normal but, all my clicks were made before the first action was done.
So my question is does richfaces has a scheduler and start the action when he wants?
Or someone knows a good way to do this correctly?
Thank you reading

You can use RichFaces queue to "combined" a number of clicks together and only fire one at the end.

Related

How to use FutureTask<V>, waiting for ui event?

I have an interface method which is supposed to return a Future object.
Future<Result> doSomething()
The implementation of this method shows some ui (javafx).
One of the ui elements has a listener, that needs to be called in order to receive the actual result, I need.
How do I achieve this?
Is there a better solution?
Here an example action I need to wait for:
// this is some framework method I cannot change
#Override
public Data execute(Data data) {
Future<Data> dataFuture = handler.doSomething(data);
// this should basically wait until the user clicked a button
return dataFuture.get();
}
// handler implementation
public Future<Data> doSomething(Data data) {
// the question is how to implement this part, to be able to
// return a future object
Button button = new Button("Wait until click");
// create thread that waits for the button click ?!????
// modify incoming data object when the button was clicked
// somehow create the Future object that's bound to the button click
return future;
}
This is what I want to achieve:
my method doSomething shows a new scene(ui) with a button on it
and returns immedeately the future object
future.get() waits until the user pressed the button
limitations: it has to be done with no extra library and on >=Java7
Use a javafx.concurrent.Task. It derives from FutureTask. There are extensive examples in the linked javadoc on Task usage.
Oracle also provide a tutorial which discusses Task usage:
Concurrency in JavaFX
I think this is what you want, but I may have understood the question, if so, please edit the question a bit to clarify requirements (perhaps with an mcve). The bit that makes me a little unsure is the part in your title "waiting for ui event?", I'm not quite sure what that means in this context.
This is a solution I was searching for. It's not very nice, since the Thread.sleep doesn't convince me.
but now you propably get an idea of what I want to achieve
// make sure this is not called on the ui thread
public Future<Data> doSomething(Data data) {
WaitingFuture future = new WaitingFuture(data);
Platform.runLater(() -> {
Button button = new Button("Wait until click");
button.setOnAction(future);
// show button on ui...
});
favouriteExecutorService.submit(future);
return future;
}
static class WaitingFuture extends Task<Data> implements EventHandler<ActionEvent> {
private Data data;
WaitingFuture(Data originalData) {
this.data = originalData;
}
private Data waitingData;
#Override
public void handle(ActionEvent event) {
waitingData = data.modify();
}
#Override
protected Data call() throws Exception {
while (waitingData == null) {
Thread.sleep(100);
}
return waitingData;
}
}

Delayed view rendering not working

Currently learning play! 2.0, I wanted to add an "opening" to my homepage : the first time a user connects to the homepage, an opening would display for a few seconds and then he would be automatically redirected to the real home page. This opening would not be shown again for the rest of the session.
For now that piece of code looks like :
public class Application extends Controller {
private static ScheduledExecutorService executor = executors.newSingleThreadScheduledExecutor();
public static Result home() {
boolean introSeen = Cache.get("introSeen") == null ? false : true;
if(introSeen) {
System.out.println("Cache good, sending you home !");
return ok(home.render(Configs.HOME));
//return redirect("/");
}
else {
Cache.set("introSeen", true, 2*60*60);
Runnable task = new Runnable(){
#Override
public void run() {
home();
executor.shutdown();
}
};
executor.schedule(task, 7, TimeUnit.SECONDS);
return ok(intro.render(Configs.HOME));
}
}
I've added the println to make sure the cache variable registration and the delayed task were working, and they do. But for an unknown reason, the code
return ok(home.render(Configs.HOME));
is not working and the intro view (intro) stays on screen.
I've tried to user redirect instead of "ok" too, but nothing so far.
Thanks for your help :)
Why don't you just use Meta refresh or some JavaScript technique to do that ?
You can use session cookie for checking if next time user should see the opening or target page.

How i can detect JasperViewer processing report time

we know jasper viewer need much time to process report according to the data that will display.
I want to handle it, with give the user loading information.
this my step :
Check ,is the viewer in process or done.
If in process, create JLabel and set text to "Loading report..."
If done, set text to "" or null
And the point 1 , i don't know How to check viewer is in generating process?
Please help me. Thank you :)
Make the call to viewReport() in a separate thread. Store an instance level AtomicBoolean, and set it to false once the report is done. In you client checking method, check this instance variable periodically to check if the report is done.
Example pseudocode:
public void YourClass {
private AtomicBoolean reportRunning;
...
private void getReport() {
new Thread() {
reportRunning = new AtomicBoolean(true);
JRViewer.viewReport();
reportRunning.set(false);
}.start();
}
// Call periodically and update UI
private boolean clientCheck() {
return reportRunning != null && reportRunning.get();
}

Clever asynchronous repaint in Java

I have a use-case coming from a GUI problem I would like to submit to your sagacity.
Use case
I have a GUI that displays a computation result depending on some parameters the user set in a GUI. For instance, when the user moves a slider, several events are fired, that all trigger a new computation. When the user adjust the slider value from A to B, a dozens of events are fired.
But the computation can take up to several seconds, whereas the slider adjustment can fire an event every few 100 ms.
How to write a proper Thread that would listen to these events, and kind of filter them so that the repaint of the results is lively? Ideally you would like something like
start a new computation as soon as first change event is received;
cancel the first computation if a new event is received, and start a new one with the new parameters;
but ensure that the last event will not be lost, because the last completed computation needs to be the one with last updated parameters.
What I have tried
A friend of mine (A. Cardona) proposed this low level approach of an Updater thread that prevents too many events to trigger a computation. I copy-paste it here (GPL):
He puts this in a class that extends Thread:
public void doUpdate() {
if (isInterrupted())
return;
synchronized (this) {
request++;
notify();
}
}
public void quit() {
interrupt();
synchronized (this) {
notify();
}
}
public void run() {
while (!isInterrupted()) {
try {
final long r;
synchronized (this) {
r = request;
}
// Call refreshable update from this thread
if (r > 0)
refresh(); // Will trigger re-computation
synchronized (this) {
if (r == request) {
request = 0; // reset
wait();
}
// else loop through to update again
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void refresh() {
// Execute computation and paint it
...
}
Every-time an event is sent by the GUI stating that parameters have been changed, we call updater.doUpdate(). This causes the method refresh() to be called much less.
But I have no control on this.
Another way?
I was wondering if there is another way to do that, that would use the jaca.concurrent classes. But I could not sort in the Executors framework what would be the one I should start with.
Does any of you have some experience with a similar use case?
Thanks
If you're using Swing, the SwingWorker provides capabilities for this, and you don't have to deal with the thread pool yourself.
Fire off a SwingWorker for each request. If a new request comes in and the worker is not done, you can cancel() it, and just start a new SwingWorker. Regarding what the other poster said, I don't think publish() and process() are what you are looking for (although they are also very useful), since they are meant for a case where the worker might fire off events faster than the GUI can process it.
ThingyWorker worker;
public void actionPerformed(ActionEvent e) {
if( worker != null ) worker.cancel();
worker = new ThingyWorker();
worker.execute();
}
class ThingyWorker extends SwingWorker<YOURCLASS, Object> {
#Override protected YOURCLASS doInBackground() throws Exception {
return doSomeComputation(); // Should be interruptible
}
#Override protected void done() {
worker = null; // Reset the reference to worker
YOURCLASS data;
try {
data = get();
} catch (Exception e) {
// May be InterruptedException or ExecutionException
e.printStackTrace();
return;
}
// Do something with data
}
}
Both the action and the done() method are executed on the same thread, so they can effectively check the reference to whether there is an existing worker.
Note that effectively this is doing the same thing that allows a GUI to cancel an existing operation, except the cancel is done automatically when a new request is fired.
I would provide a further degree of disconnect between the GUI and the controls by using a queue.
If you use a BlockingQueue between the two processes. Whenever the controls change you can post the new settings to the queue.
Your graphics component can read the queue whenever it likes and act on the arriving events or discard them as necessary.
I would look into SwingWorker.publish() (http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html)
Publish allows the background thread of a SwingWorker object to cause calls to the process() method, but not every publish() call results in a process() call. If multiple process calls are made before process() returns and can be called again, SwingWorker concatenates the parameters used for multiple publish calls into one call to process.
I had a progress dialog which displayed files being processed; the files were processed faster than the UI could keep up with them, and I didn't want the processing to slow down to display the file names; I used this and had process display only the final filename sent to process(); all I wanted in this case was to indicate to the user where the current processing was, they weren't going to read all the filenames anyway. My UI worked very smoothly with this.
Take a look at the implementation of javax.swing.SwingWorker (source code in the Java JDK),
with a focus on the handshaking between two methods: publish and process.
These won't be directly applicable, as-is, to your problem - however they demonstrate how you might queue (publish) updates to a worker thread and then service them in your worker thread (process).
Since you only need the last work request, you don't even need a queue for your situation: keep only the last work request. Sample that "last request" over some small period (1 second), to avoid stopping/restarting many many times every 1 second, and if it's changed THEN stop the work and restart.
The reason you don't want to use publish / process as-is is that process always runs on the Swing Event Dispatch Thread - not at all suitable for long running calculations.
The key here is that you want to be able to cancel an ongoing computation. The computation must frequently check a condition to see if it needs to abort.
volatile Param newParam;
Result compute(Param param)
{
loop
compute a small sub problem
if(newParam!=null) // abort
return null;
return result
}
To handover param from event thread to compute thread
synchronized void put(Param param) // invoked by event thread
newParam = param;
notify();
synchronized Param take()
while(newParam==null)
wait();
Param param = newParam;
newParam=null;
return param;
And the compute thread does
public void run()
while(true)
Param param = take();
Result result = compute(param);
if(result!=null)
paint result in event thread

Delaying SWT Table Refresh

We have a ViewerFilter for a TableViewer that is a little slow, so to try to give the impression of awesomeness, we wanted to have the viewer wait 500 milliseconds before refreshing the window (otherwise, it was blocking after every key stroke).
Not having any clue what I was doing, I tried creating a class that would check if System.currentTimeMillis() was greater then the time of the last key stroke + 500 from a different thread. This just caused an Invalid thread access exception to be thrown, so I'm lost.
Edit: I was able to use TableViewer.getTable().getDisplay().asyncExec() to sidestep the invalid thread problem, but I don't like my solution, and would love to hear other suggestions.
You might want to try to turn off redraw while updating the viewer.
Viewer.getControl().setRedraw(false);
// update
Viewer.getControl().setRedraw(true);
It can sometimes give a better user experience. You can also schedule a ui-job that you cancel when the user hits a new key or modifies the text. E.g.
class RefreshJob extends WorkbenchJob
{
public RefreshJob()
{
super("Refresh Job");
setSystem(true); // set to false to show progress to user
}
public IStatus runInUIThread(IProgressMonitor monitor)
{
monitor.beginTask("Refreshing", ProgressMonitor.UNKNOWN);
m_viewer.refresh();
monitor.done();
return Status.OK_STATUS;
};
}
and then reschedule the refresh in a separate job.
private RefreshJob m_refreshJob = new RefreshJob();
private Text m_filterText;
void hookModifyListener()
{
m_filterText.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
m_refreshJob.cancel();
m_refreshJob.schedule(500);
}
});
}
If the user hits the Enter key you can schedule a refresh job without the delay,
Just wrap your code in display.syncExec, something like this:
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// check refresh time
// refresh.
}
});
You may want to look in to asyncExec too, if syncExec does not meet your needs.

Categories