SwingWorker issue, method doInBackground not executed? - java

Sometimes the doInBackgorund() method of my SwingWorker seems not to be executed, it goes directly to the done() method without saving or printing anything on some of my clients machines, so i suppose it's a random thing , and i can't figure out why. Here 's my code :
public class saveCmdWorker extends SwingWorker<Integer, Integer> {
Order ord;
public saveCmdWorker(Order ord) {
this.ord = ord;
}
#Override
public Integer doInBackground() {
if(999 != ord.getCaissier().getIdCaissier())
saveCmd(ord); // database queries
else
JOptionPane.showMessageDialog(null,"Error",JOptionPane.WARNING_MESSAGE);
if(ord.isIsProd() == false){
try {
// print via serial port
Printer.print(ord, false, Restaurant.numCaisse);
} catch (Exception ex) {
PosO2.errorLogger.log(Level.SEVERE, "Printing error", ex);
}
}
try {
Printer.printFacture(ord, false);
if(btnDuplicata.getForeground() == Color.red)
Printer.printFacture(ord, true);
} catch (Exception ex) {
PosO2.errorLogger.log(Level.SEVERE, "Printing error", ex);
}
return 1;
}
#Override
protected void done() {
try {
btnDuplicata.setForeground(Color.black);
ARendre = 0.0;
ord.clear();
for (int j = 0; j < tab_paiement.size(); j++) {
tab_paiement.get(j).setVisible(true);
}
montantRestant.setBackground(Color.red);
} catch(Exception e) {
PosO2.errorLogger.log(Level.SEVERE, "Refresh Error", e);
}
}
}
I execute this worker via this actionlistener :
ActionListener encaissListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
worker = new saveCmdWorker(cmd);
worker.execute();
}
};
I don't have any logs available so i assume no exception is caught. I saw that a JOptionPane was fired in the doInBackground()(consider as ui modification in an other thread?) but the problem exists when the application doesn't go in the else statement. Can this be the cause of my problems? I don't have this bug on my computer, it just works fine.

As per the SwingWorker documentation (http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#execute()):
SwingWorker is only designed to be executed once. Executing a SwingWorker more than once will not result in invoking the doInBackground method twice.
So, it looks like you need to create a new instance of your subclass each time you want to run the execute method properly.

Related

FutureTask.get method is blocking forever, although I am setting it's value from another thread

I am trying to signal between two threads using the below FutureResult class which extends FutureTask class. When run the script, it prints the following result.
SENDING: 0
SENT: 0
POLL: FutureResult#513431
SIGNALLED: FutureResult#513431
Then the program hang up forever. I expect FutureResult instance should return the value from it's blocking get method. Then print the result in the console. But FutureResult.get is blocking forever.
import java.util.concurrent.*;
/**
* Created by someone on 20/08/2015.
*/
final public class FutureResult<T> extends FutureTask<T> {
private static final Object SS = "SS";
public FutureResult() {
super(() -> null);
}
public void signal(final T value) {
set(value);
}
public void signalError(final Throwable throwable) {
setException(throwable);
}
public static void main(String... args) throws Exception {
final ArrayBlockingQueue<FutureResult> queue = new ArrayBlockingQueue<>(1000000);
new Thread(() -> {
while (true) {
try {
final FutureResult poll = queue.take();
System.out.println("POLL: " + poll);
if (poll != null) {
poll.signal(SS);
System.out.println("SIGNALLED: " + poll);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 1; i++) {
final FutureResult<Object> result = new FutureResult<>();
System.out.println("SENDING: " + i);
queue.offer(new FutureResult());
try {
System.out.println("SENT: " + i);
result.get();
System.out.println("GOT : " + i);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}).start();
}
}
This is the problem:
queue.offer(new FutureResult());
You're setting the value on one FutureResult, but that's not the one you're waiting for. Just change that line to:
queue.offer(result);
and it works fine.
Looks like the confusion is in the use of FutureTask. FutureTask is designed as a Runnable; running it is necessary.
Honestly, based on the code, it looks like the custom code is implementing something similar to FutureTask. If the intent here is to learn to use FutureTask, then create a FutureTask instance with a "run" method, and then execute that run method. On completion of the run method, the FutureTask.get() will complete.

SWTException: Invalid thread access

I work on a wizard for creation of a java project and get a invalid thread access exception if I run it in the empty workspace for the first time. I try to implement my wizard similar to JavaProjectWizard, but I don't need the second page, so I try to perform finish from the first page and to initialize the second page in advance:
import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
public class SomeNewWizard
extends Wizard
implements INewWizard {
private SomeWizardPageTwo javaWizardPageTwo;
#Override
public void addPages() {
if (javaWizardPageTwo == null)
someWizardPageTwo = new SomeWizardPageTwo(newSeeAppWizardPageOne);
}
#Override
public boolean performFinish() {
/*line 109*/someWizardPageTwo .createProvisonalProject();
final IWorkspaceRunnable op = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor)
throws CoreException, OperationCanceledException {
try {
someWizardPageTwo.performFinish(new SubProgressMonitor(monitor, 1));
}
catch (InterruptedException e) {
throw new OperationCanceledException(e.getMessage());
}
finally {
monitor.done();
}
}
};
try {
rule = null;
Job job = Job.getJobManager().currentJob();
if (job != null)
rule = job.getRule();
IRunnableWithProgress runnable = new IRunnableWithProgress() {
#Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
JavaCore.run(op, rule, monitor);
}
catch (OperationCanceledException e) {
throw new InterruptedException(e.getMessage());
}
catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
getContainer().run(true, true, runnable);
}
catch (InvocationTargetException e) {
handleFinishException(getShell(), e);
return false;
}
catch (InterruptedException e) {
return false;
}
return true;
}
public class SomeWizardPageTwo
extends NewJavaProjectWizardPageTwo
{
private NewJavaProjectWizardPageOne mainPage;
public SomeWizardPageTwo(NewJavaProjectWizardPageOne mainPage)
{
super(mainPage);
this.mainPage = mainPage;
}
#Override
public IProject createProvisonalProject()
{
return super.createProvisonalProject();
}
#Override
protected IWizardContainer getContainer()
{
if (mainPage == null)
return null;
return mainPage.getWizard().getContainer();
}
}
The stacktrace can be found here.
The root of the issue seems that ImageDescriptorRegistry is created from the wrong thread because the corresponding IRunnableWithProgress runs forked. But I wonder why does it work for the normal JavaProjectWizard then? And the main question is: how to make it work for my wizard?
getContainer().run(true, true, runnable); causes the runnable to be executed in a separate thread. The first parameter fork is responsible therefore.
The call to javaWizardPageTwo.performFinish() atempts to access the UI thread and causes the invalid thread access exception.
If you set the fork parameter to false, the code will be executed on the current thread.
Why don't you call javaWizardPageTwo.performFinish() directly?
There is not a bug in Display.checkDevice.
Your call to NewJavaProjectWizardPageTwo.performFinish is running in a background thread, but the code is using ImageDescriptorRegistry which needs to be initialized on the User Interface thread.
This is intermittent because sometimes something else that you do will have already initialized the registry.

Java - synchronous callback

I have the following code which is executed asynchronously. I would like to make it synchronous in order to follow some logical flow but I cannot work out how.
You will see that scanning is set to true to indicate that the method is still working, at the beginning - I then initiate a findPrinters(...) command - this contains a DiscoveryHandler which runs asynchronously - foundPrinter() is called each time an item is discovered. discoveryFinished() is when the discovery process is successfully completed, and discoveryError(...) is called whenever an error occurs.
I rely on something being set in my DiscoveryHandler before I would like to return from this method. Hence why I have while (scanning) underneath it. But this feels like a hack to me, and not the correct way of doing things. I cannot get wait() and notify() working. Can someone tell me what the correct way to do this is please?
private boolean findPrinter(final Context ctx) {
try {
scanning = true;
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
scanning = false;
}
public void discoveryError(String arg0) {
scanning = false;
}
});
} catch (Exception ex) {
}
while (scanning) {}
return false;
}
You could do this with CountDownLatch, which might be the lightest synchronization primitive in java.util.concurrent:
private boolean findPrinter(final Context ctx) {
final CountDownLatch latch = new CountDownLatch(1);
final boolean[] result = {false};
...
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
...
public void discoveryFinished() {
result[0] = true;
latch.countDown();
}
public void discoveryError(String arg0) {
result[0] = false;
latch.countDown();
}
...
}
// before final return
// wait for 10 seconds for the response
latch.await(10, TimeUnit.SECONDS);
//return the result, it will return false when there is timeout
return result[0];
}
There are a bunch of ways you can do this and wait()/notify() is probably not the best since you probably want to return something from your async method. As such I suggest using something like a BlockingQueue. Here is a simplified example of how you can do this:
private boolean findPrinter(final Context ctx) {
final BlockingQueue<?> asyncResult = new SynchronousQueue<?>();
try {
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
public void foundPrinter(DiscoveredPrinter device) {
if (device instanceof DiscoveredPrinterBluetooth) {
DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device;
if (btDevice.friendlyName.startsWith("XXXX")) {
try {
connection = new BluetoothConnection(btDevice.address);
connection.open();
if (connection.isConnected()) {
address = btDevice.address;
}
} catch (Exception ex) {
}
}
}
}
public void discoveryFinished() {
asyncResult.put(true);
}
public void discoveryError(String arg0) {
asyncResult.put(arg0);
}
});
} catch (Exception ex) {
}
Object result = asyncResult.take();
if (result instanceof Boolean) {
return (Boolean) result;
} else if (result instanceof String) {
logError((String) result);
}
return false;
}
One problem with using SynchronousQueue here though is that if discoveryFinished()/discoveryError() is called more than once, then the thread executing the code asynchronously will block forever since the SynchronousQueue assumes there will be exactly one take() per every put() and will block if a put() is made without a corresponding take() or vice versa. So if in your case those methods can be called more than once you would probably use a different kind of BlockingQueue instead (see documentation).

How SwingWork works with EDT?

Well, i have the following code bellow that works fine, but i wanna understand how works the threads in this code.
private void jLabelInicioMovimentacaoMouseClicked(
java.awt.event.MouseEvent evt) {// GEN-FIRST:event_jLabelInicioMovimentacaoMouseClicked
jStatusBar1.setWaitState(false);
jStatusBar1.setWaitStartMessage("Pesquisando...");
jStatusBar1.setWaitState(true);
this.sw = new SwingWorker() {
#Override
public Object construct() {
try {
jGDataTextFieldDataInicial
.setValue(retornarPrimeiroDiaMovimentacao());
} catch (Exception e) {
e.printStackTrace();
JGOptionPane.showMessageDialog(FFormMain.this,
"Ocorreu um erro nas bibliotecas",
JGOptionPane.ERROR_MESSAGE);
}
return null;
}
#Override
public void finished() {
jStatusBar1.setWaitStartMessage("Finalizado");
jStatusBar1.setWaitState(false);
}
};
sw.start();
}// GEN-LAST:event_jLabelInicioMovimentacaoMouseClicked
So, my idea is: When I execute the jStatusBar1.setWaitState(false) (first line); this code is executed in EDT (Event Dispatcher Thread) instantly, and the others lines too.
But when I execute this.sw = new SwingWorker()... I am creating a new Thread (outside of EDT), when this "Outside Thread" finish, the method "finished()" is called from EDT and the jStatusBar1 is updated.
My concept is right ?

Telling a ThreadPoolExecutor when it should go ahead or not

I have to send a set of files to several computers through a certain port. The fact is that, each time that the method that sends the files is called, the destination data (address and port) is calculated. Therefore, using a loop that creates a thread for each method call, and surround the method call with a try-catch statement for a BindException to process the situation of the program trying to use a port which is already in use (different destination addresses may receive the message through the same port) telling the thread to wait some seconds and then restart to retry, and keep trying until the exception is not thrown (the shipping is successfully performed).
I didn't know why (although I could guess it when I first saw it), Netbeans warned me about that sleeping a Thread object inside a loop is not the best choice. Then I googled a bit for further information and found this link to another stackoverflow post, which looked so interesting (I had never heard of the ThreadPoolExecutor class). I've been reading both that link and the API in order to try to improve my program, but I'm not yet pretty sure about how am I supposed to apply that in my program. Could anybody give a helping hand on this please?
EDIT: The important code:
for (Iterator<String> it = ConnectionsPanel.list.getSelectedValuesList().iterator(); it.hasNext();) {
final String x = it.next();
new Thread() {
#Override
public void run() {
ConnectionsPanel.singleAddVideos(x);
}
}.start();
}
private static void singleAddVideos(String connName) {
String newVideosInfo = "";
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
newVideosInfo = newVideosInfo.concat(it.next().toString());
}
try {
MassiveDesktopClient.sendMessage("hi", connName);
if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
MassiveDesktopClient.sendMessage(newVideosInfo, connName);
}
} catch (BindException ex) {
MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
try {
Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
} catch (InterruptedException ex1) {
JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
ConnectionsPanel.singleAddVideos(connName);
return;
}
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
try {
MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
} catch (BindException ex) {
MassiveDesktopClient.println("Attempted to use a port which is already being used. Waiting and retrying...", new Exception().getStackTrace()[0].getLineNumber());
try {
Thread.sleep(MassiveDesktopClient.PORT_BUSY_DELAY_SECONDS * 1000);
} catch (InterruptedException ex1) {
JOptionPane.showMessageDialog(null, ex1.toString(), "Error", JOptionPane.ERROR_MESSAGE);
}
ConnectionsPanel.singleAddVideos(connName);
return;
}
}
}
Your question is not very clear - I understand that you want to rerun your task until it succeeds (no BindException). To do that, you could:
try to run your code without catching the exception
capture the exception from the future
reschedule the task a bit later if it fails
A simplified code would be as below - add error messages and refine as needed:
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(corePoolSize);
final String x = "video";
Callable<Void> yourTask = new Callable<Void>() {
#Override
public Void call() throws BindException {
ConnectionsPanel.singleAddVideos(x);
return null;
}
};
Future f = scheduler.submit(yourTask);
boolean added = false; //it will retry until success
//you might use an int instead to retry
//n times only and avoid the risk of infinite loop
while (!added) {
try {
f.get();
added = true; //added set to true if no exception caught
} catch (ExecutionException e) {
if (e.getCause() instanceof BindException) {
scheduler.schedule(yourTask, 3, TimeUnit.SECONDS); //reschedule in 3 seconds
} else {
//another exception was thrown => handle it
}
}
}
}
public static class ConnectionsPanel {
private static void singleAddVideos(String connName) throws BindException {
String newVideosInfo = "";
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
newVideosInfo = newVideosInfo.concat(it.next().toString());
}
MassiveDesktopClient.sendMessage("hi", connName);
if (MassiveDesktopClient.receiveMessage(connName).matches("hello")) {
MassiveDesktopClient.sendMessage(newVideosInfo, connName);
}
for (Iterator<Video> it = ConnectionsPanel.videosToSend.iterator(); it.hasNext();) {
MassiveDesktopClient.sendFile(it.next().getAttribute("name"), connName);
}
}
}

Categories