@Nullable all the way: null-safety at field level

This commits extends nullability declarations to the field level, formalizing the interaction between methods and their underlying fields and therefore avoiding any nullability mismatch.

Issue: SPR-15720
This commit is contained in:
Juergen Hoeller
2017-06-30 01:53:45 +02:00
parent c4694c3f5c
commit cc74a2891a
936 changed files with 6090 additions and 2806 deletions

View File

@@ -129,6 +129,7 @@ public class CaffeineCache extends AbstractValueAdaptingCache {
private class PutIfAbsentFunction implements Function<Object, Object> {
@Nullable
private final Object value;
private boolean called;

View File

@@ -61,6 +61,7 @@ public class CaffeineCacheManager implements CacheManager {
private Caffeine<Object, Object> cacheBuilder = Caffeine.newBuilder();
@Nullable
private CacheLoader<Object, Object> cacheLoader;
private boolean allowNullValues = true;

View File

@@ -36,6 +36,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that creates a named EhCache {@link net.sf.ehcache.Cache} instance
@@ -63,20 +64,26 @@ public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBea
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private CacheManager cacheManager;
private boolean blocking = false;
@Nullable
private CacheEntryFactory cacheEntryFactory;
@Nullable
private BootstrapCacheLoader bootstrapCacheLoader;
@Nullable
private Set<CacheEventListener> cacheEventListeners;
private boolean disabled = false;
@Nullable
private String beanName;
@Nullable
private Ehcache cache;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that exposes an EhCache {@link net.sf.ehcache.CacheManager}
@@ -55,14 +56,17 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Resource configLocation;
@Nullable
private String cacheManagerName;
private boolean acceptExisting = false;
private boolean shared = false;
@Nullable
private CacheManager cacheManager;
private boolean locallyManaged = true;
@@ -182,7 +186,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
@Override
public void destroy() {
if (this.locallyManaged) {
if (this.cacheManager != null && this.locallyManaged) {
if (logger.isInfoEnabled()) {
logger.info("Shutting down EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,12 +42,16 @@ import org.springframework.lang.Nullable;
public class JCacheManagerFactoryBean
implements FactoryBean<CacheManager>, BeanClassLoaderAware, InitializingBean, DisposableBean {
@Nullable
private URI cacheManagerUri;
@Nullable
private Properties cacheManagerProperties;
@Nullable
private ClassLoader beanClassLoader;
@Nullable
private CacheManager cacheManager;
@@ -98,7 +102,9 @@ public class JCacheManagerFactoryBean
@Override
public void destroy() {
this.cacheManager.close();
if (this.cacheManager != null) {
this.cacheManager.close();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,7 +45,9 @@ public class ProxyJCacheConfiguration extends AbstractJCacheConfiguration {
new BeanFactoryJCacheOperationSourceAdvisor();
advisor.setCacheOperationSource(cacheOperationSource());
advisor.setAdvice(cacheInterceptor());
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
if (this.enableCaching != null) {
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
}
return advisor;
}

View File

@@ -21,6 +21,7 @@ import java.util.Collection;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -38,6 +39,7 @@ import org.springframework.util.Assert;
*/
public class TransactionAwareCacheManagerProxy implements CacheManager, InitializingBean {
@Nullable
private CacheManager targetCacheManager;
@@ -75,12 +77,14 @@ public class TransactionAwareCacheManagerProxy implements CacheManager, Initiali
@Override
public Cache getCache(String name) {
Assert.state(this.targetCacheManager != null, "No target CacheManager set");
Cache targetCache = this.targetCacheManager.getCache(name);
return (targetCache != null ? new TransactionAwareCacheDecorator(targetCache) : null);
}
@Override
public Collection<String> getCacheNames() {
Assert.state(this.targetCacheManager != null, "No target CacheManager set");
return this.targetCacheManager.getCacheNames();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ public class MailSendException extends MailException {
private transient final Map<Object, Exception> failedMessages;
@Nullable
private Exception[] messageExceptions;

View File

@@ -43,20 +43,28 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("serial")
public class SimpleMailMessage implements MailMessage, Serializable {
@Nullable
private String from;
@Nullable
private String replyTo;
@Nullable
private String[] to;
@Nullable
private String[] cc;
@Nullable
private String[] bcc;
@Nullable
private Date sentDate;
@Nullable
private String subject;
@Nullable
private String text;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,12 +69,14 @@ public class ConfigurableMimeFileTypeMap extends FileTypeMap implements Initiali
/**
* Used to configure additional mappings.
*/
@Nullable
private String[] mappings;
/**
* The delegate FileTypeMap, compiled from the mappings in the mapping file
* and the entries in the {@code mappings} property.
*/
@Nullable
private FileTypeMap fileTypeMap;

View File

@@ -79,18 +79,24 @@ public class JavaMailSenderImpl implements JavaMailSender {
private Properties javaMailProperties = new Properties();
@Nullable
private Session session;
@Nullable
private String protocol;
@Nullable
private String host;
private int port = DEFAULT_PORT;
@Nullable
private String username;
@Nullable
private String password;
@Nullable
private String defaultEncoding;
private FileTypeMap defaultFileTypeMap;

View File

@@ -163,10 +163,13 @@ public class MimeMessageHelper {
private final MimeMessage mimeMessage;
@Nullable
private MimeMultipart rootMimeMultipart;
@Nullable
private MimeMultipart mimeMultipart;
@Nullable
private final String encoding;
private FileTypeMap fileTypeMap;
@@ -376,17 +379,6 @@ public class MimeMessageHelper {
return (this.rootMimeMultipart != null);
}
/**
* Throw an IllegalStateException if this helper is not in multipart mode.
*/
private void checkMultipart() throws IllegalStateException {
if (!isMultipart()) {
throw new IllegalStateException("Not in multipart mode - " +
"create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag " +
"if you need to set alternative texts or add inline elements or attachments.");
}
}
/**
* Return the root MIME "multipart/mixed" object, if any.
* Can be used to manually add attachments.
@@ -398,7 +390,11 @@ public class MimeMessageHelper {
* @see javax.mail.internet.MimeMultipart#addBodyPart
*/
public final MimeMultipart getRootMimeMultipart() throws IllegalStateException {
checkMultipart();
if (this.rootMimeMultipart == null) {
throw new IllegalStateException("Not in multipart mode - " +
"create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag " +
"if you need to set alternative texts or add inline elements or attachments.");
}
return this.rootMimeMultipart;
}
@@ -413,7 +409,11 @@ public class MimeMessageHelper {
* @see javax.mail.internet.MimeMultipart#addBodyPart
*/
public final MimeMultipart getMimeMultipart() throws IllegalStateException {
checkMultipart();
if (this.mimeMultipart == null) {
throw new IllegalStateException("Not in multipart mode - " +
"create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag " +
"if you need to set alternative texts or add inline elements or attachments.");
}
return this.mimeMultipart;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,8 +39,10 @@ import org.springframework.lang.Nullable;
*/
class SmartMimeMessage extends MimeMessage {
@Nullable
private final String defaultEncoding;
@Nullable
private final FileTypeMap defaultFileTypeMap;
@@ -50,7 +52,9 @@ class SmartMimeMessage extends MimeMessage {
* @param defaultEncoding the default encoding, or {@code null} if none
* @param defaultFileTypeMap the default FileTypeMap, or {@code null} if none
*/
public SmartMimeMessage(Session session, @Nullable String defaultEncoding, @Nullable FileTypeMap defaultFileTypeMap) {
public SmartMimeMessage(
Session session, @Nullable String defaultEncoding, @Nullable FileTypeMap defaultFileTypeMap) {
super(session);
this.defaultEncoding = defaultEncoding;
this.defaultFileTypeMap = defaultFileTypeMap;

View File

@@ -38,8 +38,10 @@ import org.springframework.util.Assert;
public abstract class TimerManagerAccessor extends JndiLocatorSupport
implements InitializingBean, DisposableBean, Lifecycle {
@Nullable
private TimerManager timerManager;
@Nullable
private String timerManagerName;
private boolean shared = false;
@@ -139,7 +141,7 @@ public abstract class TimerManagerAccessor extends JndiLocatorSupport
@Override
public void start() {
if (!this.shared) {
this.timerManager.resume();
obtainTimerManager().resume();
}
}
@@ -150,7 +152,7 @@ public abstract class TimerManagerAccessor extends JndiLocatorSupport
@Override
public void stop() {
if (!this.shared) {
this.timerManager.suspend();
obtainTimerManager().suspend();
}
}
@@ -162,7 +164,8 @@ public abstract class TimerManagerAccessor extends JndiLocatorSupport
*/
@Override
public boolean isRunning() {
return (!this.timerManager.isSuspending() && !this.timerManager.isStopping());
TimerManager tm = obtainTimerManager();
return (!tm.isSuspending() && !tm.isStopping());
}
@@ -177,7 +180,7 @@ public abstract class TimerManagerAccessor extends JndiLocatorSupport
@Override
public void destroy() {
// Stop the entire TimerManager, if necessary.
if (!this.shared) {
if (this.timerManager != null && !this.shared) {
// May return early, but at least we already cancelled all known Timers.
this.timerManager.stop();
}

View File

@@ -27,6 +27,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.lang.Nullable;
/**
* {@link org.springframework.beans.factory.FactoryBean} that retrieves a
@@ -54,6 +55,7 @@ import org.springframework.context.Lifecycle;
public class TimerManagerFactoryBean extends TimerManagerAccessor
implements FactoryBean<TimerManager>, InitializingBean, DisposableBean, Lifecycle {
@Nullable
private ScheduledTimerListener[] scheduledTimerListeners;
private final List<Timer> timers = new LinkedList<>();
@@ -79,6 +81,7 @@ public class TimerManagerFactoryBean extends TimerManagerAccessor
@Override
public void afterPropertiesSet() throws NamingException {
super.afterPropertiesSet();
if (this.scheduledTimerListeners != null) {
TimerManager timerManager = obtainTimerManager();
for (ScheduledTimerListener scheduledTask : this.scheduledTimerListeners) {

View File

@@ -30,6 +30,7 @@ import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
@@ -42,6 +43,7 @@ import org.springframework.util.ErrorHandler;
*/
public class TimerManagerTaskScheduler extends TimerManagerAccessor implements TaskScheduler {
@Nullable
private volatile ErrorHandler errorHandler;
@@ -108,6 +110,7 @@ public class TimerManagerTaskScheduler extends TimerManagerAccessor implements T
*/
private static class TimerScheduledFuture extends FutureTask<Object> implements TimerListener, ScheduledFuture<Object> {
@Nullable
protected transient Timer timer;
protected transient boolean cancelled = false;
@@ -128,13 +131,16 @@ public class TimerManagerTaskScheduler extends TimerManagerAccessor implements T
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean result = super.cancel(mayInterruptIfRunning);
this.timer.cancel();
if (this.timer != null) {
this.timer.cancel();
}
this.cancelled = true;
return result;
}
@Override
public long getDelay(TimeUnit unit) {
Assert.state(this.timer != null, "No Timer available");
return unit.convert(this.timer.getScheduledExecutionTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@@ -158,7 +164,7 @@ public class TimerManagerTaskScheduler extends TimerManagerAccessor implements T
private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();
private volatile Date scheduledExecutionTime;
private volatile Date scheduledExecutionTime = new Date();
public ReschedulingTimerListener(Runnable runnable, Trigger trigger) {
super(runnable);
@@ -167,10 +173,11 @@ public class TimerManagerTaskScheduler extends TimerManagerAccessor implements T
@Nullable
public ScheduledFuture<?> schedule() {
this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (this.scheduledExecutionTime == null) {
Date nextExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (nextExecutionTime == null) {
return null;
}
this.scheduledExecutionTime = nextExecutionTime;
setTimer(obtainTimerManager().schedule(this, this.scheduledExecutionTime));
return this;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.Assert;
@@ -66,12 +67,16 @@ import org.springframework.util.concurrent.ListenableFutureTask;
public class WorkManagerTaskExecutor extends JndiLocatorSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, InitializingBean {
@Nullable
private WorkManager workManager;
@Nullable
private String workManagerName;
@Nullable
private WorkListener workListener;
@Nullable
private TaskDecorator taskDecorator;
@@ -128,6 +133,11 @@ public class WorkManagerTaskExecutor extends JndiLocatorSupport
}
}
private WorkManager obtainWorkManager() {
Assert.state(this.workManager != null, "No WorkManager specified");
return this.workManager;
}
//-------------------------------------------------------------------------
// Implementation of the Spring SchedulingTaskExecutor interface
@@ -135,14 +145,13 @@ public class WorkManagerTaskExecutor extends JndiLocatorSupport
@Override
public void execute(Runnable task) {
Assert.state(this.workManager != null, "No WorkManager specified");
Work work = new DelegatingWork(this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
try {
if (this.workListener != null) {
this.workManager.schedule(work, this.workListener);
obtainWorkManager().schedule(work, this.workListener);
}
else {
this.workManager.schedule(work);
obtainWorkManager().schedule(work);
}
}
catch (WorkRejectedException ex) {
@@ -201,24 +210,24 @@ public class WorkManagerTaskExecutor extends JndiLocatorSupport
@Override
public WorkItem schedule(Work work) throws WorkException, IllegalArgumentException {
return this.workManager.schedule(work);
return obtainWorkManager().schedule(work);
}
@Override
public WorkItem schedule(Work work, WorkListener workListener) throws WorkException {
return this.workManager.schedule(work, workListener);
return obtainWorkManager().schedule(work, workListener);
}
@Override
@SuppressWarnings("rawtypes")
public boolean waitForAll(Collection workItems, long timeout) throws InterruptedException {
return this.workManager.waitForAll(workItems, timeout);
return obtainWorkManager().waitForAll(workItems, timeout);
}
@Override
@SuppressWarnings("rawtypes")
public Collection waitForAny(Collection workItems, long timeout) throws InterruptedException {
return this.workManager.waitForAny(workItems, timeout);
return obtainWorkManager().waitForAny(workItems, timeout);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -61,32 +62,42 @@ public class CronTriggerFactoryBean implements FactoryBean<CronTrigger>, BeanNam
private static final Constants constants = new Constants(CronTrigger.class);
@Nullable
private String name;
@Nullable
private String group;
@Nullable
private JobDetail jobDetail;
private JobDataMap jobDataMap = new JobDataMap();
@Nullable
private Date startTime;
private long startDelay = 0;
@Nullable
private String cronExpression;
@Nullable
private TimeZone timeZone;
@Nullable
private String calendarName;
private int priority;
private int misfireInstruction;
@Nullable
private String description;
@Nullable
private String beanName;
@Nullable
private CronTrigger cronTrigger;
@@ -218,6 +229,8 @@ public class CronTriggerFactoryBean implements FactoryBean<CronTrigger>, BeanNam
@Override
public void afterPropertiesSet() throws ParseException {
Assert.notNull(this.cronExpression, "Property 'cronExpression' is required");
if (this.name == null) {
this.name = this.beanName;
}
@@ -235,7 +248,7 @@ public class CronTriggerFactoryBean implements FactoryBean<CronTrigger>, BeanNam
}
CronTriggerImpl cti = new CronTriggerImpl();
cti.setName(this.name);
cti.setName(this.name != null ? this.name : toString());
cti.setGroup(this.group);
if (this.jobDetail != null) {
cti.setJobKey(this.jobDetail.getKey());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.scheduling.quartz;
import java.util.Map;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
@@ -28,6 +29,8 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* A Spring {@link FactoryBean} for creating a Quartz {@link org.quartz.JobDetail}
@@ -47,11 +50,14 @@ import org.springframework.context.ApplicationContextAware;
public class JobDetailFactoryBean
implements FactoryBean<JobDetail>, BeanNameAware, ApplicationContextAware, InitializingBean {
@Nullable
private String name;
@Nullable
private String group;
private Class<?> jobClass;
@Nullable
private Class<? extends Job> jobClass;
private JobDataMap jobDataMap = new JobDataMap();
@@ -59,14 +65,19 @@ public class JobDetailFactoryBean
private boolean requestsRecovery = false;
@Nullable
private String description;
@Nullable
private String beanName;
@Nullable
private ApplicationContext applicationContext;
@Nullable
private String applicationContextJobDataKey;
@Nullable
private JobDetail jobDetail;
@@ -87,7 +98,7 @@ public class JobDetailFactoryBean
/**
* Specify the job's implementation class.
*/
public void setJobClass(Class<?> jobClass) {
public void setJobClass(Class<? extends Job> jobClass) {
this.jobClass = jobClass;
}
@@ -176,8 +187,9 @@ public class JobDetailFactoryBean
@Override
@SuppressWarnings("unchecked")
public void afterPropertiesSet() {
Assert.notNull(this.jobClass, "Property 'jobClass' is required");
if (this.name == null) {
this.name = this.beanName;
}
@@ -194,9 +206,9 @@ public class JobDetailFactoryBean
}
JobDetailImpl jdi = new JobDetailImpl();
jdi.setName(this.name);
jdi.setName(this.name != null ? this.name : toString());
jdi.setGroup(this.group);
jdi.setJobClass((Class) this.jobClass);
jdi.setJobClass(this.jobClass);
jdi.setJobDataMap(this.jobDataMap);
jdi.setDurability(this.durability);
jdi.setRequestsRecovery(this.requestsRecovery);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.quartz.utils.DBConnectionManager;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;
import org.springframework.lang.Nullable;
/**
* Subclass of Quartz's JobStoreCMT class that delegates to a Spring-managed
@@ -78,6 +79,7 @@ public class LocalDataSourceJobStore extends JobStoreCMT {
public static final String NON_TX_DATA_SOURCE_PREFIX = "springNonTxDataSource.";
@Nullable
private DataSource dataSource;

View File

@@ -24,6 +24,9 @@ import org.apache.commons.logging.LogFactory;
import org.quartz.SchedulerConfigException;
import org.quartz.spi.ThreadPool;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Quartz ThreadPool adapter that delegates to a Spring-managed
* TaskExecutor instance, specified on SchedulerFactoryBean.
@@ -37,6 +40,7 @@ public class LocalTaskExecutorThreadPool implements ThreadPool {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Executor taskExecutor;
@@ -72,6 +76,7 @@ public class LocalTaskExecutorThreadPool implements ThreadPool {
@Override
public boolean runInThread(Runnable runnable) {
Assert.state(this.taskExecutor != null, "No TaskExecutor available");
try {
this.taskExecutor.execute(runnable);
return true;

View File

@@ -35,6 +35,7 @@ import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MethodInvoker;
@@ -76,20 +77,26 @@ import org.springframework.util.MethodInvoker;
public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethodInvoker
implements FactoryBean<JobDetail>, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
@Nullable
private String name;
private String group = Scheduler.DEFAULT_GROUP;
private boolean concurrent = true;
@Nullable
private String targetBeanName;
@Nullable
private String beanName;
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@Nullable
private BeanFactory beanFactory;
@Nullable
private JobDetail jobDetail;
@@ -169,7 +176,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
// Build JobDetail instance.
JobDetailImpl jdi = new JobDetailImpl();
jdi.setName(name);
jdi.setName(name != null ? name : toString());
jdi.setGroup(this.group);
jdi.setJobClass((Class) jobClass);
jdi.setDurability(true);
@@ -239,6 +246,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
protected static final Log logger = LogFactory.getLog(MethodInvokingJob.class);
@Nullable
private MethodInvoker methodInvoker;
/**
@@ -253,6 +261,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
*/
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
Assert.state(this.methodInvoker != null, "No MethodInvoker set");
try {
context.setResult(this.methodInvoker.invoke());
}

View File

@@ -44,6 +44,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
protected static final Log logger = LogFactory.getLog(ResourceLoaderClassLoadHelper.class);
@Nullable
private ResourceLoader resourceLoader;
@@ -59,7 +60,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
* Create a new ResourceLoaderClassLoadHelper for the given ResourceLoader.
* @param resourceLoader the ResourceLoader to delegate to
*/
public ResourceLoaderClassLoadHelper(ResourceLoader resourceLoader) {
public ResourceLoaderClassLoadHelper(@Nullable ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@@ -76,6 +77,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Assert.state(this.resourceLoader != null, "ResourceLoaderClassLoadHelper not initialized");
return ClassUtils.forName(name, this.resourceLoader.getClassLoader());
}
@@ -87,6 +89,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
@Override
@Nullable
public URL getResource(String name) {
Assert.state(this.resourceLoader != null, "ResourceLoaderClassLoadHelper not initialized");
Resource resource = this.resourceLoader.getResource(name);
if (resource.exists()) {
try {
@@ -107,6 +110,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
@Override
@Nullable
public InputStream getResourceAsStream(String name) {
Assert.state(this.resourceLoader != null, "ResourceLoaderClassLoadHelper not initialized");
Resource resource = this.resourceLoader.getResource(name);
if (resource.exists()) {
try {
@@ -126,6 +130,7 @@ public class ResourceLoaderClassLoadHelper implements ClassLoadHelper {
@Override
public ClassLoader getClassLoader() {
Assert.state(this.resourceLoader != null, "ResourceLoaderClassLoadHelper not initialized");
ClassLoader classLoader = this.resourceLoader.getClassLoader();
Assert.state(classLoader != null, "No ClassLoader");
return classLoader;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,22 +64,31 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
private boolean overwriteExistingJobs = false;
@Nullable
private String[] jobSchedulingDataLocations;
@Nullable
private List<JobDetail> jobDetails;
@Nullable
private Map<String, Calendar> calendars;
@Nullable
private List<Trigger> triggers;
@Nullable
private SchedulerListener[] schedulerListeners;
@Nullable
private JobListener[] globalJobListeners;
@Nullable
private TriggerListener[] globalTriggerListeners;
@Nullable
private PlatformTransactionManager transactionManager;
@Nullable
protected ResourceLoader resourceLoader;
@@ -187,7 +196,7 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
}
@Override
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@@ -297,14 +306,15 @@ public abstract class SchedulerAccessor implements ResourceLoaderAware {
// Check if the Trigger is aware of an associated JobDetail.
JobDetail jobDetail = (JobDetail) trigger.getJobDataMap().remove("jobDetail");
if (triggerExists) {
if (jobDetail != null && !this.jobDetails.contains(jobDetail) && addJobToScheduler(jobDetail)) {
if (jobDetail != null && this.jobDetails != null &&
!this.jobDetails.contains(jobDetail) && addJobToScheduler(jobDetail)) {
this.jobDetails.add(jobDetail);
}
getScheduler().rescheduleJob(trigger.getKey(), trigger);
}
else {
try {
if (jobDetail != null && !this.jobDetails.contains(jobDetail) &&
if (jobDetail != null && this.jobDetails != null && !this.jobDetails.contains(jobDetail) &&
(this.overwriteExistingJobs || getScheduler().getJobDetail(jobDetail.getKey()) == null)) {
getScheduler().scheduleJob(jobDetail, trigger);
this.jobDetails.add(jobDetail);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Spring bean-style class for accessing a Quartz Scheduler, i.e. for registering jobs,
@@ -38,10 +40,13 @@ import org.springframework.beans.factory.ListableBeanFactory;
*/
public class SchedulerAccessorBean extends SchedulerAccessor implements BeanFactoryAware, InitializingBean {
@Nullable
private String schedulerName;
@Nullable
private Scheduler scheduler;
@Nullable
private BeanFactory beanFactory;
@@ -74,6 +79,7 @@ public class SchedulerAccessorBean extends SchedulerAccessor implements BeanFact
*/
@Override
public Scheduler getScheduler() {
Assert.state(this.scheduler != null, "No Scheduler set");
return this.scheduler;
}

View File

@@ -44,6 +44,7 @@ import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingException;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
@@ -165,26 +166,36 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
private Class<? extends SchedulerFactory> schedulerFactoryClass = StdSchedulerFactory.class;
@Nullable
private String schedulerName;
@Nullable
private Resource configLocation;
@Nullable
private Properties quartzProperties;
@Nullable
private Executor taskExecutor;
@Nullable
private DataSource dataSource;
@Nullable
private DataSource nonTransactionalDataSource;
@Nullable
private Map<String, ?> schedulerContextMap;
@Nullable
private ApplicationContext applicationContext;
@Nullable
private String applicationContextSchedulerContextKey;
@Nullable
private JobFactory jobFactory;
private boolean jobFactorySet = false;
@@ -201,6 +212,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
private boolean waitForJobsToCompleteOnShutdown = false;
@Nullable
private Scheduler scheduler;
@@ -625,7 +637,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
private void populateSchedulerContext() throws SchedulerException {
// Put specified objects into Scheduler context.
if (this.schedulerContextMap != null) {
this.scheduler.getContext().putAll(this.schedulerContextMap);
getScheduler().getContext().putAll(this.schedulerContextMap);
}
// Register ApplicationContext in Scheduler context.
@@ -635,7 +647,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
"SchedulerFactoryBean needs to be set up in an ApplicationContext " +
"to be able to handle an 'applicationContextSchedulerContextKey'");
}
this.scheduler.getContext().put(this.applicationContextSchedulerContextKey, this.applicationContext);
getScheduler().getContext().put(this.applicationContextSchedulerContextKey, this.applicationContext);
}
}
@@ -691,6 +703,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
@Override
public Scheduler getScheduler() {
Assert.state(this.scheduler != null, "No Scheduler set");
return this.scheduler;
}
@@ -768,8 +781,10 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
*/
@Override
public void destroy() throws SchedulerException {
logger.info("Shutting down Quartz Scheduler");
this.scheduler.shutdown(this.waitForJobsToCompleteOnShutdown);
if (this.scheduler != null) {
logger.info("Shutting down Quartz Scheduler");
this.scheduler.shutdown(this.waitForJobsToCompleteOnShutdown);
}
}
}

View File

@@ -29,6 +29,7 @@ import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -59,14 +60,18 @@ public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, Bea
private static final Constants constants = new Constants(SimpleTrigger.class);
@Nullable
private String name;
@Nullable
private String group;
@Nullable
private JobDetail jobDetail;
private JobDataMap jobDataMap = new JobDataMap();
@Nullable
private Date startTime;
private long startDelay;
@@ -79,10 +84,13 @@ public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, Bea
private int misfireInstruction;
@Nullable
private String description;
@Nullable
private String beanName;
@Nullable
private SimpleTrigger simpleTrigger;
@@ -226,7 +234,7 @@ public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, Bea
}
SimpleTriggerImpl sti = new SimpleTriggerImpl();
sti.setName(this.name);
sti.setName(this.name != null ? this.name : toString());
sti.setGroup(this.group);
if (this.jobDetail != null) {
sti.setJobKey(this.jobDetail.getKey());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,8 +43,10 @@ import org.springframework.lang.Nullable;
*/
public class SpringBeanJobFactory extends AdaptableJobFactory implements SchedulerContextAware {
@Nullable
private String[] ignoredUnknownProperties;
@Nullable
private SchedulerContext schedulerContext;
@@ -56,7 +58,7 @@ public class SpringBeanJobFactory extends AdaptableJobFactory implements Schedul
* ignored if there is no corresponding property found on the particular
* job class (all other unknown properties will still trigger an exception).
*/
public void setIgnoredUnknownProperties(@Nullable String... ignoredUnknownProperties) {
public void setIgnoredUnknownProperties(String... ignoredUnknownProperties) {
this.ignoredUnknownProperties = ignoredUnknownProperties;
}

View File

@@ -78,20 +78,27 @@ public class FreeMarkerConfigurationFactory {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Resource configLocation;
@Nullable
private Properties freemarkerSettings;
@Nullable
private Map<String, Object> freemarkerVariables;
@Nullable
private String defaultEncoding;
private final List<TemplateLoader> templateLoaders = new ArrayList<>();
@Nullable
private List<TemplateLoader> preTemplateLoaders;
@Nullable
private List<TemplateLoader> postTemplateLoaders;
@Nullable
private String[] templateLoaderPaths;
private ResourceLoader resourceLoader = new DefaultResourceLoader();