Periodic repetitive background task using Timer task and SwingWorker in Swing

Periodic repetitive background task using Timer task and SwingWorker in Swing

Many of you would be aware of Timer task which is part of core java library. It’s used to execute a piece of task after a certain delay periodically on the current thread. This API is very popular and is used in quartz API. But let’s focus our mind in the context of Swing application. There have been times where we have to perform background tasks, so what if your boss says to execute some tasks periodically in background. Recently I encountered this situation where my Swing application had 3 mail settings of the corresponding mail servers and it had to connect to each mail server after a certain delay and read mails, all this as part of background task.

So, what would be the design? Yes you got it right, all we want is the combination of “Timer” task and “SwingWorker”. From the Event Dispatcher thread for each Timer task start a separate background task. Note that instead of Timer API of core JAVA library we have to use Timer API of Swing library. Also don’t forget to sleep background threads for some time so that other threads can get chance. Below is the code:-

import javax.swing.SwingWorker;
import javax.swing.Timer;

public class App
{
     private Timer timer1, timer2, timer3;
     private MailDao mailDao=new MailDao();

if(mailDao.isMailSettingsTableExists()){
				final List<MailSettings> allMailSettings=mailDao.getMailsSettings();
				if(allMailSettings!=null && !allMailSettings.isEmpty()){
					if(allMailSettings.size()>=1 && allMailSettings.get(0)!=null && allMailSettings.get(0).getMailSyncAutoTime()!=0){
						timer1 = new Timer(allMailSettings.get(0).getMailSyncAutoTime()*60*1000 ,new ActionListener() {
							@Override
							public void actionPerformed(ActionEvent e) {
								logger.info("Timer1---actionPerformed--"+allMailSettings.get(0).getEmailAddress());
								MailSyncBackgroundTask1 mailSyncBackgroundTask1=new MailSyncBackgroundTask1(allMailSettings.get(0));
								mailSyncBackgroundTask1.execute();
							}
						});
						timer1.start();
					}
					if(allMailSettings.size()>=2 && allMailSettings.get(1)!=null && allMailSettings.get(1).getMailSyncAutoTime()!=0){
						timer2 = new Timer(allMailSettings.get(1).getMailSyncAutoTime()*60*1000 ,new ActionListener() {
							@Override
							public void actionPerformed(ActionEvent e) {
								logger.info("Timer2---actionPerformed--"+allMailSettings.get(1).getEmailAddress());
								MailSyncBackgroundTask2 mailSyncBackgroundTask2=new MailSyncBackgroundTask2(allMailSettings.get(1));
								mailSyncBackgroundTask2.execute();
							}
						});
						timer2.start();
					}
					if(allMailSettings.size()==3 && allMailSettings.get(2)!=null && allMailSettings.get(2).getMailSyncAutoTime()!=0){
						timer3 = new Timer(allMailSettings.get(2).getMailSyncAutoTime()*60*1000 ,new ActionListener() {
							@Override
							public void actionPerformed(ActionEvent e) {
								logger.info("Timer3---actionPerformed--"+allMailSettings.get(2).getEmailAddress());
								MailSyncBackgroundTask3 mailSyncBackgroundTask3=new MailSyncBackgroundTask3(allMailSettings.get(2));
								mailSyncBackgroundTask3.execute();
							}
						});
						timer3.start();
					}
				}
			}
private class MailSyncBackgroundTask1 extends SwingWorker<Void, Void> {
    	private MailSettings mailSettings;
    	private MailUtility mailUtility;
    	public MailSyncBackgroundTask1(MailSettings mailSettings) {
			this.mailSettings=mailSettings;
		}
    	
		@Override
		protected Void doInBackground() throws Exception {
			logger.info("Timer1---MailSyncBackgroundTask1--start Mail Reading--"+mailSettings.getEmailAddress());
			mailUtility=new MailUtility();
  	  		mailUtility.connectToMailBox(mailSettings);
  	  		logger.info("Timer1---MailSyncBackgroundTask1--Mail Reading done--"+mailSettings.getEmailAddress());
  	  		Thread.sleep(1000);
			return null;
		}
    }
    
    private class MailSyncBackgroundTask2 extends SwingWorker<Void, Void> {
    	private MailSettings mailSettings;
    	private MailUtility mailUtility;
    	public MailSyncBackgroundTask2(MailSettings mailSettings) {
			this.mailSettings=mailSettings;
		}
    	
		@Override
		protected Void doInBackground() throws Exception {
			logger.info("Timer2---MailSyncBackgroundTask2--start Mail Reading--"+mailSettings.getEmailAddress());
			mailUtility=new MailUtility();
  	  		mailUtility.connectToMailBox(mailSettings);
  	  		logger.info("Timer2---MailSyncBackgroundTask2--Mail Reading done--"+mailSettings.getEmailAddress());
  	  		Thread.sleep(1000);
			return null;
		}
    }
    
    private class MailSyncBackgroundTask3 extends SwingWorker<Void, Void> {
    	private MailSettings mailSettings;
    	private MailUtility mailUtility;
    	public MailSyncBackgroundTask3(MailSettings mailSettings) {
			this.mailSettings=mailSettings;
		}
    	
		@Override
		protected Void doInBackground() throws Exception {
			logger.info("Timer3---MailSyncBackgroundTask3--start Mail Reading--"+mailSettings.getEmailAddress());
			mailUtility=new MailUtility();
  	  		mailUtility.connectToMailBox(mailSettings);
  	  		logger.info("Timer3---MailSyncBackgroundTask3--Mail Reading done--"+mailSettings.getEmailAddress());
  	  		Thread.sleep(1000);
			return null;
		}
    }
}

Although this design will work and it won’t be freezing the UI, however better approach would be to start the background thread and then on it start the Timer task. So this way your periodic task as part of Timer task will be called on the same background thread, so need of creating new background threads for each iteration of Timer task. This way we won’t we utilizing much of the resources. I haven’t tried this approach but surely it would be good.