How to handle different exceptions in Task? - javafx

I'm kinda new in JavaFX, and I didn't find any answer to this.
I'm trying to use Task to do some background calculation in a database. The problem is the following : How can I handle exceptions (SQLException, IOException etc ...) in my task.SetOnFailed(e -> ....) function ?
I tried this : e.getSource().getException().getMessage() but I don't think it is the right way to do this.

You can just check the type of the exception:
Task<Something> myTask = new Task<Something>() {
#Override
public Something call() throws Exception {
// code...
return something ;
}
};
myTask.setOnFailed(e -> {
Throwable exc = myTask.getException();
if (exc instanceof SQLException) {
// ...
} else if (exc instanceof IOException) {
// ...
} else {
// ...
}
});

Related

How to print subcommand result automatically?

I have Java CLI application based on cliche library and I want to migrate it to picocli.
My application was based on cliche so I have a lot of methods with asg.cliche.Command annotation which return some result. cliche prints command methods's result automatically so result was printed in command line. I replaced asg.cliche.Command annotations by picocli.CommandLine.Command and I see that picocli does not print command methods's results.
I have following class:
import picocli.CommandLine;
#CommandLine.Command(subcommandsRepeatable = true)
public class Foo
{
public static void main( String[] args )
{
new CommandLine( new Foo() ).execute( args );
}
#CommandLine.Command
public String sayHello()
{
return "Hello";
}
#CommandLine.Command
public String sayGoodbye()
{
return "GoodBye";
}
}
when I call java -cp myJar.jar Foo sayHello sayGoodbye I do not see any output.
I see three solutions:
1. Modify each methods to print result instead of return it.
import picocli.CommandLine;
#CommandLine.Command( subcommandsRepeatable = true )
public class Foo2
{
public static void main( String[] args )
{
new CommandLine( new Foo2() ).execute( args );
}
#CommandLine.Command
public void sayHello()
{
System.out.println( "Hello" );
}
#CommandLine.Command
public void sayGoodbye()
{
System.out.println( "GoodBye" );
}
}
I am not happy with this solution. I prefer not modify my methods.
Retrieve results after execution.
public static void main( String[] args )
{
final CommandLine commandLine = new CommandLine( new Foo() );
commandLine.execute( args );
CommandLine.ParseResult parseResult = commandLine.getParseResult();
for( CommandLine.ParseResult pr : parseResult.subcommands() )
{
System.out.println( pr.commandSpec().commandLine()
.getExecutionResult()
.toString() );
}
}
I see a few problems with this solution. The main problem is formatting. Execution result can be null, array, collection. The second problem is that results are printed after execution of all subcommands. If second subcommand throws exception then I firstly see exception stack trace and after that I see result of first subcommand.
Ask on stackoverflow if there is some better solution. I do not believe that there is no any configuration option in picocli which enable results printing.
Personally, I like your first solution best, it is simple and easy to maintain. Maybe introduce a helper method for the printing and formatting so the command methods can look like this:
#CommandLine.Command
public String sayGoodbye()
{
return printValue("GoodBye");
}
You already found the CommandLine.getParseResult method; perhaps a helper method could assist with the formatting there as well.
There is a third option, but it is unfortunately quite a bit more complex: you can create a custom IExecutionStrategy that prints the result of each command after executing it. It involves copying a lot of code from the picocli internals and it’s not really a realistic solution; I just mention it for completeness.
// extend RunLast to handle requests for help/version and exit code stuff
class PrintingExecutionStrategy extends CommandLine.RunLast {
#Override
protected List<Object> handle(ParseResult parseResult) throws ExecutionException {
// Simplified: executes only the last subcommand (so no repeating subcommands).
// Look at RunLast.executeUserObjectOfLastSubcommandWithSameParent if you need repeating subcommands.
List<CommandLine> parsedCommands = parseResult.asCommandLineList();
CommandLine last = parsedCommands.get(parsedCommands.size() - 1);
return execute(last, new ArrayList<Object>());
}
// copied from CommandLine.executeUserObject,
// modified to print the execution result
private List<Object> execute(CommandLine cmd, List<Object> executionResultList) throws Exception {
Object command = parsed.getCommand();
if (command instanceof Runnable) {
try {
((Runnable) command).run();
parsed.setExecutionResult(null); // 4.0
executionResultList.add(null); // for compatibility with picocli 2.x
return executionResultList;
} catch (ParameterException ex) {
throw ex;
} catch (ExecutionException ex) {
throw ex;
} catch (Exception ex) {
throw new ExecutionException(parsed, "Error while running command (" + command + "): " + ex, ex);
}
} else if (command instanceof Callable) {
try {
#SuppressWarnings("unchecked") Callable<Object> callable = (Callable<Object>) command;
Object executionResult = callable.call();
System.out.println(executionResult); <-------- print result
parsed.setExecutionResult(executionResult);
executionResultList.add(executionResult);
return executionResultList;
} catch (ParameterException ex) {
throw ex;
} catch (ExecutionException ex) {
throw ex;
} catch (Exception ex) {
throw new ExecutionException(parsed, "Error while calling command (" + command + "): " + ex, ex);
}
} else if (command instanceof Method) {
try {
Method method = (Method) command;
Object[] parsedArgs = parsed.getCommandSpec().argValues();
Object executionResult;
if (Modifier.isStatic(method.getModifiers())) {
executionResult = method.invoke(null, parsedArgs); // invoke static method
} else if (parsed.getCommandSpec().parent() != null) {
executionResult = method.invoke(parsed.getCommandSpec().parent().userObject(), parsedArgs);
} else {
executionResult = method.invoke(parsed.factory.create(method.getDeclaringClass()), parsedArgs);
}
System.out.println(executionResult); <-------- print result
parsed.setExecutionResult(executionResult);
executionResultList.add(executionResult);
return executionResultList;
} catch (InvocationTargetException ex) {
Throwable t = ex.getTargetException();
if (t instanceof ParameterException) {
throw (ParameterException) t;
} else if (t instanceof ExecutionException) {
throw (ExecutionException) t;
} else {
throw new ExecutionException(parsed, "Error while calling command (" + command + "): " + t, t);
}
} catch (Exception ex) {
throw new ExecutionException(parsed, "Unhandled error while calling command (" + command + "): " + ex, ex);
}
}
throw new ExecutionException(parsed, "Parsed command (" + command + ") is not a Method, Runnable or Callable");
}
}
Use it like this:
public static void main(String... args) {
new CommandLine(new Foo())
.setExecutionStrategy(new PrintingExecutionStrategy())
.execute(args);
}
I wouldn’t recommend the above.
Update: I thought of another, fourth, option (actually a variation of your 2nd solution). You can specify a custom IExecutionExceptionHandler that doesn’t print the stacktrace, but instead stores the exception so you can print the stacktrace after printing the command results. Something like this:
class MyHandler extends IExecutionExceptionHandler() {
Exception exception;
public int handleExecutionException(Exception ex,
CommandLine commandLine,
ParseResult parseResult) {
//ex.printStackTrace(); // no stack trace
exception = ex;
}
}
Use it like this:
public static void main(String... args) {
MyHandler handler = new MyHandler();
CommandLine cmd = new CommandLine(new Foo())
.setExecutionExceptionHandler(handler);
cmd.execute(args);
ParseResult parseResult = cmd.getParseResult();
for( ParseResult pr : parseResult.subcommands() )
{
System.out.println( pr.commandSpec().commandLine()
.getExecutionResult()
.toString() );
}
if (handler.exception != null) {
handler.exception.printStackTrace();
}
}

Async Co-Routine in Kotlin

I never use async in Kotlin. I'm not sure whether I understand is correctly.
I need that the method buttonChange(result) wait the thread is finish, to obtain the result.
fun sendConnection(view: View) {
var result = ""
if (!connected) {
async {
val runnable = Runnable()
{
result = me.connect("connection")
}
val threadSend = Thread(runnable)
threadSend.start()
}
buttonChange(result)
}
catch (e: Exception) {}
} else {
try {
async {
val runnable = Runnable()
{
result = me.connect("disconnection")
}
val threadSend = Thread(runnable)
threadSend.start()
}
buttonChange(result)
} catch (e: Exception) {
}
}
The pattern you should use is async/await.
It'll return a Deferred from async { } which you can use to call await() on. Since buttonChange seems to need the UI context, you might need to launch the coroutines as well.
launch(UI) {
try {
val result = async { me.connect("disconnection") }
buttonChange(result.await())
} catch (_: Exception) { }
}
You should not create a thread manually.

Issues appending text to a TextArea (JavaFX 8)

I am receiving strings from my server that I want to append into a Textarea on the client side (Think chat window). Problem is, when I receive the string, the client freezes.
insertUserNameButton.setOnAction((event) -> {
userName=userNameField.getText();
try {
connect();
} catch (IOException e) {
e.printStackTrace();
}
});
public Client() {
userInput.setOnAction((event) -> {
out.println(userInput.getText());
userInput.setText("");
});
}
private void connect() throws IOException {
String serverAddress = hostName;
Socket socket = new Socket(serverAddress, portNumber);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(userName);
} else if (line.startsWith("MESSAGE")) {
Platform.runLater(()->serverOutput.appendText(line.substring(8) + "\n"));
} else if (line.startsWith("QUESTION")) {
Platform.runLater(()->serverOutput.appendText(line.substring(8) + "\n"));
} else if (line.startsWith("CORRECTANSWER")) {
Platform.runLater(()->serverOutput.appendText(line.substring(14) + "\n"));
}
}
}
public static void main(String[] args) {
launch(args);
}
I have done some research and it seems that using Platform.runLater on each append should fix the problem. It doesn't for me.
Anyone has an idea of what it can be caused by? Thank you!
You are calling connect() on the FX Application Thread. Since it blocks indefinitely via the
while(true) {
String line = in.readLine();
// ...
}
construct, you block the FX Application Thread and prevent it from doing any of its usual work (rendering the UI, responding to user events, etc).
You need to run this on a background thread. It's best to use a Executor to manage the threads:
private final Executor exec = Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
and then do
insertUserNameButton.setOnAction((event) -> {
userName=userNameField.getText();
exec.execute(() -> {
try {
connect();
} catch (IOException e) {
e.printStackTrace();
}
});
});

Error while calling external AsyncTask from fragment

Can some one please help me with this issue .
I am calling an AsyncTask when ever there is SharedPreference change in fragment.
public class UbiSavePreferenceTask extends AsyncTask {
public final AsyncTask<JSONObject, Integer, Boolean> parallelExecute(JSONObject pref) {
return parallelExecute(pref);
}
In My fragment
emailNotificationPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference,Object newValue) {
JSONObject json = new JSONObject();
try {
json.put("Email", newValue);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
UbiSavePreferenceTask savePref = new UbiSavePreferenceTask(mContext);
savePref.parallelExecute(json);
return true;
}
});
but parallelExecute method in Async task in going to an infinite loop so i am getting stackOverflowError.
Is there any way i can come out of this error .
Please let me know.
The method parallelExecute calls itself, so it is normal that it goes in an infinite loop!
public final AsyncTask<JSONObject, Integer, Boolean> parallelExecute(JSONObject pref) {
return parallelExecute(pref); // <--- here the method calls itself!
}
I hope this helps!

Make multiple asynchronous calls and do something when they are completed

I have run into this problem across multiple programming languages and I was just wondering what the best way to handle it is.
I have three method calls that fire off asynchronously. Each one has a callback. I want to do something only when all three callbacks have completed.
What is the best way to code this? I usually end up with all these public bool flags and as you add more calls the code gets more convoluted.
Coming from C#, I would probably use WaitHandle.WaitAll. You can create an array of ManualResetEvent objects (one for each task to be completed), and pass that array to WaitAll. The threaded tasks will get one ManualResetEvent object each, and call the Set method when they are ready. WaitAll will block the calling thread until all tasks are done. I'll give a C# code example:
private void SpawnWorkers()
{
ManualResetEvent[] resetEvents = new[] {
new ManualResetEvent(false),
new ManualResetEvent(false)
};
// spawn the workers from a separate thread, so that
// the WaitAll call does not block the main thread
ThreadPool.QueueUserWorkItem((state) =>
{
ThreadPool.QueueUserWorkItem(Worker1, resetEvents[0]);
ThreadPool.QueueUserWorkItem(Worker2, resetEvents[1]);
WaitHandle.WaitAll(resetEvents);
this.BeginInvoke(new Action(AllTasksAreDone));
});
}
private void AllTasksAreDone()
{
// OK, all are done, act accordingly
}
private void Worker1(object state)
{
// do work, and then signal the waiting thread
((ManualResetEvent) state).Set();
}
private void Worker2(object state)
{
// do work, and then signal the waiting thread
((ManualResetEvent)state).Set();
}
Note that the AllTasksAreDone method will execute on the thread pool thread that was used to spawn the workers, and not on the main thread... I assume that many other languages have similar constructs.
If you really only want to wait for all to finish:
Create volatile counter
Synchronize access to counter
Increase counter on start
Decrease on callback fired
Wait for counter to reach 0
Use a semaphore.
Futures are very easy to use. Futures look like normal functions, except that they execute asynch.
The classes:
public struct FutureResult<T>
{
public T Value;
public Exception Error;
}
public class Future<T>
{
public delegate R FutureDelegate<R>();
public Future(FutureDelegate<T> del)
{
_del = del;
_result = del.BeginInvoke(null, null);
}
private FutureDelegate<T> _del;
private IAsyncResult _result;
private T _persistedValue;
private bool _hasValue = false;
private T Value
{
get
{
if (!_hasValue)
{
if (!_result.IsCompleted)
_result.AsyncWaitHandle.WaitOne();
_persistedValue = _del.EndInvoke(_result);
_hasValue = true;
}
return _persistedValue;
}
}
public static implicit operator T(Future<T> f)
{
return f.Value;
}
}
Here I use futures to simulate a deadlock:
void SimulateDeadlock()
{
Future> deadlockFuture1 = new Future>(() =>
{
try
{
new SystemData(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)
.SimulateDeadlock1(new DateTime(2000, 1, 1, 0, 0, 2));
return new FutureResult { Value = true };
}
catch (Exception ex)
{
return new FutureResult { Value = false, Error = ex };
}
});
Future> deadlockFuture2 = new Future>(() =>
{
try
{
new SystemData(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)
.SimulateDeadlock2(new DateTime(2000, 1, 1, 0, 0, 2));
return new FutureResult { Value = true };
}
catch (Exception ex)
{
return new FutureResult { Value = false, Error = ex };
}
});
FutureResult result1 = deadlockFuture1;
FutureResult result2 = deadlockFuture2;
if (result1.Error != null)
{
if (result1.Error is SqlException && ((SqlException)result1.Error).Number == 1205)
Console.WriteLine("Deadlock!");
else
Console.WriteLine(result1.Error.ToString());
}
else if (result2.Error != null)
{
if (result2.Error is SqlException && ((SqlException)result2.Error).Number == 1205)
Console.WriteLine("Deadlock!");
else
Console.WriteLine(result2.Error.ToString());
}
}
For those using JavaScript, consider using the pattern discussed at this Stackoverflow question:
javascript: execute a bunch of asynchronous method with one callback

Resources