Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>Introduction</h2> <p>As to spawning a thread from inside a JSF managed bean, it would <em>only</em> make sense if you want to be able to reference it in your views by <code>#{managedBeanName}</code> or in other managed beans by <a href="http://docs.oracle.com/javaee/7/api/javax/faces/bean/ManagedProperty.html" rel="noreferrer"><code>@ManagedProperty("#{managedBeanName}")</code></a>. You should only make sure that you implement <a href="http://docs.oracle.com/javaee/7/api/javax/annotation/PreDestroy.html" rel="noreferrer"><code>@PreDestroy</code></a> to ensure that all those threads are shut down whenever the webapp is about to shutdown, like as you would do in <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContextListener.html#contextDestroyed-javax.servlet.ServletContextEvent-" rel="noreferrer"><code>contextDestroyed()</code></a> method of <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContextListener.html" rel="noreferrer"><code>ServletContextListener</code></a> (yes, you did?). See also <a href="https://stackoverflow.com/questions/6149919/is-it-safe-to-start-a-new-thread-in-a-jsf-managed-bean">Is it safe to start a new thread in a JSF managed bean?</a></p> <h2>Never use <code>java.util.Timer</code> in Java EE</h2> <p>As to using <code>java.util.Timer</code> in a JSF managed bean, you should <strong>absolutely not</strong> use the old fashioned <code>Timer</code>, but the modern <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html" rel="noreferrer"><code>ScheduledExecutorService</code></a>. The <code>Timer</code> has the following major problems which makes it unsuitable for use in a long running Java EE web application (quoted from <a href="http://jcip.net/" rel="noreferrer">Java Concurrency in Practice</a>):</p> <ul> <li><code>Timer</code> is sensitive to changes in the system clock, <code>ScheduledExecutorService</code> isn't.</li> <li><code>Timer</code> has only one execution thread, so long-running task can delay other tasks. <code>ScheduledExecutorService</code> can be configured with any number of threads.</li> <li>Any runtime exceptions thrown in a <code>TimerTask</code> kill that one thread, thus making <code>Timer</code> dead, i.e. scheduled tasks will not run anymore. <code>ScheduledThreadExecutor</code> not only catches runtime exceptions, but it lets you handle them if you want. Task which threw exception will be canceled, but other tasks will continue to run.</li> </ul> <p>Apart from the book quotes, I can think of more disadvantages:</p> <ul> <li><p>If you forget to explicitly <code>cancel()</code> the <code>Timer</code>, then it keeps running after undeployment. So after a redeploy a new thread is created, doing the same job again. Etcetera. It has become a "fire and forget" by now and you can't programmatically cancel it anymore. You'd basically need to shutdown and restart the whole server to clear out previous threads. </p></li> <li><p>If the <code>Timer</code> thread is not marked as daemon thread, then it will block the webapp's undeployment and server's shutdown. You'd basically need to hard kill the server. The major disadvantage is that the webapp won't be able to perform graceful cleanup via e.g. <code>contextDestroyed()</code> and <code>@PreDestroy</code> methods.</p></li> </ul> <h2>EJB available? Use <code>@Schedule</code></h2> <p>If you target Java EE 6 or newer (e.g. JBoss AS, GlassFish, TomEE, etc and thus <em>not</em> a barebones JSP/Servlet container such as Tomcat), then use a <a href="http://docs.oracle.com/javaee/7/api/javax/ejb/Singleton.html" rel="noreferrer"><code>@Singleton</code></a> EJB with a <a href="http://docs.oracle.com/javaee/7/api/javax/ejb/Schedule.html" rel="noreferrer"><code>@Schedule</code></a> method instead. This way the container will worry itself about pooling and destroying threads via <code>ScheduledExecutorService</code>. All you need is then the following EJB:</p> <pre><code>@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. } } </code></pre> <p>This is if necessary available in managed beans by <a href="http://docs.oracle.com/javaee/7/api/javax/ejb/EJB.html" rel="noreferrer"><code>@EJB</code></a>:</p> <pre><code>@EJB private BackgroundJobManager backgroundJobManager; </code></pre> <h2>EJB unavailable? Use <code>ScheduledExecutorService</code></h2> <p>Without EJB, you'd need to manually work with <code>ScheduledExecutorService</code>. The application scoped managed bean implementation would look something like this:</p> <pre><code>@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(); } } </code></pre> <p>where the <code>SomeDailyJob</code> look like this:</p> <pre><code>public class SomeDailyJob implements Runnable { @Override public void run() { // Do your job here. } } </code></pre> <p>If you don't need to reference it in the view or other managed beans at all, then better just use <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContextListener.html" rel="noreferrer"><code>ServletContextListener</code></a> to keep it decoupled from JSF.</p> <pre><code>@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(); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload