user2095246
user2095246

Reputation: 45

Spring @Async with Future

I am new to java.util.concurrent.Future and have some questions. If I call a service using Future how do I know what element was used to call the service?

Here is an example:

  1. For each id I am using java.util.concurrent.Future to call a service to fill some extra data.

    Collection< Future< ObjectX>> future = new ArrayList< Future< ObjectX>>();  
    

    Edit###

     List< ObjectY> serviceResult= new ArrayList< ObjectY>();
    
    for (ObjectX obj: ids) 
     {  
       future.add(getAsyncInfo(obj);
     }
    
    //Because I have a lot of ids i need to call the service @async
    @Async
    public  Future< ObjectY> getAsyncInfo(ObjectX obj){
    
    return new AsyncResult<ObjectY>(callService(obj));
        ...
     }
    

Get the response

for (Future<ObjectY> futureResult : future) 
    {               
        serviceResult.add(futureResult.get());
    }

In this stage I have a List of results, and I don´t know what result belongs to what id

     ids.get(0).setResult(serviceResult.get(0))????
     ids.get(0).setResult(serviceResult.get(1))????
     ids.get(0).setResult(serviceResult.get(2))????
     ...

Thank you!

Upvotes: 4

Views: 3080

Answers (2)

nicholas.hauschild
nicholas.hauschild

Reputation: 42849

There are a couple things you can do here.

  1. Have your Collection of Future's be a Map instead (Map<MyKey, Future<ObjectX>>) The key of the Map should be some means you can use to map back to your initial ObjectX.
  2. Have your service return some info on its return value to assist in determining the id.

For 1, I was thinking something like this:

//to kick off the tasks
Map<ObjectX, Future<ObjectY>> futures = new HashMap<ObjectX, Future<ObjectY>>();
for (ObjectX id: ids) 
{  
    futures.put(id, getAsyncInfo(id));
}

//...some time later...

//to fetch the results
for(Map.Entry<ObjectX, Future<ObjectY>> entry : futures.entrySet())
{
    final ObjectX id = entry.getKey();
    final Future<ObjectY> future = entry.getValue();
    final ObjectY objY = future.get();
    id.setResult(objY);
}

Upvotes: 0

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136002

I would do it this way

class MyResult extends AsyncResult<Object> {
    Object id;
    public MyResult(Object id, Object res) {
        super(res);
        this.id = id;
    }
    public Object getId() {
        return id;
    }
}

@Async
public MyResult getAsyncInfo(Object id) {
    Object res = callService(id);
    return new MyResult(id, res);
}

Now you know both result and id. Id and result may be of any type

Upvotes: 2

Related Questions