Java ScheduledExecutorService wait until a resource is available - java

I have a problem with my java application. On the startup of the application the application needs a connection to another application. My idea was to check on startup of my application to check every second if the other application is available (no condition like wait 5 Minutes, just wait infinitly until available).
I tryed this in the abstract example shown below. In the excample my application will get the other application after 3 trys ...
package main;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger logger = LogManager.getLogger(Main.class);
public static void main(String[] args) {
final Callable<String> sleeper = new Callable<String>() {
// local timer for resource getter
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> timer;
String returnValue;
#Override
public String call() throws Exception {
// start on first call
if (null == timer) {
logger.info("sleeper - starting getter ...");
timer = executor.scheduleAtFixedRate(new getter(3), 0, 1, TimeUnit.SECONDS);
}
// the right way - this seems to be ugly!
try {
timer.get();
} catch (CancellationException | ExecutionException | InterruptedException e) {
logger.error("sleeper - got an exception ... but nothing bad?!");
}
logger.info("sleeper - returning="+returnValue);
return returnValue;
}
class getter implements Runnable {
int _trys;
int _maxTrys;
String _res = null;
getter(int maxTrys) {
logger.info("getter - init, maxTrys=" + maxTrys);
_maxTrys=maxTrys;
}
#Override
public void run() {
if (null == _res) {
if (_trys<_maxTrys) {
++_trys;
logger.info("getter - sleeping trys="+_trys + "/" + _maxTrys);
} else {
_res = "*MIGHTY RESOURCE*";
logger.info("getter - found resource after "+_trys+" trys!");
}
} else {
logger.info("getter - returning resource to parent");
returnValue = _res; // hand over
this.notify(); // exit?
}
}
}
};
logger.info("Main - starting sleeper");
ScheduledExecutorService sleeperExecutor = Executors.newScheduledThreadPool(1);
Future<String> resource = sleeperExecutor.submit(sleeper);
try {
logger.info("Main - got="+resource.get());
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
}
This seems to be a bad solution for me because I can only exit with an exception (see timer.get()). And it seems to be very mich code for such a simple problem.
I imagine something like this (pseudo code):
Application {
start() {
while (!otherAppl.isAvailable) {
// wait until other appl is available
}
// other application is available ... go on with startup
}
}
Regards
S.

Related

Task succeeds but the service onSucceed method is not triggered

When the Task includes 2 lines opening a stream and closing it, the Task returns correctly. Its succeed method runs. But the Service' setOnSucceeded method does not run. Why?
When the 2 lines about the streaming opening and closing are commented out in the Task, we do get the expected behavior: System.out.println("in the succeed method of the Service") does print.
The Main method:
package Test;
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
MyService pluginUpdateService = new MyService();
pluginUpdateService.setOnFailed(e -> {
System.out.println("task failed");
});
pluginUpdateService.setOnSucceeded(e -> {
System.out.println("in the succeed method of the Service"); // this does not print, when MyTask opens the stream (see code of MyTask)
});
// launching the service
if (pluginUpdateService.getState() == Worker.State.READY) {
pluginUpdateService.start();
}
}
}
The service MyService
package Test;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class MyService extends Service {
public MyService() {
}
#Override
protected Task createTask() {
Task updater = new MyTask();
return updater;
}
}
The task MyTask:
package Test;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import javafx.concurrent.Task;
public class MyTask extends Task {
public MyTask() {
}
#Override
protected Void call() throws MalformedURLException, IOException {
InputStream in;
URL url = new URL("https://clementlevallois.net");
in = url.openStream(); // when this line is commented out, the Service does trigger its setOnSucceeded method as expected
in.close(); // when this line is commented out, the Service does trigger its setOnSucceeded method as expected
System.out.println("about to return from the call method of the Task");
return null;
}
#Override
protected void succeeded() {
super.succeeded();
System.out.println("succeeded - sent from the succeeded method of the Task");
}
#Override
protected void cancelled() {
super.cancelled();
System.out.println("cancelled");
updateMessage("Cancelled!");
}
#Override
protected void failed() {
super.failed();
System.out.println("failed");
updateMessage("Failed!");
}
}

Why does Amazon SWF Workflow not cancel immediately after calling TryCatch.cancel()?

I am using the below code sample where I am calling the cancelWF method to cancel the execution of workflow. The onCatch method is successfully invoked with the RuntimeException("Simply cancel"), but on the Amazon SWF console the WF does not end immediately, it waits will timeout and ends with a WorkflowExecutionTerminated event.
The whole project is available here if you want more info.
package aws.swf;
import aws.swf.common.Constants;
import aws.swf.common.DelayRequest;
import aws.swf.common.MyActivityClient;
import aws.swf.common.MyActivityClientImpl;
import aws.swf.common.MyWorkflow;
import aws.swf.common.SWFClient;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.TryCatch;
import java.util.concurrent.CancellationException;
public class D_CancelWorkflow implements MyWorkflow {
private TryCatch tryCatch;
private final MyActivityClient activityClient = new MyActivityClientImpl();
#Override
public void sum() {
tryCatch = new TryCatch() {
#Override
protected void doTry() throws Throwable {
System.out.printf("[WF %s] Started exec\n", D_CancelWorkflow.this);
Promise<Integer> result = activityClient.getNumWithDelay(new DelayRequest("req1", 1));
cancelWF(result);
newDelayRequest(result);
}
#Override
protected void doCatch(Throwable e) throws Throwable {
if (e instanceof CancellationException) {
System.out.printf("[WF %s] Cancelled With message [%s]\n",
D_CancelWorkflow.this, e.getCause().getMessage());
} else {
e.printStackTrace();
}
rethrow(e);
}
};
}
#Asynchronous
private void newDelayRequest(Promise<Integer> num) {
activityClient.getNumWithDelay(new DelayRequest("req2", 1));
}
#Asynchronous
private void cancelWF(Promise<Integer> ignore) {
System.out.printf("[WF %s] Cancelling WF\n", D_CancelWorkflow.this);
this.tryCatch.cancel(new RuntimeException("Simply cancel"));
}
public static void main(String[] args) throws Exception {
AmazonSimpleWorkflow awsSwfClient = new SWFClient().getClient();
WorkflowWorker workflowWorker =
new WorkflowWorker(awsSwfClient, Constants.DOMAIN, Constants.TASK_LIST);
workflowWorker.addWorkflowImplementationType(D_CancelWorkflow.class);
workflowWorker.start();
}
}
This is the event history for one of my execution,

Android Handler is null during testing with junit

I'm trying to test my network module. When I run this on simulator or device, handler is ok, but when I'm trying to do it from tests, handler = null and callback doesn't get called. How can I solve this problem?
public void performCall(Call callToPerform){
callToPerform.call.enqueue(new okhttp3.Callback() {
Handler handler = new Handler();
#Override
public void onFailure(okhttp3.Call call, IOException e) {
handler.post(() -> {
for (Callback callback : callToPerform.callbacks) {
callback.onFailure(callToPerform, e);
}
});
}
#Override
public void onResponse(okhttp3.Call call, final okhttp3.Response response){
handler.post(() -> {
for (Callback callback : callToPerform.callbacks) {
try {
callback.onResponse(callToPerform, new Response(response.body().bytes(), response.headers().toMultimap()));
} catch (IOException e) {
callback.onFailure(call, e);
}
}
});
}
});
}
My graddle app file contains this params.
testOptions {
unitTests.returnDefaultValues = true
}
Ok, after a few hours of research I've found solution and it's similar to this:
package com.dpmedeiros.androidtestsupportlibrary;
import android.os.Handler;
import android.os.Looper;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.*;
/**
* Utility methods that unit tests can use to do common android library mocking that might be needed.
*/
public class AndroidMockUtil {
private AndroidMockUtil() {}
/**
* Mocks main thread handler post() and postDelayed() for use in Android unit tests
*
* To use this:
* <ol>
* <li>Call this method in an {#literal #}Before method of your test.</li>
* <li>Place Looper.class in the {#literal #}PrepareForTest annotation before your test class.</li>
* <li>any class under test that needs to call {#code new Handler(Looper.getMainLooper())} should be placed
* in the {#literal #}PrepareForTest annotation as well.</li>
* </ol>
*
* #throws Exception
*/
public static void mockMainThreadHandler() throws Exception {
PowerMockito.mockStatic(Looper.class);
Looper mockMainThreadLooper = mock(Looper.class);
when(Looper.getMainLooper()).thenReturn(mockMainThreadLooper);
Handler mockMainThreadHandler = mock(Handler.class);
Answer<Boolean> handlerPostAnswer = new Answer<Boolean>() {
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
Runnable runnable = invocation.getArgumentAt(0, Runnable.class);
Long delay = 0L;
if (invocation.getArguments().length > 1) {
delay = invocation.getArgumentAt(1, Long.class);
}
if (runnable != null) {
mainThread.schedule(runnable, delay, TimeUnit.MILLISECONDS);
}
return true;
}
};
doAnswer(handlerPostAnswer).when(mockMainThreadHandler).post(any(Runnable.class));
doAnswer(handlerPostAnswer).when(mockMainThreadHandler).postDelayed(any(Runnable.class), anyLong());
PowerMockito.whenNew(Handler.class).withArguments(mockMainThreadLooper).thenReturn(mockMainThreadHandler);
}
private final static ScheduledExecutorService mainThread = Executors.newSingleThreadScheduledExecutor();
}
If you run this sample code on JUnit, this will not work because JUnit tests are running on a JVM, and Instrumented tests are running on a Simulator or Real Device
You can take a look at this link, it explains why :
Instrumented tests or Local tests

No stack trace is printed when ScheduledExecutorService's task throws an exception

I am creating a ScheduledExecutorService through Dropwizard's LifecycleEnvironment.scheduledExecutorService(). I schedule four tasks on it, which throw an exception after 3 seconds. The problem is that no stack trace is printed for exceptions and hence I cannot trace why it happened. The task which throws exception one is never restarted.
I tried setting a default uncaught exception handler but it didn't help either:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
System.err.println("An exception occurred as below:");
throwable.printStackTrace(System.err);
}
});
Following is the complete code:
This is the main driving class which extends Application:
App.java
import io.dropwizard.Application;
import io.dropwizard.setup.Environment;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class App extends Application<AppConfiguration> {
public void run(AppConfiguration appConfiguration, Environment environment) throws Exception {
final ScheduledExecutorService scheduledExecutorService = environment.lifecycle()
.scheduledExecutorService("throwing-exception-threads").threads(4)
.build();
scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
final HelloWorldResource resource = new HelloWorldResource();
environment.jersey().register(resource);
}
public static void main(String[] args) throws Exception {
new App().run(args);
}
}
Code for task being scheduled at fixed interval is below. It prints counter value which is incremented at each second. When the counter is 3 it throws a NullPointerException.
ThreadToDie.java
public class ThreadToDie implements Runnable {
int i = 0;
#Override
public void run() {
i++;
System.out.printf("Value of i: %d\n", i);
if (i % 3 == 0) {
System.out.printf("Throwing NullPointerException\n");
throw new NullPointerException("This should be printed.");
}
}
}
For the sake of completeness following are the Configuration class and A HelloWorld API class. Though in the question asked what they contain is not relevant.
AppConfiguration.java
import io.dropwizard.Configuration;
public class AppConfiguration extends Configuration {
}
HelloWorldResource.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Optional;
#Path("/hello")
#Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
#GET
public String hello(#QueryParam("name") Optional<String> name) {
final String retVal = String.format("Hello %s!", name.orElse("World"));
return retVal;
}
}
See Why is UncaughtExceptionHandler not called by ExecutorService? for an explanation on why the UncaughtExceptionHandler is never triggered - each task you supply is handled by a worker that catches all exceptions.
When you submit a task to an executor you receive back a Future and can access the exception in that way:
ScheduledFuture<?> future = scheduledExecutorService.scheduleAtFixedRate(new ThreadToDie(), 0,5, TimeUnit.SECONDS);
try {
future.get();
} catch (ExecutionException ex) {
ex.getCause().printStackTrace();
}
Future.get will wait until the task has completed or errored.

Timestamp, timers, time question

I've been Googling Java timestamps, timers, and anything to do with time and Java.
I just can't seem to get anything to work for me.
I need a timestamp to control a while loop like the pseudo-code below
while(true)
{
while(mytimer.millsecounds < amountOftimeIwantLoopToRunFor)
{
dostuff();
}
mytimer.rest();
}
Any ideas what data type I could use; I have tried Timestamp, but didn't seem to work.
Thanks
CiarĂ¡n
Do something like:
long maxduration = 10000; // 10 seconds.
long endtime = System.currentTimeMillis() + maxduration;
while (System.currentTimeMillis() < endtime) {
// ...
}
An (more advanced) alternative is using java.util.concurrent.ExecutorService. Here's an SSCCE:
package com.stackoverflow.q2303206;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String... args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 10, TimeUnit.SECONDS); // Get 10 seconds time.
executor.shutdown();
}
}
class Task implements Callable<String> {
public String call() throws Exception {
while (true) {
// ...
}
return null;
}
}

Categories

Resources