0

Need help on this . Once i setup Timer.schedule the Run method got called twice. can you help please. i am using jdk1.7 and Timer and TimerTask class for this.

my code

web.xml

<listener>
    <listener-class>com.globeop.gobookmanager.startup.ScheduleReportManager</listener-class>  
</listener>




public class ScheduleReportManager implements ServletContextListener{
    private ServletContext application  = null;
    private Environment environment =null;
    private Timer scheduledReportTimer=null;
    private ConcurrentHashMap scheduledReportTimerTasks;
    ApplicationContext webContext=null;

    public ScheduleReportManager() {
    }
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        try{
            this.application= servletContextEvent.getServletContext();
            webContext = (ApplicationContext) application.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
            if(application.getAttribute("scheduledReportTimer")==null)
            {
                application.setAttribute("scheduleReportManager",this);
                this.scheduledReportTimer= new Timer(true);
                setupSchedule(scheduledReportTimer, application);
                application.setAttribute("scheduledReportTimer", scheduledReportTimer);
            }           
             Logger.global.log(Level.INFO, "ScheduledReportTimer: " + application.getServletContextName() + ": Setup completed");
        } catch (Exception e)
        {
            Logger.global.log(Level.SEVERE, "Setup Report Timer Exception - " + e.toString());
        }
    }

    public void setupSchedule(Timer scheduledReportTimer,  ServletContext application) throws Exception{
        this.environment = SpringBridgeUtil.retrieveEnvironment(application);
        this.scheduledReportTimerTasks= new ConcurrentHashMap();
        ScheduledReportTimerTask scheduledReportTimerTask = new ScheduledReportTimerTask(application,environment,this);
        scheduledReportTimerTasks.put(environment.getCode(),scheduledReportTimerTask);
          scheduledReportTimer.schedule(scheduledReportTimerTask,1000);
    }
    

    public void setTimerForNextExecution(ScheduledReportTimerTask timerTask, DateTime nextExecutionDateTime)
    {
        if(nextExecutionDateTime == null)
            return;

        Environment environment = timerTask.getEnvironment();
        ServletContext application = timerTask.getApplication();
        ScheduledReportTimerTask scheduledReportTimerTask =  new ScheduledReportTimerTask(application,environment,this);
        java.util.Date nextScheduleTime = nextExecutionDateTime.getDate();
        String environmentCode = environment.getCode();
        synchronized (scheduledReportTimerTasks){
            scheduledReportTimerTasks.put(environmentCode,scheduledReportTimerTask);
            Logger.global.log(Level.INFO, "ScheduledReportManager: next execution time is " + nextScheduleTime.toString());
            scheduledReportTimer.schedule(scheduledReportTimerTask,nextScheduleTime);
        }
    }
            
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        String contextName = application.getServletContextName();
        if (scheduledReportTimer != null) {
            scheduledReportTimer.cancel();
        }
        
        Logger.global.log(Level.INFO, "scheduledReportTimer: " + contextName
                + ": Tasks cancelled due to context removal");
    }    
}

My understanding is once scheduledReportTimer.schedule(scheduledReportTimerTask,1000); executes it call run() of class scheduledReportTimerTask . And yes it is. But i found from loggers that run method got called twice.

public class ScheduledReportTimerTask extends TimerTask{ 
    private ServletContext application;
    private Environment environment;
    private ScheduleReportManager scheduledReportManager;
    private EmailNotificationDao emailNotificationDao;
    private DataSource dataSource;

    private ClientDao clientDao;
    private EmployeeDao employeeDao = null;
       
    public ServletContext getApplication() {
        return application;
    }

    public Environment getEnvironment() {
        return environment;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    public void setApplication(ServletContext application) {
        this.application = application;
    }

    public ScheduledReportTimerTask(ServletContext application, Environment environment, ScheduleReportManager scheduledReportManager) {
        this.application = application;
        this.environment = environment;
        this.scheduledReportManager = scheduledReportManager;

        ApplicationContext webContext=(ApplicationContext) application.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        this.emailNotificationDao =  (EmailNotificationDao) webContext.getBean("emailNotificationDao");
        this.clientDao = (ClientDao)  webContext.getBean("clientDao");
        this.dataSource= (DataSource) webContext.getBean("gofundsDataSource");
        this.employeeDao = (EmployeeDao) webContext.getBean("employeeDao");
    }

    public ScheduledReportTimerTask() {
    }

    public void run()
    {
        try{
            synchronized (this){
                Logger.global.log(Level.INFO,"schedule ReportTimerTask is running   " +  new DateTime());
                List <ClientEmailNotification>scheduleReports = this.getScheduleReportList();
                if(scheduleReports!=null && scheduleReports.size()>0)
                {
                    processReports(scheduleReports);
                }
                DateTime nextExecutionTime = this.getNextExecutionTime();
                scheduledReportManager.setTimerForNextExecution(this,nextExecutionTime);
                Logger.global.log(Level.INFO, "ScheduleReportTimerTask task completed"+ new DateTime());
            }
        }catch (Exception e) {
            e.printStackTrace();
            Logger.global.log(Level.INFO,"ScheduledReportTimerTask exception " + e.toString());
            DateTime dateTime = new DateTime();
            dateTime.adjustMinute(10);
            scheduledReportManager.setTimerForNextExecution(this,dateTime);
        }
    }        
}

please help !!!


i am using java.util.logging; package for logging please see my comment

synchronized (this){
                Logger.global.log(Level.INFO,"schedule ReportTimerTask is running   " +  new DateTime()); // this print twice
                List <ClientEmailNotification>scheduleReports = this.getScheduleReportList();
                if(scheduleReports!=null && scheduleReports.size()>0)
                {
                    processReports(scheduleReports);
                }
                DateTime nextExecutionTime = this.getNextExecutionTime();
                scheduledReportManager.setTimerForNextExecution(this,nextExecutionTime);
                Logger.global.log(Level.INFO, "ScheduleReportTimerTask task completed"+ new DateTime()); // this print twice
            }

see my tomcat log

21-Jul-2014 11:00:00.001: INFO: schedule ReportTimerTask is running 21-Jul-2014 11:00:00

21-Jul-2014 11:00:00.002: INFO: schedule ReportTimerTask is running 21-Jul-2014 11:00:00

21-Jul-2014 11:00:14.332: INFO: ScheduleReportTimerTask task completed21-Jul-2014 11:00:14

21-Jul-2014 11:00:14.446: INFO: ScheduleReportTimerTask task completed21-Jul-2014 11:00:14

ok .. I found below configuration in server.xml

<Server port="8135" shutdown="SHUTDOWN">

    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

    <!-- Global JNDI resources -->
    <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
            type="org.apache.catalina.UserDatabase"
            description="User database that can be updated and saved"
            factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
            pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>

<Service name="Catalina">

        <Connector port="8139" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />

        <Engine name="Catalina" defaultHost="gofunds.globeop.com" jvmRoute="ajp_gobookmanager">

            <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>

            <Host name="gofunds.globeop.com"
                  appBase="webapps"
                  unpackWARs="true"
                  autoDeploy="true"
                  xmlValidation="false"
                  xmlNamespaceAware="false">

        <Context path="" docBase="../webapps/gobookmanager" debug="0" />


        <Context path="/manager" debug="0" privileged="true"
                         docBase="/home/gofunds/tomcat/webapps/manager">

                    <ResourceLink name="users"
                                  global="UserDatabase"
                                  type="org.apache.catalina.UserDatabase" />

                </Context>


            </Host>
        </Engine>
    </Service>
</Server>

is the configuration is correct ??

Community
  • 1
  • 1
Mangesh Kh
  • 13
  • 7
  • What logging system are you using? And, please post the relevant part of the log and your logging settings. – Seelenvirtuose Jul 22 '14 at 06:53
  • please see my new section added below . thanks for reply. – Mangesh Kh Jul 22 '14 at 07:11
  • You can add more logging to understand what's going on. Is it the timer that executes the task twice or maybe your listener gets called twice? – daramasala Jul 22 '14 at 07:16
  • @ daramasala thank you for you suggestion.. i will add logger in Listener class too. could you please tell me in which are the circumstances listener can get called twice.. – Mangesh Kh Jul 22 '14 at 07:21
  • 1
    As the code part in question is synchronized on a task instance, the intertwined duplicate logging output must come from two different task instances. If no other place creates such task instances, the method `setupSchedule` in your class `ScheduleReportManager` must be called twice. This is the direction to go. – Seelenvirtuose Jul 22 '14 at 07:36
  • @Seelenvirtuose thank you .. can you guide what are the possibility that listener class setUp() got twice. and why its calling twice only not thrice or so on .... – Mangesh Kh Jul 22 '14 at 08:06
  • No, I can't see it. You should add logging statements into that method and make it private as it seems to only be called by `contextInitialized`. – Seelenvirtuose Jul 22 '14 at 08:27
  • i found above configuration in server.xml . is it correct one ? – Mangesh Kh Jul 22 '14 at 11:00
  • issue resolved.. Server.xml had issue. – Mangesh Kh Jul 23 '14 at 08:10

0 Answers0