El concepto de Java Futures esta ligado a la programación asíncrona . Vamos a usar Java Futures con Enterprise Java Beans para entender su utilidad. Para ello partiremos de dos 2 EJBs asíncronos que ejecutaran una tarea que tarda 5s y devuelven un Java Future.
¿Para que sirven los Java Futures?
Un Java Future es un objeto que se construye para albergar un valor en un futuro. Vamos a verlos funcionando en código.
package com.arquitecturajava.ejb;
import java.util.concurrent.Future;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class ServicioEJB2 {
@Asynchronous
public Future<String> getMensaje2() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new AsyncResult<String>("mensaje2 lento");
}
}
package com.arquitecturajava.ejb;
import java.util.concurrent.Future;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class ServicioEJB1 {
@Asynchronous
public Future<String> getMensaje1() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new AsyncResult<String>("mensaje1 lento");
}
}
En este caso tenemos dos EJBs y cada uno tiene un método getMensaje() . Con una programación normal cada EJB devolvería un String . Sin embargo en este caso al tratarse de EJBS asíncronos cada uno devuelve un Java Future a través de una variable de tipo AsyncResult. Vamos a usar un Servlet para acceder a ellos.
El código del servlet:
package com.arquitecturajava.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.arquitecturajava.ejb.ServicioEJB1;
import com.arquitecturajava.ejb.ServicioEJB2;
@WebServlet("/ServletEJB")
public class ServletEJB extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
ServicioEJB1 servicio1;
@EJB
ServicioEJB2 servicio2;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Future<String> futuro1=servicio1.getMensaje1();
Future<String> futuro2= servicio2.getMensaje2();
while(!futuro1.isDone() && !futuro2.isDone()) {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
PrintWriter pw=response.getWriter();
try {
pw.println(futuro1.get());
pw.println(futuro2.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
En este caso recibimos cada uno de los Futures creados por los EJBs. Usamos un bucle while y comprobamos el método isDone() de cada future para saber si ambas tareas han finalizado. En caso de no haber terminado ponemos el Servlet a dormir.
while(!futuro1.isDone() && !futuro2.isDone()) {
.. sleep
}
Cuando ambos EJBs asíncronos han terminado su ejecución los métodos isDone() devolverán true. En esa situación ya podemos acceder a los valores futuros e imprimirlos por la pantalla.
De esta forma conseguiremos que aunque ambos EJBs tardan 5 segundos en ejecutarse las peticiones se ejecuten en paralelo y en 6 segundos hayamos terminado.
Otros artículos relacionados: EJB Async , EJB Remote vs Local (JEE 6), Introducción a EJB 3.1 (I)




Mmmm, IMHO el bucle con el sleep no es necesario, el método get ya se encargará de esperar:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()
¿No te parece?
Si con eso es suficiente juan , incluso podrías poner get(timeout) yo he usado el bucle while para comprobar una condición doble con el isDone de las dos peticiones , creo que solo con el get no me valdría? , ya me confirmas , gracias 🙂
Con el bucle te aseguras que se impriman las dos a la vez. ¿Esa es la idea? Lo que tal como lo planteas, aunque los getMensaje terminan en 5 segundos, aún así esperas 6. Quizás lo has puesto para que se entienda mejor.
Sí tengo que coordinar varios Future’s lo que suelo hacer es meterlos en unas lista. Y luego la recorro recogiendo (con el get) los valores de Future (a veces metiendolo en otra lista de resultados).
Y luego ya trabajo con la lista resultante. ¿Qué te parece? 🙂
Puede ser una opción pero si se trata de algo complejo yo apostaría ya por integrar el API de RxJava y como el gestiona futures