Reputation: 1648
I would like to call 3 webservices in a same method, and each result will be setted in a object in like this code bellow:
public Dossie procuraPorCPF(String cpf) {
Dossie dossie = new Dossie();
// first webservice call
dossie.setCnh(detectaClientCnh.verificaCNH(cpf));
// second webservice call
dossie.setFotoCnh(detectaClientCnhFoto.verificaFotoCNHPorCpf(cpf));
// third webservice call
dossie.setPm(consultaPMWService.getPMPorCPF(cpf).getProcuraPMPorCPFResult());
return dossie;
}
In this case above, I'm calling 3 different webservices, they takes about 5 seconds each one, then is not good continue with this code. I would like to know what is the best way to call the 3 webservices at same time and how could I do it using this code as example. I've searched some articles or even answers here, but I didn't figure out how to do it. Thanks for the patience.
Upvotes: 2
Views: 1450
Reputation: 14389
I started writing this answer in the night and then left it for the next day. By the morning two answers were given and one of those was accepted by OP. Leaving this answer here for anyone who wishes to see the complete design and idea of the implementation, instead of actual code.
Since web service calls take time to respond, they are called asynchronously, meaning that the main thread is not synchronized with these calls.
So, they are designed such that you make individual calls on separate threads.
For your case, the important Java elements are:
call()
method.
Bonus Step: It seems to me that the three web service calls need to be made in the same order repeatedly (I don't understand the language - it isn't English). For such a code, a separate orchestrator class can be created at the top of classes created in step 1 of the implementation.
This orchestrator class can extend Thread class and make the three web service calls. Now, this one class can be run asynchronously, instead of making the three web service calls. Keeps the code modular and abstracts away the complexity.
Upvotes: 1
Reputation: 2678
You can use ExecutorService to submit Callable and call Future.get() to retrieve result as shown below (change Future<String> to the appropriate return value). You should also think about error handling and creating threadpool outside of method (if possible at app startup).
public Dossie procuraPorCPF(String cpf) {
ExecutorService executor = Executors.newFixedThreadPool(3);
Future<String> cnh = executor.submit(() -> detectaClientCnh.verificaCNH(cpf));
Future<String> fotoCnh = executor.submit(() -> detectaClientCnhFoto.verificaFotoCNHPorCpf(cpf));
Future<String> pm =
executor.submit(() -> consultaPMWService.getPMPorCPF(cpf).getProcuraPMPorCPFResult());
Dossie dossie = new Dossie();
try {
dossie.setCnh(cnh.get());
dossie.setFotoCnh(fotoCnh.get());
dossie.setPm(pm.get());
} catch (InterruptedException | ExecutionException cause) {
cause.printStackTrace();
}
executor.shutdown();
return dossie;
}
Upvotes: 1
Reputation: 2177
Concurrency in Java is handled through the Thread
class. The Thread
constructor accepts a Runnable
parameter with the code for the Thread
to run. When the start()
method is called, the JVM creates the new thread and executes the code in the run()
method of the Runnable
.
Since Runnable
only has the single abstract method run()
, you can use a lambda expression for more readable code. I used traditional syntax for the first call and lambda syntax for the other 2 to demonstrate both methods.
public Dossie procuraPorCPF(String cpf) {
Dossie dossie = new Dossie();
Thread[] threads = new Thread[3];
threads[0] = new Thread(new Runnable() {
@Override
public void run() {
dossie.setCnh(detectaClientCnh.verificaCNH(cpf));
}
};
threads[0].start();
threads[1] = new Thread(() ->
dossie.setFotoCnh(detectaClientCnhFoto.verificaFotoCNHPorCpf(cpf));
threads[1].start();
threads[2] = new Thread(() ->
dossie.setPm(consultaPMWService.getPMPorCPF(cpf).getProcuraPMPorCPFResult());
threads[2].start();
try {
threads[0].join();
threads[1].join();
threads[2].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return dossie;
}
The join()
method blocks program execution until the calling Thread
has finished running. By placing the join()
s at the end of the method, you can guarantee that all 3 requests have finished before you return. If it doesn't matter whether those requests have finished before you return, you can simply remove the join()
s and the requests will continue in the background while the rest of your application runs.
For larger applications, Java also includes thread pools which will manage the creation of Thread
s for you. Since your application only uses the same 3 Runnable
s in a local context, I think the solution above is better suited (and more educational for the purposes of this answer).
Upvotes: 2