001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.thread;
018
019import org.slf4j.Logger;
020import org.slf4j.LoggerFactory;
021
022import java.util.TimerTask;
023
024/**
025 * A TimeTask for a Runnable object
026 *
027 */
028public class SchedulerTimerTask extends TimerTask {
029    private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerTimerTask.class);
030
031    private final Runnable task;
032
033    public SchedulerTimerTask(Runnable task) {
034        this.task = task;
035    }
036
037    public void run() {
038        try {
039            this.task.run();
040        } catch (Error error) {
041            // Very bad error. Can't swallow this but can log it.
042            LOGGER.error("Scheduled task error", error);
043            throw error;
044        } catch (Exception exception) {
045            // It is a known issue of java.util.Timer that if a TimerTask.run() method throws an exception, the
046            // Timer's thread exits as if Timer.cancel() had been called. This makes the Timer completely unusable from
047            // that point on - whenever the Timer triggers there is an 'IllegalStateException: Timer already cancelled'
048            // and the task does not get executed.
049            //
050            // In practice, this makes the ActiveMQ client unable to refresh connections to brokers. Generally, tasks
051            // are well coded to not throw exceptions but if they do, problems ensue...
052            //
053            // The answer, here, is to log the exception and then carry on without throwing further. This gives the
054            // added benefit that, having seen the exception thrown, one can then go and fix the offending task!
055            LOGGER.error("Scheduled task exception", exception);
056        }
057    }
058}