Here inside the for loop I'm trying to get the value from stringCompletableFutureEntry which throws the InterruptedException and with sonar enabled on this, I am supposed to interrupt the thread when an exception occurs but according to my expectation I should get data for all futures if it's not there than I can use Optional.empty() or skip this iteration and move further. How should I get rid of this sonar issue?
private void mapFutures(
Map<Obj1, CompletableFuture<DummyContainer>> futures, List<DummyStatus> dummyStatusList) {
for (Map.Entry<Obj1, CompletableFuture<DummyContainer>> stringCompletableFutureEntry :
futures.entrySet()) {
try {
Optional<DummyContainer> dummyContainer =
Optional.ofNullable(**stringCompletableFutureEntry.getValue().get()**);
List<Dummy> dummy = null;
dummy = dummyContainer.map(DummyContainer::getDummyData).orElseGet(() -> null);
if (!CollectionUtils.isEmpty(dummy)) {
dummyStatusList.add(new DummyStatus(stringCompletableFutureEntry.getKey(), dummy.get(0)));
} else {
dummyStatusList.add(new DummyStatus(stringCompletableFutureEntry.getKey()));
}
} catch (InterruptedException | ExecutionException e) {
Thread.currentThread().interrupt(); // sonar expectation
}
}
}
I tried using timeout while getting data e.g.
stringCompletableFutureEntry.getValue().get(Long.parseLong("3000"), TimeUnit.MILLISECONDS))
It'll throw a TimeoutException once the time threshold is reached.
I'm looking for other Solutions to get rid of InterruptedException inside the loop.
Related
I have to write tests for a website that sometimes hangs indefinitely while loading a page. I'd like to write a method that times out 20 minutes after it starts running.
But when I try to write code like this -
#Test(timeOut=4000)
public void test() {
try { Thread.sleep(5000); } catch (InterruptedException e) {}
System.out.println("I don't want this to print.");
}
The test prints "I don't want this to print." and THEN fails with the intended exception - org.testng.internal.thread.ThreadTimeoutException: Method didn't finish within the time-out 4000
How can I get the test to fail as soon as the time limit is reached?
TLDR;
Do not catch InterruptedException just put in throws clause.
As TestNG works (in this case) the framework will create a new single-threaded executorService, submit a worker which will be waiting for termination. If the test running was not finished the worker will throw org.testng.internal.thread.ThreadTimeoutException.
Related source code is:
org.testng.internal.MethodInvocationHelper
private static void invokeWithTimeoutWithNewExecutor(
ITestNGMethod tm,
Object instance,
Object[] parameterValues,
ITestResult testResult,
IHookable hookable)
throws InterruptedException, ThreadExecutionException {
ExecutorService exec = ThreadUtil.createExecutor(1, tm.getMethodName());
InvokeMethodRunnable imr =
new InvokeMethodRunnable(tm, instance, parameterValues, hookable, testResult);
Future<Void> future = exec.submit(imr);
exec.shutdown();
long realTimeOut = MethodHelper.calculateTimeOut(tm);
boolean finished = exec.awaitTermination(realTimeOut, TimeUnit.MILLISECONDS);
if (!finished) {
exec.shutdownNow();
ThreadTimeoutException exception =
new ThreadTimeoutException(
"Method "
+ tm.getQualifiedName()
+ "() didn't finish within the time-out "
+ realTimeOut);
testResult.setThrowable(exception);
testResult.setStatus(ITestResult.FAILURE);
} else {
Utils.log(
"Invoker " + Thread.currentThread().hashCode(),
3,
"Method " + tm.getMethodName() + " completed within the time-out " + tm.getTimeOut());
// We don't need the result from the future but invoking get() on it
// will trigger the exception that was thrown, if any
try {
future.get();
} catch (ExecutionException e) {
throw new ThreadExecutionException(e.getCause());
}
testResult.setStatus(ITestResult.SUCCESS); // if no exception till here then SUCCESS.
}
}
The point is:
ExecutorService exec = ThreadUtil.createExecutor(1, tm.getMethodName());
// ... and
boolean finished = exec.awaitTermination(realTimeOut, TimeUnit.MILLISECONDS);
The java.util.concurrent.ExecutorService.awaitTermination(...) method throws InterruptedException which was handled in the test method. Because of this the test method won't be terminated but the finished flag will be false.
So it will help:
#Test(timeOut = 4000)
public void test() throws InterruptedException {
Thread.sleep(5000);
System.out.println("I don't want this to print");
}
I use a Timer.schedule() to periodically call the run() method of the TimerTask class to poll devices. Sometimes a MalformedJsonException or a IllegalStateException are thrown, which is processed in the catch block. The thread should continue to poll devices after handling the exception, but it stops.
When there are no errors, the run method is periodically called as expected.
I also tried calling the runModulesPoll() method from the catch block, but that didn't help.
private static void runModulesPoll(Boiler boiler) {
new Timer("Modules Poll Flow").schedule(new TimerTask() {
#Override
public void run() {
try {
Module[] modules = boiler.getCore().getModules();
for (Module module : modules) {
String response = ControllersService.sendMessage(MessageBuilder.buildDataRequest(module.getAlias(), boiler.getBoilerMode()));
if (AppUtils.isStringInvalid(response)) {
module.setOnline(false);
ModulesResetService.reset();
continue;
}
module.setOnline(true);
module.fromShortJson(response);
}
MqttService.publishMessage(MqttMessageFactory.createDataMessage(boiler.getCore().getModulesDataAsJson()));
} catch (Throwable e) {
LoggerLocal.error("Exception in Modules Poll Flow: " + e.getLocalizedMessage());
e.printStackTrace();
}
}
}, 0, 1);
}
According to the logs, the exception is handled as expected, but the thread does not continue polling.
14-11-2019 18:10:47 -- Exception in Modules Poll Flow: Not a JSON Object: "hgjhgjhg"
java.lang.IllegalStateException: Not a JSON Object: "hgjhgjhg"
at com.google.gson.JsonElement.getAsJsonObject(JsonElement.java:90)
at eezo.AppUtils.getJsonObjectFromString(AppUtils.java:101)
at eezo.services.ControllersService.handleIfErrorMessage(ControllersService.java:148)
at eezo.services.ControllersService.sendMessage(ControllersService.java:53)
at eezo.ApplicationRunner$1.run(ApplicationRunner.java:107)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
UPDATE:
Exception throws inside try block and handles in catch but thread stops without any other exceptions.
LoggerLocal doesn't produce exceptions at all.
I simulated the situation with a simpler example and everything works as expected, the thread does not fall and handles exceptions constantly.
private static void run(String[] args) {
final int[] i = {0};
new Timer("Modules Poll Flow").schedule(new TimerTask() {
#Override
public void run() {
try {
System.out.println("run() " + args);
if (i[0] == 5) throw new IllegalStateException("ssss");
i[0]++;
} catch (Exception e) {
System.out.println("Exception in Modules Poll Flow: " + e.getLocalizedMessage());
e.printStackTrace();
}
}
}, 0, 1);
}
How can I make my Java run again from the start (main) when it encounters an exception without closing and running it again manually?
My program basically writes on a file. When it cannot find the file I will throw the FileNotFoundException then write the file (say for example hello.txt). After it writes, the program closes (in NetBeans cause I am still developing it) and start showing this at the buttom:
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.parseInt(Integer.java:615)
at app4pics1word.App4pics1word.cache(App4pics1word.java:127)
at app4pics1word.App4pics1word.<init>(App4pics1word.java:18)
at app4pics1word.App4pics1word.main(App4pics1word.java:146)
Java Result: 1
you can try this
public static void main(String[] args) {
try {
//something wrong happens here
}catch(Throwable e) {
e.printStackTrace();
main(args);
}
}
You should use exception handling instead of restarting the program. If you restart the program, the error will still be there and thus your program will keep on trying to run for eternity, always failing with the same exception.
You would like to catch your exception and make sure that the input is valid:
boolean okInput = false;
int x = -1;
String someData = "rr";
do {
try {
x = Integer.parseInt(someData); // try to parse
okInput = true;
} catch(NumberFormatException n) {
// Error, try again
okInput = false
someData = "2";
}
} while(!okInput); // Keep trying while input is not valid
// Here x is a valid number
This tutorial provides you good code in general of how exceptions work.
is this what you are looking for ?
public static void main(String [] args) {
boolean done = false;
do {
try {
writeSomeFile();
done = true;
}
catch (Exception ex)
{
System.out.println("Exception trapped "+ex)
}
} while (!done);
}
You can make it a loop that is broken only when the try block succeeds without an Exception:
public static void main(String[] args) {
while(true) {
try {
...
break; //at the end of try block
}
catch (SomeException e) {
//print error message here, or do whatever
}
}
//program continues here once try block gets through w/o exceptions
...
}
However, instead of having this in your main I recommend hiding this rather ugly structure inside a method.
I hava a test, with:
#test(timeout = 50000)
I want to do some operations if the test fails because the timeout, and only then.
I try the next:
#Test(timeout=60000)
public void test1() {
try{
// code
}
catch(Exception e){
//operations after time out
}
}
But it doesn't work. Any help?
It's not possible to do what you described here with JUnit's timeout parameter because it doesn't provide a callback to handle the operations after it has timed out.
But, you can certainly write your own test harness to do just that. In the below example, I want the code to execute within one second but my actual code execution takes 2 seconds. In this case, we catch the TimeoutException and you can perform your additional operation within that catch block.
#Test
public void testMe() {
// test must finish within one second
int expectedExecutionInSeconds = 1;
RunnableFuture<String> runnableFuture = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
// your actual code goes in here
Thread.sleep(2000);
return "ok";
}
});
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(runnableFuture);
try {
String result = runnableFuture.get(expectedExecutionInSeconds, TimeUnit.SECONDS);
assertEquals("ok", result);
}
catch (TimeoutException ex) {
// stop code
runnableFuture.cancel(true);
System.out.println("do other stuff");
}
catch (Exception e) {
fail("other stuff is failing");
}
executorService.shutdown();
}
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);
}
}
}