Add nullability annotations to module/spring-boot-liquibase

See gh-46587
This commit is contained in:
Moritz Halbritter
2025-08-04 11:27:41 +02:00
parent 97ad5cb204
commit 51ec3ce3df
12 changed files with 104 additions and 76 deletions
@@ -17,6 +17,7 @@
package org.springframework.boot.liquibase;
import liquibase.exception.ChangeLogParseException;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
@@ -32,17 +33,18 @@ class LiquibaseChangelogMissingFailureAnalyzer extends AbstractFailureAnalyzer<C
private static final String MESSAGE_SUFFIX = " does not exist";
@Override
protected FailureAnalysis analyze(Throwable rootFailure, ChangeLogParseException cause) {
if (cause.getMessage().endsWith(MESSAGE_SUFFIX)) {
String changelogPath = extractChangelogPath(cause);
protected @Nullable FailureAnalysis analyze(Throwable rootFailure, ChangeLogParseException cause) {
String message = cause.getMessage();
if (message != null && message.endsWith(MESSAGE_SUFFIX)) {
String changelogPath = extractChangelogPath(message);
return new FailureAnalysis(getDescription(changelogPath),
"Make sure a Liquibase changelog is present at the configured path.", cause);
}
return null;
}
private String extractChangelogPath(ChangeLogParseException cause) {
return cause.getMessage().substring(0, cause.getMessage().length() - MESSAGE_SUFFIX.length());
private String extractChangelogPath(String message) {
return message.substring(0, message.length() - MESSAGE_SUFFIX.length());
}
private String getDescription(String changelogPath) {
@@ -25,6 +25,7 @@ import liquibase.change.DatabaseChange;
import liquibase.integration.spring.Customizer;
import liquibase.integration.spring.SpringLiquibase;
import liquibase.ui.UIServiceEnum;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@@ -142,8 +143,8 @@ public final class LiquibaseAutoConfiguration {
return liquibase;
}
private SpringLiquibase createSpringLiquibase(DataSource liquibaseDataSource, DataSource dataSource,
LiquibaseConnectionDetails connectionDetails) {
private SpringLiquibase createSpringLiquibase(@Nullable DataSource liquibaseDataSource,
@Nullable DataSource dataSource, LiquibaseConnectionDetails connectionDetails) {
DataSource migrationDataSource = getMigrationDataSource(liquibaseDataSource, dataSource, connectionDetails);
SpringLiquibase liquibase = (migrationDataSource == liquibaseDataSource
|| migrationDataSource == dataSource) ? new SpringLiquibase()
@@ -152,8 +153,8 @@ public final class LiquibaseAutoConfiguration {
return liquibase;
}
private DataSource getMigrationDataSource(DataSource liquibaseDataSource, DataSource dataSource,
LiquibaseConnectionDetails connectionDetails) {
private DataSource getMigrationDataSource(@Nullable DataSource liquibaseDataSource,
@Nullable DataSource dataSource, LiquibaseConnectionDetails connectionDetails) {
if (liquibaseDataSource != null) {
return liquibaseDataSource;
}
@@ -224,7 +225,7 @@ public final class LiquibaseAutoConfiguration {
static class LiquibaseAutoConfigurationRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
hints.resources().registerPattern("db/changelog/**");
}
@@ -242,22 +243,22 @@ public final class LiquibaseAutoConfiguration {
}
@Override
public String getUsername() {
public @Nullable String getUsername() {
return this.properties.getUser();
}
@Override
public String getPassword() {
public @Nullable String getPassword() {
return this.properties.getPassword();
}
@Override
public String getJdbcUrl() {
public @Nullable String getJdbcUrl() {
return this.properties.getUrl();
}
@Override
public String getDriverClassName() {
public @Nullable String getDriverClassName() {
String driverClassName = this.properties.getDriverClassName();
return (driverClassName != null) ? driverClassName : LiquibaseConnectionDetails.super.getDriverClassName();
}
@@ -16,6 +16,8 @@
package org.springframework.boot.liquibase.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
import org.springframework.boot.jdbc.DatabaseDriver;
@@ -32,21 +34,21 @@ public interface LiquibaseConnectionDetails extends ConnectionDetails {
* required.
* @return the username for the database or {@code null}
*/
String getUsername();
@Nullable String getUsername();
/**
* Password for the database or {@code null} if no Liquibase-specific configuration is
* required.
* @return the password for the database or {@code null}
*/
String getPassword();
@Nullable String getPassword();
/**
* JDBC URL for the database or {@code null} if no Liquibase-specific configuration is
* required.
* @return the JDBC URL for the database or {@code null}
*/
String getJdbcUrl();
@Nullable String getJdbcUrl();
/**
* The name of the JDBC driver class. Defaults to the class name of the driver
@@ -56,7 +58,7 @@ public interface LiquibaseConnectionDetails extends ConnectionDetails {
* @see DatabaseDriver#fromJdbcUrl(String)
* @see DatabaseDriver#getDriverClassName()
*/
default String getDriverClassName() {
@Nullable default String getDriverClassName() {
String jdbcUrl = getJdbcUrl();
return (jdbcUrl != null) ? DatabaseDriver.fromJdbcUrl(jdbcUrl).getDriverClassName() : null;
}
@@ -24,6 +24,7 @@ import liquibase.UpdateSummaryEnum;
import liquibase.UpdateSummaryOutputEnum;
import liquibase.integration.spring.SpringLiquibase;
import liquibase.ui.UIServiceEnum;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
@@ -54,22 +55,22 @@ public class LiquibaseProperties {
/**
* List of runtime contexts to use.
*/
private List<String> contexts;
private @Nullable List<String> contexts;
/**
* Default database schema.
*/
private String defaultSchema;
private @Nullable String defaultSchema;
/**
* Schema to use for Liquibase objects.
*/
private String liquibaseSchema;
private @Nullable String liquibaseSchema;
/**
* Tablespace to use for Liquibase objects.
*/
private String liquibaseTablespace;
private @Nullable String liquibaseTablespace;
/**
* Name of table to use for tracking change history.
@@ -94,38 +95,38 @@ public class LiquibaseProperties {
/**
* Login user of the database to migrate.
*/
private String user;
private @Nullable String user;
/**
* Login password of the database to migrate.
*/
private String password;
private @Nullable String password;
/**
* Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
*/
private String driverClassName;
private @Nullable String driverClassName;
/**
* JDBC URL of the database to migrate. If not set, the primary configured data source
* is used.
*/
private String url;
private @Nullable String url;
/**
* List of runtime labels to use.
*/
private List<String> labelFilter;
private @Nullable List<String> labelFilter;
/**
* Change log parameters.
*/
private Map<String, String> parameters;
private @Nullable Map<String, String> parameters;
/**
* File to which rollback SQL is written when an update is performed.
*/
private File rollbackFile;
private @Nullable File rollbackFile;
/**
* Whether rollback should be tested before update is performed.
@@ -137,32 +138,32 @@ public class LiquibaseProperties {
* "rollbackFile" to generate a rollback script for all existing changes associated
* with that tag.
*/
private String tag;
private @Nullable String tag;
/**
* Whether to print a summary of the update operation.
*/
private ShowSummary showSummary;
private @Nullable ShowSummary showSummary;
/**
* Where to print a summary of the update operation.
*/
private ShowSummaryOutput showSummaryOutput;
private @Nullable ShowSummaryOutput showSummaryOutput;
/**
* Which UIService to use.
*/
private UiService uiService;
private @Nullable UiService uiService;
/**
* Whether to send product usage data and analytics to Liquibase.
*/
private Boolean analyticsEnabled;
private @Nullable Boolean analyticsEnabled;
/**
* Liquibase Pro license key.
*/
private String licenseKey;
private @Nullable String licenseKey;
public String getChangeLog() {
return this.changeLog;
@@ -173,35 +174,35 @@ public class LiquibaseProperties {
this.changeLog = changeLog;
}
public List<String> getContexts() {
public @Nullable List<String> getContexts() {
return this.contexts;
}
public void setContexts(List<String> contexts) {
public void setContexts(@Nullable List<String> contexts) {
this.contexts = contexts;
}
public String getDefaultSchema() {
public @Nullable String getDefaultSchema() {
return this.defaultSchema;
}
public void setDefaultSchema(String defaultSchema) {
public void setDefaultSchema(@Nullable String defaultSchema) {
this.defaultSchema = defaultSchema;
}
public String getLiquibaseSchema() {
public @Nullable String getLiquibaseSchema() {
return this.liquibaseSchema;
}
public void setLiquibaseSchema(String liquibaseSchema) {
public void setLiquibaseSchema(@Nullable String liquibaseSchema) {
this.liquibaseSchema = liquibaseSchema;
}
public String getLiquibaseTablespace() {
public @Nullable String getLiquibaseTablespace() {
return this.liquibaseTablespace;
}
public void setLiquibaseTablespace(String liquibaseTablespace) {
public void setLiquibaseTablespace(@Nullable String liquibaseTablespace) {
this.liquibaseTablespace = liquibaseTablespace;
}
@@ -245,59 +246,59 @@ public class LiquibaseProperties {
this.enabled = enabled;
}
public String getUser() {
public @Nullable String getUser() {
return this.user;
}
public void setUser(String user) {
public void setUser(@Nullable String user) {
this.user = user;
}
public String getPassword() {
public @Nullable String getPassword() {
return this.password;
}
public void setPassword(String password) {
public void setPassword(@Nullable String password) {
this.password = password;
}
public String getDriverClassName() {
public @Nullable String getDriverClassName() {
return this.driverClassName;
}
public void setDriverClassName(String driverClassName) {
public void setDriverClassName(@Nullable String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
public @Nullable String getUrl() {
return this.url;
}
public void setUrl(String url) {
public void setUrl(@Nullable String url) {
this.url = url;
}
public List<String> getLabelFilter() {
public @Nullable List<String> getLabelFilter() {
return this.labelFilter;
}
public void setLabelFilter(List<String> labelFilter) {
public void setLabelFilter(@Nullable List<String> labelFilter) {
this.labelFilter = labelFilter;
}
public Map<String, String> getParameters() {
public @Nullable Map<String, String> getParameters() {
return this.parameters;
}
public void setParameters(Map<String, String> parameters) {
public void setParameters(@Nullable Map<String, String> parameters) {
this.parameters = parameters;
}
public File getRollbackFile() {
public @Nullable File getRollbackFile() {
return this.rollbackFile;
}
public void setRollbackFile(File rollbackFile) {
public void setRollbackFile(@Nullable File rollbackFile) {
this.rollbackFile = rollbackFile;
}
@@ -309,51 +310,51 @@ public class LiquibaseProperties {
this.testRollbackOnUpdate = testRollbackOnUpdate;
}
public String getTag() {
public @Nullable String getTag() {
return this.tag;
}
public void setTag(String tag) {
public void setTag(@Nullable String tag) {
this.tag = tag;
}
public ShowSummary getShowSummary() {
public @Nullable ShowSummary getShowSummary() {
return this.showSummary;
}
public void setShowSummary(ShowSummary showSummary) {
public void setShowSummary(@Nullable ShowSummary showSummary) {
this.showSummary = showSummary;
}
public ShowSummaryOutput getShowSummaryOutput() {
public @Nullable ShowSummaryOutput getShowSummaryOutput() {
return this.showSummaryOutput;
}
public void setShowSummaryOutput(ShowSummaryOutput showSummaryOutput) {
public void setShowSummaryOutput(@Nullable ShowSummaryOutput showSummaryOutput) {
this.showSummaryOutput = showSummaryOutput;
}
public UiService getUiService() {
public @Nullable UiService getUiService() {
return this.uiService;
}
public void setUiService(UiService uiService) {
public void setUiService(@Nullable UiService uiService) {
this.uiService = uiService;
}
public Boolean getAnalyticsEnabled() {
public @Nullable Boolean getAnalyticsEnabled() {
return this.analyticsEnabled;
}
public void setAnalyticsEnabled(Boolean analyticsEnabled) {
public void setAnalyticsEnabled(@Nullable Boolean analyticsEnabled) {
this.analyticsEnabled = analyticsEnabled;
}
public String getLicenseKey() {
public @Nullable String getLicenseKey() {
return this.licenseKey;
}
public void setLicenseKey(String licenseKey) {
public void setLicenseKey(@Nullable String licenseKey) {
this.licenseKey = licenseKey;
}
@@ -17,4 +17,7 @@
/**
* Auto-configuration for Liquibase endpoint.
*/
@NullMarked
package org.springframework.boot.liquibase.autoconfigure.endpoint;
import org.jspecify.annotations.NullMarked;
@@ -17,4 +17,7 @@
/**
* Auto-configuration for Liquibase.
*/
@NullMarked
package org.springframework.boot.liquibase.autoconfigure;
import org.jspecify.annotations.NullMarked;
@@ -16,6 +16,8 @@
package org.springframework.boot.liquibase.docker.compose;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory;
import org.springframework.boot.jdbc.autoconfigure.JdbcConnectionDetails;
import org.springframework.boot.liquibase.autoconfigure.LiquibaseConnectionDetails;
@@ -34,12 +36,12 @@ class JdbcAdaptingLiquibaseConnectionDetailsFactory
return new LiquibaseConnectionDetails() {
@Override
public String getUsername() {
public @Nullable String getUsername() {
return input.getUsername();
}
@Override
public String getPassword() {
public @Nullable String getPassword() {
return input.getPassword();
}
@@ -17,4 +17,7 @@
/**
* Support for Docker Compose Liquibase service connections.
*/
@NullMarked
package org.springframework.boot.liquibase.docker.compose;
import org.jspecify.annotations.NullMarked;
@@ -31,6 +31,7 @@ import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.integration.spring.SpringLiquibase;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.actuate.endpoint.OperationResponseBody;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
@@ -128,9 +129,10 @@ public class LiquibaseEndpoint {
private final Map<String, LiquibaseBeanDescriptor> liquibaseBeans;
private final String parentId;
private final @Nullable String parentId;
private ContextLiquibaseBeansDescriptor(Map<String, LiquibaseBeanDescriptor> liquibaseBeans, String parentId) {
private ContextLiquibaseBeansDescriptor(Map<String, LiquibaseBeanDescriptor> liquibaseBeans,
@Nullable String parentId) {
this.liquibaseBeans = liquibaseBeans;
this.parentId = parentId;
}
@@ -139,7 +141,7 @@ public class LiquibaseEndpoint {
return this.liquibaseBeans;
}
public String getParentId() {
public @Nullable String getParentId() {
return this.parentId;
}
@@ -187,7 +189,7 @@ public class LiquibaseEndpoint {
private final Set<String> labels;
private final String checksum;
private final @Nullable String checksum;
private final Integer orderExecuted;
@@ -250,7 +252,7 @@ public class LiquibaseEndpoint {
return this.labels;
}
public String getChecksum() {
public @Nullable String getChecksum() {
return this.checksum;
}
@@ -17,4 +17,7 @@
/**
* Actuator endpoint for Liquibase.
*/
@NullMarked
package org.springframework.boot.liquibase.endpoint;
import org.jspecify.annotations.NullMarked;
@@ -17,4 +17,7 @@
/**
* Custom support for Liquibase database migration.
*/
@NullMarked
package org.springframework.boot.liquibase;
import org.jspecify.annotations.NullMarked;
@@ -17,4 +17,7 @@
/**
* Support for testcontainers Liquibase service connections.
*/
@NullMarked
package org.springframework.boot.liquibase.testcontainers;
import org.jspecify.annotations.NullMarked;