Java Task Execution and Reflection - java

I am having the code this way..
1) Invoking the updatedb method using reflection...
for (String uniqueSym : activeSymbolsSet) {
futureTaskUtil.submiteTask(new Helper(),
Helper.class.getDeclaredMethod("updateDb",
new Class<?>[] { String.class }), new Object[] { uniqueSym }, 60);
}
- futureTaskUtil:
2) My question is this updatedb is executed as an run time task...
public Object submiteTask(final Object obj, final Method method, final Object[] params, int timeoutSeconds) throws Exception {
if (null != obj && method != null) {
Callable<Object> task = new Callable<Object>() {
public Object call() {
try {
method.setAccessible(true);
Object resultObj = method.invoke(obj, params);
return resultObj;
} catch (Exception e) {
logger.fatal("Exception occured while invoking future task.", e);
}
return null;
}
};
Future<Object> future = executor.submit(task);
try {
Object result = null;
if (timeoutSeconds < 0) {
result = future.get(timoutsec, TimeUnit.SECONDS);
} else {
result = future.get(timeoutSeconds, TimeUnit.SECONDS);
}
logger.info("Result of method execution is :: " + result);
return result;
} catch (TimeoutException e) {
} catch (Exception e) {
logger.fatal("Exception occured while executing future tas : " + obj, e);
} finally {
future.cancel(true); // may or may not desire this
}
}
return null;
}
can some one explain why this is executed as an seperate task and invoking the method?

Future<Object> future = executor.submit(task); This is your culprit You can read about Executer Framework here

What if the method never returns? Then the application would hang at this point.
Using this wrapper, the method will be canceled after 60 seconds.

Related

Resubmit Callable to executorService on exception

My situation
I'm trying to craft a functionality which would execute n (where n >=0) requests to a given endpoint, but I do understand that sometimes that endpoint might not respond due to
500 error or other issue, so I want to repeat my requests to an endpoint (with a
small interval in between [not yet implemented]) till I get a response, or till I get an unknown error which would indicate what I can't repeat, because of other reasons than a crashed server.
So, I've tried to implement this piece of functionality using Executors and concurrency provided by Java 11 and it does not work as I want
I can't resubmit failed tasks till I get all the responses and I don't know why
I have a method
private void DoMyTasks(List<MyRequest> requests) {
final ExecutorService executorService = Executors.newFixedThreadPool(10);
final ExecutorCompletionService<MyReqResDto> completionService =
new ExecutorCompletionService<>(executorService);
for (final MyRequest MyRequest : requests) {
completionService.submit(new MyCallableRequest(webClient, MyRequest));
}
List<MyReqResDto> responses = new ArrayList<>();
for (int i = 0; i < requests.size(); ++i) {
try {
final Future<MyReqResDto> future = completionService.take();
if (future.get().getEx() != null) {
completionService.submit(new MyCallableRequest(webClient, future.get().getMyRequest()));
}
responses.add(future.get());
} catch (ExecutionException | InterruptedException e) {
log.warn("Error"));
} catch (Exception exception) {
log.error("Other error");
} finally {
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.MINUTES)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
}
}
responses.size();
}
I'm trying to repeat failed tasks with
if (future.get().getEx() != null) {
completionService.submit(new MyCallableRequest(webClient, future.get().getMyRequest()));
}
and yet, at the end of execution I don't get all responses for my requests. What I get is at most 3 to 5 responses when I try executing 10 requests. Why? How to fix it?
My callable class is
public class MyCallableRequest implements Callable<MyReqResDto> {
private final WebClient webClient;
private final MyRequest myRequest;
public MyCallableRequest(WebClient webClient, MyRequest myRequest) {
this.webClient = webClient;
this.myRequest = myRequest;
}
#Override
public MyReqResDto call() throws Exception {
try {
if (new Random().nextInt(10) % 2 == 0) {
throw new TestException();
}
if (new Random().nextInt(10) % 7 == 0) {
throw new RuntimeException();
}
WebClient.UriSpec<WebClient.RequestBodySpec> uriSpec = webClient.post();
WebClient.RequestBodySpec bodySpec = uriSpec.uri(
s -> s.path("/myEndpoint").build());
MyRequestDto myMyRequestDto = new MyRequestDto();
WebClient.RequestHeadersSpec<?> headersSpec =
bodySpec.body(Mono.just(myMyRequestDto), MyRequestDto.class);
ResponseDto responseDto = headersSpec.exchangeToMono(s -> {
if (s.statusCode().equals(HttpStatus.OK)) {
return s.bodyToMono(ResponseDto.class);
} else if (s.statusCode().is1xxInformational()) {
return s.createException().flatMap(Mono::error);
} else if (s.statusCode().is3xxRedirection()) {
return s.createException().flatMap(Mono::error);
} else if (s.statusCode().is4xxClientError()) {
return s.createException().flatMap(Mono::error);
} else if (s.statusCode().is5xxServerError()) {
return s.createException().flatMap(Mono::error);
} else {
return s.createException().flatMap(Mono::error);
}
//return null;
}).block();
return new MyReqResDto(myRequest, responseDto, null);
} catch (Exception exception) {
return new MyReqResDto(myRequest, null, exception);
}
}
}
Update NO. 1
I changed a for loop to a while loop according to a comment provided by
Slaw and an answer provided by erickson. And this solutions works, meaning that
it is hammering an endpoint till all responses are received without
any errors. But I'm still not sure it feels that I'm building a sh**
tower with this solution. Is there any thread related issues that I should be aware while using executor like this?
while (true) {
Future < MyReqResDto > future = null;
try {
future = completionService.take();
if (future.get().getEx() != null /*and check exception if possible to handle, if not break from a loop*/) {
completionService.submit(new MyCallableRequest(webClient, future.get().getRequestCT());
} else {
responseDtos.add(future.get());
}
} catch (ExecutionException | InterruptedException e) {
log.warn("Error while downloading", e.getCause());
// test if I can recover from these exceptions if no
break;
}
}
if (responseDtos.size() == requests.size()) {
executorService.shutdown();
try {
if (!executorService.awaitTermination(10, TimeUnit.MINUTES)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
break;
}
You are shutting down the executor as soon as you get one response. Perhaps a few more have completed in this time, but you are not allowing time for any others to complete.
Your logic here is wrong. The executor should only be shut down when you are sure no more tasks will be submitted; at soonest, that is after the loop responsible for re-submitting failures.
Here is a simplified view of your code to highlight the premature shutdown:
for (int i = 0; i < requests.size(); ++i) {
try {
final Future<MyReqResDto> future = completionService.take();
...
responses.add(future.get());
...
} finally {
executorService.shutdown();
}
}

How to call multiple methods asynchrounosly with different implementation

I am trying to call one method 12 times asynchronously. But before the call I am setting something different for each method call. How can I do this in a more elegant way.
I am using spring as well.
I am aware of #async but how can I change the body 12 times ?
Callable<Object> task4 = () -> {
CallContextHolder.setContext(callContext);
try {
Object m = dbQuery(userId);
if (m == null){
throw new RuntimeException();
}
return m;
}
catch (Exception e) {
throw new IllegalStateException("task interrupted", e);
}
};
Callable<Object> task5 = () -> {
CallContextHolder.setContext(callContext); //here is the difference in every task
try {
Object m = dbQuery(userId);
if (m == null){
throw new RuntimeException();
}
return m;
}
catch (Exception e) {
throw new IllegalStateException("task interrupted", e);
}
You can use something like the following method
public Callable<Object> getCallable(CallContext context, String userId) { //replace types fro parameters to appropriate
return () -> {
CallContextHolder.setContext(callContext);
try {
Object m = dbQuery(userId);
if (m == null){
throw new RuntimeException();
}
return m;
}
catch (Exception e) {
throw new IllegalStateException("task interrupted", e);
}
};
}
And use it like this
Callable<Object> call1 = getCallable(callContext, userId);
Callable<Object> call2 = getCallable(callContext, userId);
You can try to use some type of loop to generate those callables and store them in a list.

Java Using CountDownLatch to poll a method until a success response

I am trying to call a method multiple times every 60 seconds until a success response from the method which actually calls a rest end point on a different service. As of now I am using do while loop and using
Thread.sleep(60000);
to make the main thread wait 60 seconds which I feel is not the ideal way due to concurrency issues.
I came across the CountDownLatch method using
CountDownLatch latch = new CountDownLatch(1);
boolean processingCompleteWithin60Second = latch.await(60, TimeUnit.SECONDS);
#Override
public void run(){
String processStat = null;
try {
status = getStat(processStatId);
if("SUCCEEDED".equals(processStat))
{
latch.countDown();
}
} catch (Exception e) {
e.printStackTrace();
}
}
I have the run method in a different class which implements runnable. Not able to get this working. Any idea what is wrong?
You could use a CompletableFuture instead of CountDownLatch to return the result:
CompletableFuture<String> future = new CompletableFuture<>();
invokeYourLogicInAnotherThread(future);
String result = future.get(); // this blocks
And in another thread (possibly in a loop):
#Override
public void run() {
String processStat = null;
try {
status = getStat(processStatId);
if("SUCCEEDED".equals(processStat))
{
future.complete(processStat);
}
} catch (Exception e) {
future.completeExceptionally(e);
}
}
future.get() will block until something is submitted via complete() method and return the submitted value, or it will throw the exception supplied via completeExceptionally() wrapped in an ExecutionException.
There is also get() version with timeout limit:
String result = future.get(60, TimeUnit.SECONDS);
Finally got it to work using Executor Framework.
final int[] value = new int[1];
pollExecutor.scheduleWithFixedDelay(new Runnable() {
Map<String, String> statMap = null;
#Override
public void run() {
try {
statMap = coldService.doPoll(id);
} catch (Exception e) {
}
if (statMap != null) {
for (Map.Entry<String, String> entry : statMap
.entrySet()) {
if ("failed".equals(entry.getValue())) {
value[0] = 2;
pollExecutor.shutdown();
}
}
}
}
}, 0, 5, TimeUnit.MINUTES);
try {
pollExecutor.awaitTermination(40, TimeUnit.MINUTES);
} catch (InterruptedException e) {
}

How to give message when Threadpool Executor is completed?

I am trying to give a pop up alert message when my ThreadpoolExecutor is finished executing. It is searching email addresses from websites, once it is done I want a alert message as "Completed". Here is my Thread :-
public class Constant
{
public static final int NUM_OF_THREAD = 60;
public static final int TIME_OUT = 10000;
}
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool
(Constant.NUM_OF_THREAD);
Here is my Searching Operation class :-
class SearchingOperation implements Runnable {
URL urldata;
int i;
Set<String> emailAddresses;
int level;
SearchingOperation(URL urldata, int i, Set<String> emailAddresses, int level) {
this.urldata = urldata;
this.i = i;
this.emailAddresses = emailAddresses;
this.level = level;
if (level != 1)
model.setValueAt(urldata.getProtocol() + "://" + urldata.getHost() + "/contacts", i, 3);
}
public void run() {
BufferedReader bufferreader1 = null;
InputStreamReader emailReader = null;
System.out.println(this.i + ":" + poolMainExecutor.getActiveCount() + ":" + level + ";" + urldata.toString());
try {
if (level < 1) {
String httpPatternString = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9#:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9#:%_\\+.~#?&//=]*)";
String httpString = "";
BufferedReader bufferreaderHTTP = null;
InputStreamReader httpReader = null;
try {
httpReader = new InputStreamReader(urldata.openStream());
bufferreaderHTTP = new BufferedReader(httpReader
);
StringBuilder rawhttp = new StringBuilder();
while ((httpString = bufferreaderHTTP.readLine()) != null) {
rawhttp.append(httpString);
}
if (rawhttp.toString().isEmpty()) {
return;
}
List<String> urls = getURL(rawhttp.toString());
for (String url : urls) {
String fullUrl = getMatchRegex(url, httpPatternString);
if (fullUrl.isEmpty()) {
if (!url.startsWith("/")) {
url = "/" + url;
}
String address = urldata.getProtocol() + "://" + urldata.getHost() + url;
fullUrl = getMatchRegex(address, httpPatternString);
}
if (!addressWorked.contains(fullUrl) && fullUrl.contains(urldata.getHost())) {
addressWorked.add(fullUrl);
sendToSearch(fullUrl);
}
}
} catch (Exception e) {
//System.out.println("652" + e.getMessage());
//e.printStackTrace();
return;
} finally {
try {
if (httpReader != null)
bufferreaderHTTP.close();
} catch (Exception e) {
// e.printStackTrace();
}
try {
if (httpReader != null)
httpReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
String someString = "";
emailReader = new InputStreamReader(urldata.openStream());
bufferreader1 = new BufferedReader(
emailReader);
StringBuilder emailRaw = new StringBuilder();
while ((someString = bufferreader1.readLine()) != null) {
if (someString.contains("#")) {
emailRaw.append(someString).append(";");
}
}
//Set<String> emailAddresses = new HashSet<String>();
String emailAddress;
//Pattern pattern = Pattern
//.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Pattern
pattern = Pattern
.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Matcher matchs = pattern.matcher(emailRaw);
while (matchs.find()) {
emailAddress = (emailRaw.substring(matchs.start(),
matchs.end()));
// //System.out.println(emailAddress);
if (!emailAddresses.contains(emailAddress)) {
emailAddresses.add(emailAddress);
// //System.out.println(emailAddress);
if (!foundItem.get(i)) {
table.setValueAt("Found", i, 4);
foundItem.set(i, true);
}
String emails = !emailAddresses.isEmpty() ? emailAddresses.toString() : "";
model.setValueAt(emails, i, 2);
model.setValueAt("", i, 3);
}
}
} catch (Exception e) {
//System.out.println("687" + e.getMessage());
} finally {
try {
if (bufferreader1 != null)
bufferreader1.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (emailReader != null)
emailReader.close();
} catch (Exception e) {
e.printStackTrace();
}
Thread.currentThread().interrupt();
return;
}
}
After this the final snippet :-
private void sendToSearch(String address) throws Throwable {
SearchingOperation operation = new SearchingOperation(new URL(address), i,
emailAddresses, level + 1);
//operation.run();
try {
final Future handler = poolMainExecutor.submit(operation);
try {
handler.get(Constant.TIME_OUT, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
handler.cancel(false);
}
} catch (Exception e) {
//System.out.println("Time out for:" + address);
} catch (Error error) {
//System.out.println("Time out for:" + address);
} finally {
}
}
Implement Callable<Void> instead of Runnable and wait for all the task to terminate by calling Future<Void>.get():
class SearchingOperation implements Callable<Void>
{
public Void call() throws Exception
{
//same code as in run()
}
}
//submit and wait until the task complete
Future<Void> future = poolMainExecutor.submit(new SearchingOperation()).get();
Use ThreadPoolExecutor.awaitTermination():
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
As in your code, you create your ThreadPoolExecutor first
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Constant.NUM_OF_THREAD);
Then, you need to add Tasks to it:
poolMainExecutor.execute(myTask);
poolMainExecutor.submit(myTask);
execute will return nothing, while submit will return a Future object. Tasks must implement Runnable or Callable. An object of SearchingOperation is a task for example. The thread pool will execute the tasks in parallel, but each task will be executed by one thread. That means to effectively use NUM_OF_THREAD Threads you need to add at least NUM_OF_THREAD Tasks.
(Optional) Once you got all jobs to work, shutdown your pool. This will prevent new tasks from being submitted. It won't affect running tasks.
poolMainExecutor.shutdown();
At the end, you need to wait for all Tasks to complete. The easiest way is by calling
poolMainExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
You should adjust the amount of time you want to wait for the tasks to finish before throwing an exception.
Now that the work is done, notify the user. A simple way is to call one of the Dialog presets from JOptionPane, like:
JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.INFORMATION_MESSAGE);
It will popup a little window with title "title", the message "message", an "information" icon and a button to close it.
This code can be used., it will check whether the execution is completed in every 2.5 seconds.
do {
System.out.println("In Progress");
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (poolMainExecutor.getActiveCount() != 0);
System.out.println("Completed");

Invoke more than one webservice using separate thread in java?

I have to call more than one webservice in one method each webservice is executed by separate thread in concurrent/parellel. Every web service will return one ArrayList. Note: may chance some webservices will fail or take more time process response in this case i have to skip these failure result. How can I achieve this? I tried this sample code.
public class MultiThreadsEx{
public class Task implements Runnable {
private Object result;
private String id;
int maxRowCount = 0;
public Task(String id) {
this.id = id;
}
public Object getResult() {
return result;
}
public void run() {
try {
System.out.println("Running id=" + id+" at "+Utilities.getCurrentJavaDate("DD/MM/YYYY HH:MM:SS"));
if(id.equalsIgnoreCase("1")){
/**Getting Details from Amazon WS*/
maxRowCount = AmazonUtils.getweather(cityname);
}else if(id.equalsIgnoreCase("2")){
/**Getting Details from Google WS* /
maxRowCount = GoogleUtils.getWeather(cityName);
}
// call web service
//Thread.sleep(1000);
//result = id + " more";
result = maxRowCount;
} catch (InterruptedException e) {
// TODO do something with the error
throw new RuntimeException("caught InterruptedException", e);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void runInParallel(Runnable runnable1, Runnable runnable2) {
try {
Thread t1 = new Thread(runnable1);
Thread t2 = new Thread(runnable2);
t1.start();
t2.start();
} catch (Exception e) {
// TODO do something nice with exception
throw new RuntimeException("caught InterruptedException", e);
}
}
public void foo() {
try {
Task task1 = new Task("1");
Task task2 = new Task("2");
runInParallel(task1, task2);
System.out.println("task1 = " + task1.getResult()+" at "+Utilities.getCurrentJavaDate("DD/MM/YYYY HH:MM:SS"));
System.out.println("task2 = " + task2.getResult()+" at "+Utilities.getCurrentJavaDate("DD/MM/YYYY HH:MM:SS"));
} catch (Exception e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
But run() return type is void so how can return result? Examples are highly appreciated. I am new to multithread/concurrent threads concept so if I'm doing anything wrong, please point me in the right direction.
Consider replacing Runnable - run with Callable - call. This will allow you to return a result from your thread task:
public class Task implements Callable<Object> {
private Object result;
public Object call() {
// compute result
return result;
}
}
Now use an ExecutorService:
public static void runInParallel(Callable<Object> c1, Callable<Object> c2) {
ExecutorService exec = Executors.newFixedThreadPool(2);
Future<Object> f1 = exec.submit(c1);
Future<Object> f2 = exec.submit(c2);
}
Later in the code you can use f1.get() and f2.get() to wait for the results of the tasks.
The usual way to communicate the results of a Runnable back to the object which created it is by passing the creating object to the constructor of the Runnable. When the task is finished, you can call a method in the creating object and pass the result data.

Categories