java - How to send parallel GET requests and wait for result responses? -


i'm using apache http client within spring mvc 3.2.2 send 5 requests synchronously illustrated.

how can send of these asynchronously (in parallel) , wait requests return in order return parsed payload string requests?

public string mymvccontrollergetdatamethod() {    // send 1st request     httpclient httpclient = new defaulthttpclient();    httpget httpget = new httpget("http://api/data?type=1");       responsehandler<string> responsehandler = new basicresponsehandler();    string responsebody = httpclient.execute(httpget, responsehandler);     // send 2st request     httpclient httpclient2 = new defaulthttpclient();    httpget httpget2 = new httpget("http://api/data?type=2");       responsehandler2<string> responsehandler2 = new basicresponsehandler();    string responsebody2 = httpclient.execute(httpget, responsehandler2);     // o o o more gets here     // perform work here...and wait requests return    // parse info out of multiple requests , return    string results = doworkwithmultipledatareturned();     model.addattribute(results, results);    return "index";  } 

just in general, need encapsulate units of work in runnable or java.util.concurrent.callable , execute them via java.util.concurrent.executor (or org.springframework.core.task.taskexecutor). allows each unit of work executed separately, typically in asynchronous fashion (depending on implementation of executor).

so specific problem, this:

import java.util.arraylist; import java.util.iterator; import java.util.list; import java.util.concurrent.callable; import java.util.concurrent.executor; import java.util.concurrent.futuretask; import org.apache.http.client.methods.httpget; import org.apache.http.impl.client.basicresponsehandler; import org.apache.http.impl.client.defaulthttpclient; import org.springframework.stereotype.controller; import org.springframework.ui.model; import org.springframework.web.bind.annotation.requestmapping;  @controller public class mycontroller {     //inject     private executor executor;      @requestmapping("/your/path/here")     public string mymvccontrollergetdatamethod(model model) {         //define async requests , give them injected executor         list<getrequesttask> tasks = new arraylist<getrequesttask>();         tasks.add(new getrequesttask("http://api/data?type=1", this.executor));         tasks.add(new getrequesttask("http://api/data?type=2", this.executor));         //...         //do other work here         //...         //now wait async tasks complete         while(!tasks.isempty()) {             for(iterator<getrequesttask> = tasks.iterator(); it.hasnext();) {                 getrequesttask task = it.next();                 if(task.isdone()) {                     string request = task.getrequest();                     string response = task.getresponse();                     //put code here                     //possibly aggregate request , response in map<string,string>                     //or else request , response                     it.remove();                 }             }             //avoid tight loop in "main" thread             if(!tasks.isempty()) thread.sleep(100);         }         //now have responses async requests          //the following original code         //note: should pass responses above         //to next method (to keep controller stateless)         string results = doworkwithmultipledatareturned();         model.addattribute(results, results);         return "index";     }      //abstraction wrap callable , future     class getrequesttask {         private getrequestwork work;         private futuretask<string> task;         public getrequesttask(string url, executor executor) {             this.work = new getrequestwork(url);             this.task = new futuretask<string>(work);             executor.execute(this.task);         }         public string getrequest() {             return this.work.geturl();         }         public boolean isdone() {             return this.task.isdone();         }         public string getresponse() {             try {                 return this.task.get();             } catch(exception e) {                 throw new runtimeexception(e);             }         }     }      //callable representing actual http request     class getrequestwork implements callable<string> {         private final string url;         public getrequestwork(string url) {             this.url = url;         }         public string geturl() {             return this.url;         }         public string call() throws exception {             return new defaulthttpclient().execute(new httpget(geturl()), new basicresponsehandler());         }     } } 

note code has not been tested.

for executor implementation, check out spring's taskexecutor , task:executor namespace. want reusable pool of threads use-case (instead of creating new thread every time).


Comments

Popular posts from this blog

html5 - What is breaking my page when printing? -

c# - must be a non-abstract type with a public parameterless constructor in redis -

ajax - PHP/JSON Login script (Twitter style) not setting sessions -