001/* 002 * Copyright 2002-2013 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scheduling.support; 018 019import java.util.concurrent.Future; 020 021import org.apache.commons.logging.Log; 022import org.apache.commons.logging.LogFactory; 023 024import org.springframework.util.ErrorHandler; 025import org.springframework.util.ReflectionUtils; 026 027/** 028 * Utility methods for decorating tasks with error handling. 029 * 030 * <p><b>NOTE:</b> This class is intended for internal use by Spring's scheduler 031 * implementations. It is only public so that it may be accessed from impl classes 032 * within other packages. It is <i>not</i> intended for general use. 033 * 034 * @author Mark Fisher 035 * @author Juergen Hoeller 036 * @since 3.0 037 */ 038public abstract class TaskUtils { 039 040 /** 041 * An ErrorHandler strategy that will log the Exception but perform 042 * no further handling. This will suppress the error so that 043 * subsequent executions of the task will not be prevented. 044 */ 045 public static final ErrorHandler LOG_AND_SUPPRESS_ERROR_HANDLER = new LoggingErrorHandler(); 046 047 /** 048 * An ErrorHandler strategy that will log at error level and then 049 * re-throw the Exception. Note: this will typically prevent subsequent 050 * execution of a scheduled task. 051 */ 052 public static final ErrorHandler LOG_AND_PROPAGATE_ERROR_HANDLER = new PropagatingErrorHandler(); 053 054 055 /** 056 * Decorate the task for error handling. If the provided {@link ErrorHandler} 057 * is not {@code null}, it will be used. Otherwise, repeating tasks will have 058 * errors suppressed by default whereas one-shot tasks will have errors 059 * propagated by default since those errors may be expected through the 060 * returned {@link Future}. In both cases, the errors will be logged. 061 */ 062 public static DelegatingErrorHandlingRunnable decorateTaskWithErrorHandler( 063 Runnable task, ErrorHandler errorHandler, boolean isRepeatingTask) { 064 065 if (task instanceof DelegatingErrorHandlingRunnable) { 066 return (DelegatingErrorHandlingRunnable) task; 067 } 068 ErrorHandler eh = (errorHandler != null ? errorHandler : getDefaultErrorHandler(isRepeatingTask)); 069 return new DelegatingErrorHandlingRunnable(task, eh); 070 } 071 072 /** 073 * Return the default {@link ErrorHandler} implementation based on the boolean 074 * value indicating whether the task will be repeating or not. For repeating tasks 075 * it will suppress errors, but for one-time tasks it will propagate. In both 076 * cases, the error will be logged. 077 */ 078 public static ErrorHandler getDefaultErrorHandler(boolean isRepeatingTask) { 079 return (isRepeatingTask ? LOG_AND_SUPPRESS_ERROR_HANDLER : LOG_AND_PROPAGATE_ERROR_HANDLER); 080 } 081 082 083 /** 084 * An {@link ErrorHandler} implementation that logs the Throwable at error 085 * level. It does not perform any additional error handling. This can be 086 * useful when suppression of errors is the intended behavior. 087 */ 088 private static class LoggingErrorHandler implements ErrorHandler { 089 090 private final Log logger = LogFactory.getLog(LoggingErrorHandler.class); 091 092 @Override 093 public void handleError(Throwable t) { 094 if (logger.isErrorEnabled()) { 095 logger.error("Unexpected error occurred in scheduled task.", t); 096 } 097 } 098 } 099 100 101 /** 102 * An {@link ErrorHandler} implementation that logs the Throwable at error 103 * level and then propagates it. 104 */ 105 private static class PropagatingErrorHandler extends LoggingErrorHandler { 106 107 @Override 108 public void handleError(Throwable t) { 109 super.handleError(t); 110 ReflectionUtils.rethrowRuntimeException(t); 111 } 112 } 113 114}