From 5764db24a05f6f1e44aee599c353a0451dbdf5af Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 4 Aug 2025 14:05:36 +0200 Subject: [PATCH] Add nullability annotations to module/spring-boot-quartz See gh-46587 --- .../QuartzAutoConfiguration.java | 3 +- ...tzDataSourceScriptDatabaseInitializer.java | 6 ++-- .../autoconfigure/QuartzJdbcProperties.java | 8 ++++-- .../autoconfigure/QuartzProperties.java | 8 ++++-- .../autoconfigure/endpoint/package-info.java | 3 ++ .../quartz/autoconfigure/package-info.java | 3 ++ .../boot/quartz/endpoint/QuartzEndpoint.java | 28 +++++++++++-------- .../endpoint/QuartzEndpointWebExtension.java | 7 +++-- .../boot/quartz/endpoint/package-info.java | 3 ++ 9 files changed, 46 insertions(+), 23 deletions(-) diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzAutoConfiguration.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzAutoConfiguration.java index f5b687320eb..9c1d5268325 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzAutoConfiguration.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzAutoConfiguration.java @@ -21,6 +21,7 @@ import java.util.Properties; import javax.sql.DataSource; +import org.jspecify.annotations.Nullable; import org.quartz.Calendar; import org.quartz.JobDetail; import org.quartz.Scheduler; @@ -120,7 +121,7 @@ public final class QuartzAutoConfiguration { return (dataSourceIfAvailable != null) ? dataSourceIfAvailable : dataSource; } - private PlatformTransactionManager getTransactionManager( + private @Nullable PlatformTransactionManager getTransactionManager( ObjectProvider transactionManager, ObjectProvider quartzTransactionManager) { PlatformTransactionManager transactionManagerIfAvailable = quartzTransactionManager.getIfAvailable(); diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzDataSourceScriptDatabaseInitializer.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzDataSourceScriptDatabaseInitializer.java index 5dc48207877..1e4ee8d0637 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzDataSourceScriptDatabaseInitializer.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzDataSourceScriptDatabaseInitializer.java @@ -20,6 +20,8 @@ import java.util.List; import javax.sql.DataSource; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver; @@ -39,7 +41,7 @@ import org.springframework.util.StringUtils; */ public class QuartzDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer { - private final List commentPrefixes; + private final @Nullable List commentPrefixes; /** * Create a new {@link QuartzDataSourceScriptDatabaseInitializer} instance. @@ -62,7 +64,7 @@ public class QuartzDataSourceScriptDatabaseInitializer extends DataSourceScriptD } private QuartzDataSourceScriptDatabaseInitializer(DataSource dataSource, DatabaseInitializationSettings settings, - List commentPrefixes) { + @Nullable List commentPrefixes) { super(dataSource, settings); this.commentPrefixes = commentPrefixes; } diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzJdbcProperties.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzJdbcProperties.java index 4adf537d44b..dce929eae16 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzJdbcProperties.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzJdbcProperties.java @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.sql.init.DatabaseInitializationMode; @@ -46,7 +48,7 @@ public class QuartzJdbcProperties { * Platform to use in initialization scripts if the @@platform@@ placeholder is used. * Auto-detected by default. */ - private String platform; + private @Nullable String platform; /** * Database schema initialization mode. @@ -66,11 +68,11 @@ public class QuartzJdbcProperties { this.schema = schema; } - public String getPlatform() { + public @Nullable String getPlatform() { return this.platform; } - public void setPlatform(String platform) { + public void setPlatform(@Nullable String platform) { this.platform = platform; } diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzProperties.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzProperties.java index 707f0bd6e1a..6e8f6e1d887 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzProperties.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/QuartzProperties.java @@ -20,6 +20,8 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -40,7 +42,7 @@ public class QuartzProperties { /** * Name of the scheduler. */ - private String schedulerName; + private @Nullable String schedulerName; /** * Whether to automatically start the scheduler after initialization. @@ -77,11 +79,11 @@ public class QuartzProperties { this.jobStoreType = jobStoreType; } - public String getSchedulerName() { + public @Nullable String getSchedulerName() { return this.schedulerName; } - public void setSchedulerName(String schedulerName) { + public void setSchedulerName(@Nullable String schedulerName) { this.schedulerName = schedulerName; } diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/endpoint/package-info.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/endpoint/package-info.java index 19ae3c80eb6..98c403abe0a 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/endpoint/package-info.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/endpoint/package-info.java @@ -17,4 +17,7 @@ /** * Auto-configuration for Quartz Scheduler endpoint. */ +@NullMarked package org.springframework.boot.quartz.autoconfigure.endpoint; + +import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/package-info.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/package-info.java index 87fc620b97d..81fc6ca7e63 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/package-info.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/autoconfigure/package-info.java @@ -17,4 +17,7 @@ /** * Auto-configuration for Quartz Scheduler. */ +@NullMarked package org.springframework.boot.quartz.autoconfigure; + +import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpoint.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpoint.java index f7ba6d944e1..427970fddcf 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpoint.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpoint.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.quartz.CalendarIntervalTrigger; import org.quartz.CronTrigger; import org.quartz.DailyTimeIntervalTrigger; @@ -55,6 +56,7 @@ import org.springframework.boot.actuate.endpoint.Sanitizer; import org.springframework.boot.actuate.endpoint.SanitizingFunction; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.lang.Contract; import org.springframework.util.Assert; /** @@ -137,7 +139,7 @@ public class QuartzEndpoint { * @return a summary of the jobs in the given {@code group} * @throws SchedulerException if retrieving the information from the scheduler failed */ - public QuartzJobGroupSummaryDescriptor quartzJobGroupSummary(String group) throws SchedulerException { + public @Nullable QuartzJobGroupSummaryDescriptor quartzJobGroupSummary(String group) throws SchedulerException { List jobs = findJobsByGroup(group); if (jobs.isEmpty() && !this.scheduler.getJobGroupNames().contains(group)) { return null; @@ -165,7 +167,8 @@ public class QuartzEndpoint { * @return a summary of the triggers in the given {@code group} * @throws SchedulerException if retrieving the information from the scheduler failed */ - public QuartzTriggerGroupSummaryDescriptor quartzTriggerGroupSummary(String group) throws SchedulerException { + public @Nullable QuartzTriggerGroupSummaryDescriptor quartzTriggerGroupSummary(String group) + throws SchedulerException { List triggers = findTriggersByGroup(group); if (triggers.isEmpty() && !this.scheduler.getTriggerGroupNames().contains(group)) { return null; @@ -199,7 +202,7 @@ public class QuartzEndpoint { * @return the details of the job or {@code null} if such job does not exist * @throws SchedulerException if retrieving the information from the scheduler failed */ - public QuartzJobDetailsDescriptor quartzJob(String groupName, String jobName, boolean showUnsanitized) + public @Nullable QuartzJobDetailsDescriptor quartzJob(String groupName, String jobName, boolean showUnsanitized) throws SchedulerException { JobKey jobKey = JobKey.jobKey(jobName, groupName); JobDetail jobDetail = this.scheduler.getJobDetail(jobKey); @@ -219,11 +222,12 @@ public class QuartzEndpoint { * exist * @throws SchedulerException if there is an error triggering the job */ - public QuartzJobTriggerDescriptor triggerQuartzJob(String groupName, String jobName) throws SchedulerException { + public @Nullable QuartzJobTriggerDescriptor triggerQuartzJob(String groupName, String jobName) + throws SchedulerException { return triggerQuartzJob(JobKey.jobKey(jobName, groupName)); } - private QuartzJobTriggerDescriptor triggerQuartzJob(JobKey jobKey) throws SchedulerException { + private @Nullable QuartzJobTriggerDescriptor triggerQuartzJob(JobKey jobKey) throws SchedulerException { JobDetail jobDetail = this.scheduler.getJobDetail(jobKey); if (jobDetail == null) { return null; @@ -255,7 +259,7 @@ public class QuartzEndpoint { * @return the details of the trigger or {@code null} if such trigger does not exist * @throws SchedulerException if retrieving the information from the scheduler failed */ - Map quartzTrigger(String groupName, String triggerName, boolean showUnsanitized) + @Nullable Map quartzTrigger(String groupName, String triggerName, boolean showUnsanitized) throws SchedulerException { TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, groupName); Trigger trigger = this.scheduler.getTrigger(triggerKey); @@ -272,12 +276,13 @@ public class QuartzEndpoint { return temporalUnit(unit).getDuration().multipliedBy(amount); } - private static LocalTime getLocalTime(TimeOfDay timeOfDay) { + private static @Nullable LocalTime getLocalTime(@Nullable TimeOfDay timeOfDay) { return (timeOfDay != null) ? LocalTime.of(timeOfDay.getHour(), timeOfDay.getMinute(), timeOfDay.getSecond()) : null; } - private Map sanitizeJobDataMap(JobDataMap dataMap, boolean showUnsanitized) { + @Contract("!null, _ -> !null") + private @Nullable Map sanitizeJobDataMap(@Nullable JobDataMap dataMap, boolean showUnsanitized) { if (dataMap == null) { return null; } @@ -286,7 +291,7 @@ public class QuartzEndpoint { return map; } - private Object getSanitizedValue(boolean showUnsanitized, String key, Object value) { + private @Nullable Object getSanitizedValue(boolean showUnsanitized, String key, @Nullable Object value) { SanitizableData data = new SanitizableData(null, key, value); return this.sanitizer.sanitize(data, showUnsanitized); } @@ -669,7 +674,8 @@ public class QuartzEndpoint { * @param sanitizedDataMap a sanitized data map or {@code null} * @return all properties of the trigger */ - public Map buildDetails(TriggerState triggerState, Map sanitizedDataMap) { + public Map buildDetails(TriggerState triggerState, + @Nullable Map sanitizedDataMap) { Map details = new LinkedHashMap<>(); details.put("group", this.trigger.getKey().getGroup()); details.put("name", this.trigger.getKey().getName()); @@ -697,7 +703,7 @@ public class QuartzEndpoint { */ protected abstract void appendDetails(Map content); - protected void putIfNoNull(Map content, String key, Object value) { + protected void putIfNoNull(Map content, String key, @Nullable Object value) { if (value != null) { content.put(key, value); } diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpointWebExtension.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpointWebExtension.java index bfade76f277..1fc2e33e7c9 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpointWebExtension.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/QuartzEndpointWebExtension.java @@ -18,6 +18,7 @@ package org.springframework.boot.quartz.endpoint; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.quartz.SchedulerException; import org.springframework.aot.hint.BindingReflectionHintsRegistrar; @@ -109,7 +110,7 @@ public class QuartzEndpointWebExtension { return new WebEndpointResponse<>(WebEndpointResponse.STATUS_BAD_REQUEST); } - private WebEndpointResponse handleNull(T value) { + private WebEndpointResponse handleNull(@Nullable T value) { return (value != null) ? new WebEndpointResponse<>(value) : new WebEndpointResponse<>(WebEndpointResponse.STATUS_NOT_FOUND); } @@ -117,7 +118,7 @@ public class QuartzEndpointWebExtension { @FunctionalInterface private interface ResponseSupplier { - T get() throws SchedulerException; + @Nullable T get() throws SchedulerException; } @@ -126,7 +127,7 @@ public class QuartzEndpointWebExtension { private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar(); @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { this.bindingRegistrar.registerReflectionHints(hints.reflection(), QuartzGroupsDescriptor.class, QuartzJobDetailsDescriptor.class, QuartzJobGroupSummaryDescriptor.class, QuartzTriggerGroupSummaryDescriptor.class); diff --git a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/package-info.java b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/package-info.java index c75356aba90..6fdc3288291 100644 --- a/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/package-info.java +++ b/module/spring-boot-quartz/src/main/java/org/springframework/boot/quartz/endpoint/package-info.java @@ -17,4 +17,7 @@ /** * Actuator endpoint for Quartz Scheduler. */ +@NullMarked package org.springframework.boot.quartz.endpoint; + +import org.jspecify.annotations.NullMarked;