Java Futures y Enterprise Java Beans

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.

Java Futures EJB

 

 

 

 

 

¿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.

 

Java Futures Servlets

 

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.

Java Futures Time

Otros artículos relacionados: EJB Async  , EJB Remote vs Local (JEE 6)Introducción a EJB 3.1 (I)

It's only fair to share...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

About Cecilio Álvarez Caules

Cecilio Álvarez Caules Sun Certified Enterprise Architech (J2EE/JEE).

4 Responses to Java Futures y Enterprise Java Beans

  1. jllado 4 Febrero, 2017 at 0:53 #

    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?

    • Cecilio Álvarez Caules 4 Febrero, 2017 at 14:08 #

      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 🙂

      • jllado 4 Febrero, 2017 at 21:37 #

        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? 🙂

        • Cecilio Álvarez Caules 6 Febrero, 2017 at 10:29 #

          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

Deja un comentario