2011-10-26 17 views
5

Tengo algún método dentro de mi controlador que ejecuta @Async tareaVolver @Async resultado del método en Spring MVC y devolverlo al cliente Ajax

@Async 
public Future<String> getResultFromServer(){ 
    String result = ...... 
    return new AsyncResult<String>(result); 
} 

El tiempo de ejecución del método es de hasta 1o minutos. Todo lo que necesito hacer es solo devolver el resultado al lado del cliente que se conectará usando AJAX/JQuery.

No deseo que el cliente solicite mi servidor cada segundo si el método @Async se ejecutó o no. Solo quiero mantener mi conexión abierta y luego simplemente enviar el resultado al servidor.

@RequestMapping(value="/async.do", method=RequestMethod.POST) 
public void getResult(HttpServletResponse res){ 
    String result = null; 
    PrintWriter out = res.getWriter(); 
    Future<String> future = getResultFromServer(); 
    try { 
     if (future.isDone()) 
      result = future.get(); 
     out.println(result); 
     out.close(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 
} 

Entiendo que esto sea muy parecido al modelo de Comit, pero no estoy familiarizado con el cometa en general.

Mi pregunta es ¿cómo puedo mantener la conexión abierta en el lado del cliente usando JavaScript/JQuery?

y ¿mi método @RequestMapping(value="/async.do", method=RequestMethod.POST) empujará el resultado al cliente?

+1

¿Cómo resolvió esto/parte 2 eventualmente? – happybuddha

Respuesta

2

La manera más fácil sería no invocar el método de forma asíncrona, sino invocarlo directamente desde el controlador de forma síncrona.

Luego, la solicitud deberá "esperar" hasta que se calcule el resultado del método, y puede devolverse tan pronto como se haya creado.

Por supuesto, esto significa que la conexión estará abierta por cuánto tiempo lleva hacer el trabajo (1 minuto).

+0

gracias por la respuesta y por la idea de ejecutar el método directamente, tengo otra preocupación: por lo que tengo entendido, Tomcat procede a mi solicitud en un hilo separado que se abre para mi conexión HTTP. ¿Significa que si mi solicitud continúa durante 15 minutos, entonces el hilo de Tomcat se ejecutará todo ese tiempo? ¿Significa que esta operación requiere 2 hilos para la solicitud y el segundo para la tarea de Asincronización? ¿Hay alguna forma de suspender el primer hilo mientras se ejecuta el segundo hilo (tarea asíncrona)? –

+0

Si usa '@ async', entonces tiene dos hilos, uno que invoca el método anotado por' @ async' y regresa al instante, y otro que realmente está haciendo las cosas en el método '@ async'. Para suspender el primer hilo, simplemente invoque future.get(), esto bloquea el hilo hasta que se calcule el resultado. Pero si lo haces: invocas el '@ async' y llamas a future.get() directamente después de wards, entonces el material completo de' @ ascync' es inútil, porque simulas (casi) el comportamiento normal de una invocación a un método con mucha técnica cosas. – Ralph

+0

@ danny.lesnik: ¡Pero si su cálculo tardará 15 minutos, entonces realmente necesita otra solución que no sea mantener una conexión durante este lapso de tiempo! – Ralph