I have the following methods:
#EnableAsync
#Service
Class MyService{
private String processRequest() {
log.info("Start processing request");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("Completed processing request");
return RESULT;
}
#Async
public CompletableFuture<String> getSupplyAsyncResult(){
CompletableFuture<String> future
= CompletableFuture.supplyAsync(this::processRequest);
return future;
}
#Async
public CompletableFuture<String> getCompletedFutureResult(){
CompletableFuture<String> future
= CompletableFuture.supplyAsync(this::processRequest);
return future;
}
and the following endpoints in controller:
#RequestMapping(path = "/asyncSupplyAsync", method = RequestMethod.GET)
public CompletableFuture<String> getValueAsyncUsingCompletableFuture() {
log.info("Request received");
CompletableFuture<String> completableFuture
= myService.getSupplyAsyncResult();
log.info("Servlet thread released");
return completableFuture;
}
and
#RequestMapping(path = "/asyncCompletable", method = RequestMethod.GET)
public CompletableFuture<String> getValueAsyncUsingCompletableFuture() {
log.info("Request received");
CompletableFuture<String> completableFuture
= myService.getCompletedFutureResult();
log.info("Servlet thread released");
return completableFuture;
}
Why would anyone use completableFuture.supplyAsync within #Async method in Spring endpoint?
I assume using completableFuture.completedFuture is more appropriate, please share your views.
They serve entirely different purposes to begin with. Before you think about how much it takes one or the other to process, you might want to understand how they work, first (so little calls are no indication of slow/fast anyway; these numbers mean nothing in this context).
Here is the same example you have:
public class SO64718973 {
public static void main(String[] args) {
System.out.println("dispatching to CF...");
//CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> processRequest());
CompletableFuture<String> future = CompletableFuture.completedFuture(processRequest());
System.out.println("done dispatching to CF...");
future.join();
}
private static String processRequest() {
System.out.println("Start processing request");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Completed processing request");
return "RESULT";
}
}
You can run this and then change the implementation (by uncommenting CompletableFuture.supplyAsync) and see where those System.out.println occur. You will notice that completedFuture will block main thread until it is executed, while supplyAsync will run in a different thread. So it's not like one is wrong and one is not, it depends on your use-case.
In general, it is not a great idea to use CompletableFuture.supplyAsync without configuring a pool for it; otherwise it will consume threads from ForkJoinPool.
Suppose I have a two classes that work together to execute a callable like this:
public class blah {
#Autowired
private ExecutorServiceUtil executorServiceUtil;
#Autowired
private RestTemplate restClient;
public SomeReturnType getDepositTransactions(HttpHeaders httpHeaders) {
ExecutorService executor = executorServiceUtil.createExecuter();
try {
DepositTransactionsAsyncResponse asyncResponse = getPersonalCollectionAsyncResponse( httpHeaders, executor);
// do some processing
// return appropriate return type
}finally {
executorServiceUtil.shutDownExecutor(executor);
}
}
Future<ResponseEntity<PersonalCollectionResponse>> getPersonalCollectionAsyncResponse( HttpHeaders httpHeaders, ExecutorService executor) {
PersonalCollectionRequest personalCollectionRequest = getpersonalCollectionRequest(); // getPersonalCollectionRequest populates the request appropriately
return executor.submit(() -> restClient.exchange(personalCollectionRequest, httpHeaders, PersonalCollectionResponse.class));
}
}
public class ExecutorServiceUtil {
private static Logger log = LoggerFactory.getLogger(ExecutorServiceUtil.class);
public ExecutorService createExecuter() {
return Executors.newCachedThreadPool();
}
public void shutDownExecutor(ExecutorService executor) {
try {
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.error("Tasks were interrupted");
}
finally {
if (!executor.isTerminated()) {
log.error("Cancel non-finished tasks");
}
executor.shutdownNow();
}
}
}
How can I use Mockito to stub the a response and return it immediately?
I've tried the below but my innovcation.args() returns [null]
PowerMockito.when(executor.submit(Matchers.<Callable<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>>> any())).thenAnswer(new Answer<FutureTask<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>>>() {
#Override
public FutureTask<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>> answer(InvocationOnMock invocation) throws Throwable {
Object [] args = invocation.getArguments();
Callable<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>> callable = (Callable<ResponseEntity<OrxPendingPostedTrxCollectionResponseV3>>) args[0];
callable.call();
return null;
}
});
You do that by not using your ExecutorServiceUtil in your test code. What I mean is: you provide a mock of that util class to your production code!
And that mock does return a "same thread executor service"; instead of a "real service" (based on a thread pool). Writing such a same-thread-executor is actually straight forward - see here.
In other words: you want two different unit tests here:
You write unit tests for your ExecutorServiceUtil class in isolation; make sure it does the thing it is supposed to do (where I think: checking that it returns a non-null ExecutorService is almost good enough!)
You write unit tests for your blah class ... that use a mocked service. And all of a sudden, all your problems around "it is async" go away; because the "async" part vanishes in thin air.
I'm trying to figure out a way to implement an asynchronous retry mechanism using Hazelcast IExecutorService without recursive calls:
The recursive solution looks like that:
Callable task = ...
private sendToExecutor(){
Future future = submitToExecutorService(task);
((ICompletableFuture<ActionReply>) future).andThen(callback);
}
The callback is an ExecutionCallback:
#Override
public void onResponse(ActionReply response) {
// normal stuff
}
#Override
public void onFailure(Throwable t) {
// re-send if possible
if(numRetries < max_retries){
sendToExecutor();
}
}
I'm struggling to find a nice solution that does not involve the recursion. Any help will be appreciated. Thanks!
Create a wrapper class that implements Future and implement the get method which should catch RetryableHazelcastException. Note that you need have a limit on number of retries. If it crosses that limit means, there some major problem with your cluster.
public class RetryableFuture implements Future {
//Implement other methods.
#Override
public Object get() throws InterruptedException, ExecutionException {
try{
//get operation on future object
}catch(ExecutionException e){
if(e.getCause() instanceof RetryableHazelcastException){
//Log some warnings and submit the task back to Executors
}
}catch(Exception e){
//Not all exceptions are retryable
}finally {
//Close any kind of resources.
}
}
}
I've been looking for hints on how to best test Spring MVC Controller methods that return SseEmitters. I have come up pretty short, but have a trial-and-error solution that tests against asynchronous, threaded behavior. The below is sample code just to demonstrate concept, there may be a typo or two:
Controller Class:
#Autowired
Publisher<MyResponse> responsePublisher;
#RequestMapping("/mypath")
public SseEmitter index() throws IOException {
SseEmitter emitter = new SseEmitter();
Observable<MyResponse> responseObservable = RxReactiveStreams.toObservable(responsePublisher);
responseObservable.subscribe(
response -> {
try {
emitter.send(response);
} catch (IOException ex) {
emitter.completeWithError(ex);
}
},
error -> {
emitter.completeWithError(error);
},
emitter::complete
);
return emitter;
}
Test Class:
//A threaded dummy publisher to demonstrate async properties.
//Sends 2 responses with a 250ms pause in between.
protected static class MockPublisher implements Publisher<MyResponse> {
#Override
public void subscribe(Subscriber<? super MyResponse> subscriber) {
new Thread() {
#Override
public void run() {
try {
subscriber.onNext(response1);
Thread.sleep(250);
subscriber.onNext(response2);
} catch (InterruptedException ex) {
}
subscriber.onComplete();
}
}.start();
}
}
//Assume #Configuration that autowires the above mock publisher in the controller.
//Tests the output of the controller method.
#Test
public void testSseEmitter() throws Exception {
String path = "http://localhost/mypath/";
String expectedContent = "data:" + response1.toString() + "\n\n" +
"data:" + response2.toString() + "\n\n");
//Trial-and-Error attempts at testing this SseEmitter mechanism have yielded the following:
//- Returning an SseEmitter triggers 'asyncStarted'
//- Calling 'asyncResult' forces the test to wait for the process to complete
//- However, there is no actual 'asyncResult' to test. Instead, the content is checked for the published data.
mockMvc.perform(get(path).contentType(MediaType.ALL))
.andExpect(status().isOk())
.andExpect(request().asyncStarted())
.andExpect(request().asyncResult(nullValue()))
.andExpect(header().string("Content-Type", "text/event-stream"))
.andExpect(content().string(expectedContent))
}
As noted in the comments, asyncResult() is called to ensure that the publisher finishes its work and sends both responses before the test completes. Without it, the content check fails due to only one response being present in the content. However there is no actual result to check, hence asyncResult is null.
My specific question is whether there is a better, more precise way to force the test to wait for the async process to finish, rather than the klugie method here of waiting for a non-existent asyncResult. My broader question is whether there are other libs or Spring methods that are better suited to this vs. these async functions. Thanks!
This is a more general answer as it is meant to test an SseEmitter that will run forever, but will disconnect from SSE stream after a given timeout.
As for a different approach than MVC, as #ErinDrummond commented to the OP, you might want to investigate WebFlux.
It is a minimal example. One might want to expand with headers to the request, different matchers or maybe work on the stream output separately.
It is setting a delayed thread for disconnecting from SSE Stream which will allow to perform assertions.
#Autowired
MockMvc mockMvc;
#Test
public void testSseEmitter(){
ScheduledExecutorService execService = Executors.newScheduledThreadPool(1);
String streamUri = "/your-get-uri");
long timeout = 500L;
TimeUnit timeUnit = TimeUnit.MILLISECONDS;
MvcResult result = mockMvc.perform(get(streamURI)
.andExpect(request().asyncStarted()).andReturn();
MockAsyncContext asyncContext = (MockAsyncContext) result.getRequest().getAsyncContext();
execService.schedule(() -> {
for (AsyncListener listener : asyncContext.getListeners())
try {
listener.onTimeout(null);
} catch (IOException e) {
e.printStackTrace();
}
}, timeout, timeUnit);
result.getAsyncResult();
// assertions, e.g. response body as string contains "xyz"
mvc.perform(asyncDispatch(result)).andExpect(content().string(containsString("xyz")));
}
I need to send multiple requests to many different web services and receive the results. The problem is that, if I send the requests one by one it takes so long as I need to send and process all individually.
I am wondering how I can send all the requests at once and receive the results.
As the following code shows, I have three major methods and each has its own sub methods.
Each sub method sends request to its associated web service and receive the results;therefore, for example, to receive the results of web service 9 I have to wait till all web services from 1 to 8 get completed, it takes a long time to send all the requests one by one and receive their results.
As shown below none of the methods nor sub-methods are related to each other, so I can call them all and receive their results in any order, the only thing which is important is to receive the results of each sub-method and populate their associated lists.
private List<StudentsResults> studentsResults = new ArrayList();
private List<DoctorsResults> doctorsResults = new ArrayList();
private List<PatientsResults> patientsResults = new ArrayList();
main (){
retrieveAllLists();
}
retrieveAllLists(){
retrieveStudents();
retrieveDoctors();
retrievePatients();
}
retrieveStudents(){
this.studentsResults = retrieveStdWS1(); //send request to Web Service 1 to receive its list of students
this.studentsResults = retrieveStdWS2(); //send request to Web Service 2 to receive its list of students
this.studentsResults = retrieveStdWS3(); //send request to Web Service 3 to receive its list of students
}
retrieveDoctors(){
this.doctorsResults = retrieveDocWS4(); //send request to Web Service 4 to receive its list of doctors
this.doctorsResults = retrieveDocWS5(); //send request to Web Service 5 to receive its list of doctors
this.doctorsResults = retrieveDocWS6(); //send request to Web Service 6 to receive its list of doctors
}
retrievePatients(){
this.patientsResults = retrievePtWS7(); //send request to Web Service 7 to receive its list of patients
this.patientsResults = retrievePtWS8(); //send request to Web Service 8 to receive its list of patients
this.patientsResults = retrievePtWS9(); //send request to Web Service 9 to receive its list of patients
}
That is a simple fork-join approach, but for clarity, you can start any number of threads and retrieve the results later as they are available, such as this approach.
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Callable<String>> tasks = new ArrayList<>();
tasks.add(new Callable<String>() {
public String call() throws Exception {
Thread.sleep((new Random().nextInt(5000)) + 500);
return "Hello world";
}
});
List<Future<String>> results = pool.invokeAll(tasks);
for (Future<String> future : results) {
System.out.println(future.get());
}
pool.shutdown();
UPDATE, COMPLETE:
Here's a verbose, but workable solution. I wrote it ad hoc, and have not compiled it.
Given the three lists have diffent types, and the WS methods are individual, it is not
really modular, but try to use your best programming skills and see if you can modularize it a bit better.
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Callable<List<StudentsResults>>> stasks = new ArrayList<>();
List<Callable<List<DoctorsResults>>> dtasks = new ArrayList<>();
List<Callable<List<PatientsResults>>> ptasks = new ArrayList<>();
stasks.add(new Callable<List<StudentsResults>>() {
public List<StudentsResults> call() throws Exception {
return retrieveStdWS1();
}
});
stasks.add(new Callable<List<StudentsResults>>() {
public List<StudentsResults> call() throws Exception {
return retrieveStdWS2();
}
});
stasks.add(new Callable<List<StudentsResults>>() {
public List<StudentsResults> call() throws Exception {
return retrieveStdWS3();
}
});
dtasks.add(new Callable<List<DoctorsResults>>() {
public List<DoctorsResults> call() throws Exception {
return retrieveDocWS4();
}
});
dtasks.add(new Callable<List<DoctorsResults>>() {
public List<DoctorsResults> call() throws Exception {
return retrieveDocWS5();
}
});
dtasks.add(new Callable<List<DoctorsResults>>() {
public List<DoctorsResults> call() throws Exception {
return retrieveDocWS6();
}
});
ptasks.add(new Callable<List<PatientsResults>>() {
public List<PatientsResults> call() throws Exception {
return retrievePtWS7();
}
});
ptasks.add(new Callable<List<PatientsResults>>() {
public List<PatientsResults> call() throws Exception {
return retrievePtWS8();
}
});
ptasks.add(new Callable<List<PatientsResults>>() {
public List<PatientsResults> call() throws Exception {
return retrievePtWS9();
}
});
List<Future<List<StudentsResults>>> sresults = pool.invokeAll(stasks);
List<Future<List<DoctorsResults>>> dresults = pool.invokeAll(dtasks);
List<Future<List<PatientsResults>>> presults = pool.invokeAll(ptasks);
for (Future<List<StudentsResults>> future : sresults) {
this.studentsResults.addAll(future.get());
}
for (Future<List<DoctorsResults>> future : dresults) {
this.doctorsResults.addAll(future.get());
}
for (Future<List<PatientsResults>> future : presults) {
this.patientsResults.addAll(future.get());
}
pool.shutdown();
Each Callable returns a list of results, and is called in its own separate thread.
When you invoke the Future.get() method you get the result back onto the main thread.
The result is NOT available until the Callable have finished, hence there is no concurrency issues.
So just for fun I am providing two working examples. The first one shows the old school way of doing this before java 1.5. The second shows a much cleaner way using tools available within java 1.5:
import java.util.ArrayList;
public class ThreadingExample
{
private ArrayList <MyThread> myThreads;
public static class MyRunnable implements Runnable
{
private String data;
public String getData()
{
return data;
}
public void setData(String data)
{
this.data = data;
}
#Override
public void run()
{
}
}
public static class MyThread extends Thread
{
private MyRunnable myRunnable;
MyThread(MyRunnable runnable)
{
super(runnable);
setMyRunnable(runnable);
}
/**
* #return the myRunnable
*/
public MyRunnable getMyRunnable()
{
return myRunnable;
}
/**
* #param myRunnable the myRunnable to set
*/
public void setMyRunnable(MyRunnable myRunnable)
{
this.myRunnable = myRunnable;
}
}
public ThreadingExample()
{
myThreads = new ArrayList <MyThread> ();
}
public ArrayList <String> retrieveMyData ()
{
ArrayList <String> allmyData = new ArrayList <String> ();
if (isComplete() == false)
{
// Sadly we aren't done
return (null);
}
for (MyThread myThread : myThreads)
{
allmyData.add(myThread.getMyRunnable().getData());
}
return (allmyData);
}
private boolean isComplete()
{
boolean complete = true;
// wait for all of them to finish
for (MyThread x : myThreads)
{
if (x.isAlive())
{
complete = false;
break;
}
}
return (complete);
}
public void kickOffQueries()
{
myThreads.clear();
MyThread a = new MyThread(new MyRunnable()
{
#Override
public void run()
{
// This is where you make the call to external services
// giving the results to setData("");
setData("Data from list A");
}
});
myThreads.add(a);
MyThread b = new MyThread (new MyRunnable()
{
#Override
public void run()
{
// This is where you make the call to external services
// giving the results to setData("");
setData("Data from list B");
}
});
myThreads.add(b);
for (MyThread x : myThreads)
{
x.start();
}
boolean done = false;
while (done == false)
{
if (isComplete())
{
done = true;
}
else
{
// Sleep for 10 milliseconds
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public static void main(String [] args)
{
ThreadingExample example = new ThreadingExample();
example.kickOffQueries();
ArrayList <String> data = example.retrieveMyData();
if (data != null)
{
for (String s : data)
{
System.out.println (s);
}
}
}
}
This is the much simpler working version:
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadingExample
{
public static void main(String [] args)
{
ExecutorService service = Executors.newCachedThreadPool();
Set <Callable<String>> callables = new HashSet <Callable<String>> ();
callables.add(new Callable<String>()
{
#Override
public String call() throws Exception
{
return "This is where I make the call to web service A, and put its results here";
}
});
callables.add(new Callable<String>()
{
#Override
public String call() throws Exception
{
return "This is where I make the call to web service B, and put its results here";
}
});
callables.add(new Callable<String>()
{
#Override
public String call() throws Exception
{
return "This is where I make the call to web service C, and put its results here";
}
});
try
{
List<Future<String>> futures = service.invokeAll(callables);
for (Future<String> future : futures)
{
System.out.println (future.get());
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
}
}
You can ask your jax-ws implementation to generate asynchronous bindings for the web service.
This has two advantages that I can see:
As discussed in Asynchronous web services calls with JAX-WS: Use wsimport support for asynchrony or roll my own? , jax-ws will generate well-tested (and possibly fancier) code for you, you need not instantiate the ExecutorService yourself. So less work for you! (but also less control over the threading implementation details)
The generated bindings include a method where you specify a callback handler, which may suit your needs better than synchronously get() ting all response lists on the thread calling retrieveAllLists(). It allows for per-service-call error handling and will process the results in parallel, which is nice if processing is non-trivial.
An example for Metro can be found on the Metro site. Note the contents of the custom bindings file custom-client.xml :
<bindings ...>
<bindings node="wsdl:definitions">
<enableAsyncMapping>true</enableAsyncMapping>
</bindings>
</bindings>
When you specify this bindings file to wsimport, it'll generate a client which returns an object that implements javax.xml.ws.Response<T>. Response extends the Future interface that others also suggest you use when rolling your own implementation.
So, unsurprisingly, if you go without the callbacks, the code will look similar to the other answers:
public void retrieveAllLists() throws ExecutionException{
// first fire all requests
Response<List<StudentsResults>> students1 = ws1.getStudents();
Response<List<StudentsResults>> students2 = ws2.getStudents();
Response<List<StudentsResults>> students3 = ws3.getStudents();
Response<List<DoctorsResults>> doctors1 = ws4.getDoctors();
Response<List<DoctorsResults>> doctors2 = ws5.getDoctors();
Response<List<DoctorsResults>> doctors3 = ws6.getDoctors();
Response<List<PatientsResults>> patients1 = ws7.getPatients();
Response<List<PatientsResults>> patients2 = ws8.getPatients();
Response<List<PatientsResults>> patients3 = ws9.getPatients();
// then await and collect all the responses
studentsResults.addAll(students1.get());
studentsResults.addAll(students2.get());
studentsResults.addAll(students3.get());
doctorsResults.addAll(doctors1.get());
doctorsResults.addAll(doctors2.get());
doctorsResults.addAll(doctors3.get());
patientsResults.addAll(patients1.get());
patientsResults.addAll(patients2.get());
patientsResults.addAll(patients3.get());
}
If you create callback handers such as
private class StudentsCallbackHandler
implements AsyncHandler<Response<List<StudentsResults>>> {
public void handleResponse(List<StudentsResults> response) {
try {
studentsResults.addAll(response.get());
} catch (ExecutionException e) {
errors.add(new CustomError("Failed to retrieve Students.", e.getCause()));
} catch (InterruptedException e) {
log.error("Interrupted", e);
}
}
}
you can use them like this:
public void retrieveAllLists() {
List<Future<?>> responses = new ArrayList<Future<?>>();
// fire all requests, specifying callback handlers
responses.add(ws1.getStudents(new StudentsCallbackHandler()));
responses.add(ws2.getStudents(new StudentsCallbackHandler()));
responses.add(ws3.getStudents(new StudentsCallbackHandler()));
...
// await completion
for( Future<?> response: responses ) {
response.get();
}
// or do some other work, and poll response.isDone()
}
Note that the studentResults collection needs to be thread safe now, since results will get added concurrently!
Looking at the problem, you need to integrate your application with 10+ different webservices.While making all the calls asynchronous. This can be done easily with Apache Camel. It is a prominent framework for enterprise integration and also supports async processing. You can use its CXF component for calling webservices and its routing engine for invocation and processing results. Look at the following page regarding camel's async routing capability. They have also provided a complete example invoking webservices async using CXF, it available at its maven repo. Also see the following page for more details.
You might consider the following paradigm in which you create work (serially), but the actual work is done in parallel. One way to do this is to: 1) have your "main" create a queue of work items; 2) create a "doWork" object that queries the queue for work to do; 3) have "main" start some number of "doWork" threads (can be same number as number of different services, or a smaller number); have the "doWork" objects put add their results to an object list (whatever construct works Vector, list...).
Each "doWork" object would mark their queue item complete, put all results in the passed container and check for new work (if no more on the queue, it would sleep and try again).
Of course you will want to see how well you can construct your class model. If each of the webservices is quite different for parsing, then you may want to create an Interface that each of your "retrieveinfo" classes promises to implement.
It has got various option to develop this.
JMS : quality of service and management, e.g. redelivery attempt, dead message queue, load management, scalability, clustering, monitoring, etc.
Simply using the Observer pattern for this. For more details OODesign and How to solve produce and consumer follow this Kodelog**