utiliza util tiempo metodo ejemplo ejecutar detener como cierto cada jsf jsf-2 timer scheduled-tasks

jsf - util - timertask android



Engendrar hilos en un frijol administrado JSF para tareas programadas usando un temporizador (1)

Me gustaría saber si está bien usar el Timer dentro de los beans con alcance de la aplicación.

Por ejemplo, digamos que quiero crear una tarea de temporizador que envíe un montón de correos electrónicos a cada miembro registrado una vez al día. Estoy tratando de usar tanto JSF como sea posible y me gustaría saber si esto es aceptable (suena un poco raro, lo sé).

Hasta ahora, he usado todo lo anterior en un ServletContextListener . (No quiero usar ningún servidor de aplicaciones o trabajo cron y quiero mantener las cosas anteriores dentro de mi aplicación web).

¿Hay alguna forma inteligente de JSF de hacer esto o debería seguir con el viejo patrón?


Introducción

En cuanto a generar un hilo desde dentro de un bean gestionado JSF, solo tendría sentido si desea poder hacer referencia a él en sus vistas mediante #{managedBeanName} o en otros beans gestionados por @ManagedProperty("#{managedBeanName}") . Solo debe asegurarse de implementar @PreDestroy para asegurarse de que todos esos hilos se cierren cuando la aplicación esté a punto de apagarse, como lo haría en el método contextDestroyed() de ServletContextListener (sí, ¿lo hizo?). Consulte también ¿Es seguro iniciar un nuevo hilo en un bean gestionado JSF?

Nunca use java.util.Timer en Java EE

En cuanto al uso de java.util.Timer en un bean gestionado JSF, no debe usar el Timer antiguo, sino el moderno ScheduledExecutorService . El Timer tiene los siguientes problemas principales que lo hacen inadecuado para su uso en una aplicación web Java EE de larga ejecución (citada de Java Concurrency in Practice ):

  • Timer es sensible a los cambios en el reloj del sistema, ScheduledExecutorService no lo es.
  • Timer tiene solo un hilo de ejecución, por lo que la ejecución prolongada puede retrasar otras tareas. ScheduledExecutorService se puede configurar con cualquier cantidad de subprocesos.
  • Cualquier excepción de tiempo de ejecución lanzada en un TimerTask mata ese hilo, haciendo que el Timer TimerTask , es decir, las tareas programadas ya no se ejecutarán. ScheduledThreadExecutor no solo atrapa las excepciones de tiempo de ejecución, sino que le permite manejarlas si lo desea. La tarea que lanzó la excepción se cancelará, pero otras tareas continuarán ejecutándose.

Aparte de las citas de libros, puedo pensar en más desventajas:

  • Si olvida cancel() explícitamente cancel() el Timer , entonces sigue ejecutándose después del despliegue. Entonces, después de volver a implementar, se crea un nuevo hilo, haciendo el mismo trabajo nuevamente. Etcétera Se ha convertido en un "fuego y olvídate" por ahora y ya no puedes cancelarlo programáticamente. Básicamente, necesitaría apagar y reiniciar todo el servidor para borrar los hilos anteriores.

  • Si el hilo del Timer no está marcado como hilo daemon, entonces bloqueará el despliegue de la webapp y el apagado del servidor. Básicamente necesitarías matar al servidor. La principal desventaja es que la aplicación web no podrá realizar una limpieza elegante mediante, por ejemplo, contextDestroyed() y @PreDestroy .

EJB disponible? Use @Schedule

Si se dirige a Java EE 6 o posterior (por ejemplo, JBoss AS, GlassFish, TomEE, etc. y, por lo tanto, no es un contenedor barebone JSP / Servlet como Tomcat), utilice un EJB @Singleton con un método @Schedule . De esta forma, el contenedor se preocupe por agrupar y destruir subprocesos a través de ScheduledExecutorService . Todo lo que necesitas es entonces el siguiente EJB:

@Singleton public class BackgroundJobManager { @Schedule(hour="0", minute="0", second="0", persistent=false) public void someDailyJob() { // Do your job here which should run every start of day. } @Schedule(hour="*/1", minute="0", second="0", persistent=false) public void someHourlyJob() { // Do your job here which should run every hour of day. } @Schedule(hour="*", minute="*/15", second="0", persistent=false) public void someQuarterlyJob() { // Do your job here which should run every 15 minute of hour. } }

Esto es necesario si está disponible en beans administrados por @EJB :

@EJB private BackgroundJobManager backgroundJobManager;

EJB no disponible? Use ScheduledExecutorService

Sin EJB, necesitaría trabajar manualmente con ScheduledExecutorService . La implementación del bean administrado de la aplicación se vería así:

@ManagedBean(eager=true) @ApplicationScoped public class BackgroundJobManager { private ScheduledExecutorService scheduler; @PostConstruct public void init() { scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS); } @PreDestroy public void destroy() { scheduler.shutdownNow(); } }

donde SomeDailyJob ve así:

public class SomeDailyJob implements Runnable { @Override public void run() { // Do your job here. } }

Si no necesita referenciarlo en la vista u otros beans administrados, mejor solo use ServletContextListener para mantenerlo desacoplado de JSF.

@WebListener public class BackgroundJobManager implements ServletContextListener { private ScheduledExecutorService scheduler; @Override public void contextInitialized(ServletContextEvent event) { scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS); } @Override public void contextDestroyed(ServletContextEvent event) { scheduler.shutdownNow(); } }