How to send multiple asynchronous requests to different web services?

后端 未结 6 1341
梦谈多话
梦谈多话 2021-02-01 07:27

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 sen

6条回答
  •  情话喂你
    2021-02-01 07:56

    You can ask your jax-ws implementation to generate asynchronous bindings for the web service.

    This has two advantages that I can see:

    1. 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)
    2. 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 :

        
        
            true
            
    
    

    When you specify this bindings file to wsimport, it'll generate a client which returns an object that implements javax.xml.ws.Response. 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> students1 = ws1.getStudents();
        Response> students2 = ws2.getStudents();
        Response> students3 = ws3.getStudents();
    
        Response> doctors1 = ws4.getDoctors();
        Response> doctors2 = ws5.getDoctors();
        Response> doctors3 = ws6.getDoctors();
    
        Response> patients1 = ws7.getPatients();
        Response> patients2 = ws8.getPatients();
        Response> 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>> {
        public void handleResponse(List 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> responses = new ArrayList>();
        // 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!

提交回复
热议问题