diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 870e0568ff..08c8a97a3c 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -25,6 +25,7 @@ ext {
dependencies {
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:${javaFormatVersion}"
implementation(platform("org.springframework:spring-framework-bom:5.3.15"))
+ implementation("com.tngtech.archunit:archunit:1.0.0")
implementation("com.fasterxml.jackson.core:jackson-databind:2.11.4")
implementation("commons-codec:commons-codec:1.13")
implementation("org.apache.maven:maven-embedder:3.6.2")
@@ -51,6 +52,10 @@ gradlePlugin {
id = "org.springframework.boot.annotation-processor"
implementationClass = "org.springframework.boot.build.processors.AnnotationProcessorPlugin"
}
+ architecturePlugin {
+ id = "org.springframework.boot.architecture"
+ implementationClass = "org.springframework.boot.build.architecture.ArchitecturePlugin"
+ }
autoConfigurationPlugin {
id = "org.springframework.boot.auto-configuration"
implementationClass = "org.springframework.boot.build.autoconfigure.AutoConfigurationPlugin"
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java
index decff985ca..e46d2c4180 100644
--- a/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java
+++ b/buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java
@@ -48,6 +48,7 @@ import org.gradle.api.tasks.testing.Test;
import org.gradle.testretry.TestRetryPlugin;
import org.gradle.testretry.TestRetryTaskExtension;
+import org.springframework.boot.build.architecture.ArchitecturePlugin;
import org.springframework.boot.build.classpath.CheckClasspathForProhibitedDependencies;
import org.springframework.boot.build.optional.OptionalDependenciesPlugin;
import org.springframework.boot.build.testing.TestFailuresPlugin;
@@ -61,8 +62,8 @@ import org.springframework.util.StringUtils;
*
* - The project is configured with source and target compatibility of 1.8
*
- {@link SpringJavaFormatPlugin Spring Java Format}, {@link CheckstylePlugin
- * Checkstyle}, {@link TestFailuresPlugin Test Failures}, and {@link TestRetryPlugin Test
- * Retry} plugins are applied
+ * Checkstyle}, {@link TestFailuresPlugin Test Failures}, {@link TestRetryPlugin Test
+ * Retry}, and {@link ArchitecturePlugin Architecture} plugins are applied
*
- {@link Test} tasks are configured:
*
* - to use JUnit Platform
@@ -107,6 +108,7 @@ class JavaConventions {
void apply(Project project) {
project.getPlugins().withType(JavaBasePlugin.class, (java) -> {
project.getPlugins().apply(TestFailuresPlugin.class);
+ project.getPlugins().apply(ArchitecturePlugin.class);
configureSpringJavaFormat(project);
configureJavaConventions(project);
configureJavadocConventions(project);
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitecturePlugin.java b/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitecturePlugin.java
new file mode 100644
index 0000000000..dbb2842d54
--- /dev/null
+++ b/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitecturePlugin.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.plugins.JavaBasePlugin;
+import org.gradle.api.plugins.JavaPluginExtension;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.TaskProvider;
+import org.gradle.language.base.plugins.LifecycleBasePlugin;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * {@link Plugin} for verifying a project's architecture.
+ *
+ * @author Andy Wilkinson
+ */
+public class ArchitecturePlugin implements Plugin {
+
+ @Override
+ public void apply(Project project) {
+ project.getPlugins().withType(JavaBasePlugin.class, (javaPlugin) -> registerTasks(project));
+ }
+
+ private void registerTasks(Project project) {
+ JavaPluginExtension javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class);
+ List> packageTangleChecks = new ArrayList<>();
+ for (SourceSet sourceSet : javaPluginExtension.getSourceSets()) {
+ TaskProvider checkPackageTangles = project.getTasks().register(
+ "checkForPackageTangles" + StringUtils.capitalize(sourceSet.getName()), PackageTangleCheck.class,
+ (task) -> {
+ task.setClasses(sourceSet.getOutput().getClassesDirs());
+ task.setDescription("Checks the classes of the " + sourceSet.getName()
+ + " source set for package tangles.");
+ task.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
+ });
+ packageTangleChecks.add(checkPackageTangles);
+ }
+ if (!packageTangleChecks.isEmpty()) {
+ TaskProvider checkTask = project.getTasks().named(LifecycleBasePlugin.CHECK_TASK_NAME);
+ checkTask.configure((check) -> check.dependsOn(packageTangleChecks));
+ }
+ }
+
+}
diff --git a/buildSrc/src/main/java/org/springframework/boot/build/architecture/PackageTangleCheck.java b/buildSrc/src/main/java/org/springframework/boot/build/architecture/PackageTangleCheck.java
new file mode 100644
index 0000000000..abfff812c0
--- /dev/null
+++ b/buildSrc/src/main/java/org/springframework/boot/build/architecture/PackageTangleCheck.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+import java.util.stream.Collectors;
+
+import com.tngtech.archunit.core.domain.JavaClasses;
+import com.tngtech.archunit.core.importer.ClassFileImporter;
+import com.tngtech.archunit.lang.EvaluationResult;
+import com.tngtech.archunit.library.dependencies.SliceRule;
+import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.GradleException;
+import org.gradle.api.Task;
+import org.gradle.api.file.DirectoryProperty;
+import org.gradle.api.file.FileCollection;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.IgnoreEmptyDirectories;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.Internal;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.PathSensitive;
+import org.gradle.api.tasks.PathSensitivity;
+import org.gradle.api.tasks.SkipWhenEmpty;
+import org.gradle.api.tasks.TaskAction;
+
+import org.springframework.util.FileCopyUtils;
+
+/**
+ * {@link Task} that checks for package tangles.
+ *
+ * @author Andy Wilkinson
+ */
+public abstract class PackageTangleCheck extends DefaultTask {
+
+ private FileCollection classes;
+
+ public PackageTangleCheck() {
+ getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
+ }
+
+ @TaskAction
+ void checkForPackageTangles() throws IOException {
+ JavaClasses javaClasses = new ClassFileImporter()
+ .importPaths(this.classes.getFiles().stream().map(File::toPath).collect(Collectors.toList()));
+ SliceRule freeOfCycles = SlicesRuleDefinition.slices().matching("(**)").should().beFreeOfCycles();
+ EvaluationResult result = freeOfCycles.evaluate(javaClasses);
+ File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile();
+ outputFile.getParentFile().mkdirs();
+ if (result.hasViolation()) {
+ Files.write(outputFile.toPath(), result.getFailureReport().toString().getBytes(StandardCharsets.UTF_8),
+ StandardOpenOption.CREATE);
+ FileWriter writer = new FileWriter(outputFile);
+ FileCopyUtils.copy(result.getFailureReport().toString(), writer);
+ throw new GradleException("Package tangle check failed. See '" + outputFile + "' for details.");
+ }
+ else {
+ outputFile.createNewFile();
+ }
+ }
+
+ public void setClasses(FileCollection classes) {
+ this.classes = classes;
+ }
+
+ @Internal
+ public FileCollection getClasses() {
+ return this.classes;
+ }
+
+ @InputFiles
+ @SkipWhenEmpty
+ @IgnoreEmptyDirectories
+ @PathSensitive(PathSensitivity.RELATIVE)
+ final FileTree getInputClasses() {
+ return this.classes.getAsFileTree();
+ }
+
+ @OutputDirectory
+ public abstract DirectoryProperty getOutputDirectory();
+
+}
diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/PackageTangleCheckTests.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/PackageTangleCheckTests.java
new file mode 100644
index 0000000000..78133c063d
--- /dev/null
+++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/PackageTangleCheckTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.gradle.api.GradleException;
+import org.gradle.api.Project;
+import org.gradle.testfixtures.ProjectBuilder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.util.FileSystemUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+/**
+ * Tests for {@link PackageTangleCheck}.
+ *
+ * @author Andy Wilkinson
+ */
+class PackageTangleCheckTests {
+
+ @TempDir
+ File temp;
+
+ @Test
+ void whenPackagesAreTangledTaskFailsAndWritesAReport() throws Exception {
+ prepareTask("tangled", (packageTangleCheck) -> {
+ assertThatExceptionOfType(GradleException.class)
+ .isThrownBy(() -> packageTangleCheck.checkForPackageTangles());
+ assertThat(
+ new File(packageTangleCheck.getProject().getBuildDir(), "checkForPackageTangles/failure-report.txt")
+ .length()).isGreaterThan(0);
+ });
+ }
+
+ @Test
+ void whenPackagesAreNotTangledTaskSucceedsAndWritesAnEmptyReport() throws Exception {
+ prepareTask("untangled", (packageTangleCheck) -> {
+ packageTangleCheck.checkForPackageTangles();
+ assertThat(
+ new File(packageTangleCheck.getProject().getBuildDir(), "checkForPackageTangles/failure-report.txt")
+ .length()).isEqualTo(0);
+ });
+ }
+
+ private void prepareTask(String classes, Callback callback) throws Exception {
+ File projectDir = new File(this.temp, "project");
+ projectDir.mkdirs();
+ copyClasses(classes, projectDir);
+ Project project = ProjectBuilder.builder().withProjectDir(projectDir).build();
+ PackageTangleCheck packageTangleCheck = project.getTasks().create("checkForPackageTangles",
+ PackageTangleCheck.class, (task) -> task.setClasses(project.files("classes")));
+ callback.accept(packageTangleCheck);
+ }
+
+ private void copyClasses(String name, File projectDir) throws IOException {
+ PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+ Resource root = resolver.getResource("classpath:org/springframework/boot/build/architecture/" + name);
+ FileSystemUtils.copyRecursively(root.getFile(),
+ new File(projectDir, "classes/org/springframework/boot/build/architecture/" + name));
+
+ }
+
+ private interface Callback {
+
+ void accept(T item) throws Exception;
+
+ }
+
+}
diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/tangled/TangledOne.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/tangled/TangledOne.java
new file mode 100644
index 0000000000..3b417723fd
--- /dev/null
+++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/tangled/TangledOne.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture.tangled;
+
+import org.springframework.boot.build.architecture.tangled.sub.TangledTwo;
+
+public final class TangledOne {
+
+ public static final String ID = TangledTwo.class.getName() + "One";
+
+ private TangledOne() {
+
+ }
+
+}
diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/tangled/sub/TangledTwo.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/tangled/sub/TangledTwo.java
new file mode 100644
index 0000000000..172e9b1e81
--- /dev/null
+++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/tangled/sub/TangledTwo.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture.tangled.sub;
+
+import org.springframework.boot.build.architecture.tangled.TangledOne;
+
+public final class TangledTwo {
+
+ public static final String ID = TangledOne.ID + "-Two";
+
+ private TangledTwo() {
+
+ }
+
+}
diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/untangled/UntangledOne.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/untangled/UntangledOne.java
new file mode 100644
index 0000000000..04bbd463fc
--- /dev/null
+++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/untangled/UntangledOne.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture.untangled;
+
+import org.springframework.boot.build.architecture.untangled.sub.UntangledTwo;
+
+public final class UntangledOne {
+
+ public static final String ID = UntangledTwo.class.getName() + "One";
+
+ private UntangledOne() {
+
+ }
+
+}
diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/untangled/sub/UntangledTwo.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/untangled/sub/UntangledTwo.java
new file mode 100644
index 0000000000..8b7afd257b
--- /dev/null
+++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/untangled/sub/UntangledTwo.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012-2022 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.build.architecture.untangled.sub;
+
+public final class UntangledTwo {
+
+ public static final String ID = "Two";
+
+ private UntangledTwo() {
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java
index a1a55f9562..e144521271 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java
@@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
+import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -45,7 +46,7 @@ import org.springframework.transaction.TransactionManager;
* @author Kazuki Shimizu
* @since 1.0.0
*/
-@AutoConfiguration
+@AutoConfiguration(before = TransactionAutoConfiguration.class)
@ConditionalOnClass({ JdbcTemplate.class, TransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java
index a5e8fc62ab..94b1f9bf32 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.java
@@ -24,6 +24,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
@@ -37,7 +38,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
* @author Andy Wilkinson
* @since 1.0.0
*/
-@AutoConfiguration(after = { DataSourceAutoConfiguration.class })
+@AutoConfiguration(after = DataSourceAutoConfiguration.class, before = TransactionAutoConfiguration.class)
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })
@EnableConfigurationProperties(JpaProperties.class)
@Import(HibernateJpaConfiguration.class)
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration.java
index a2557d9e0c..09f4bf71ee 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration.java
@@ -20,8 +20,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
import org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration.SqlInitializationModeCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
@@ -34,7 +32,7 @@ import org.springframework.context.annotation.Import;
* @author Andy Wilkinson
* @since 2.5.0
*/
-@AutoConfiguration(after = { R2dbcAutoConfiguration.class, DataSourceAutoConfiguration.class })
+@AutoConfiguration
@EnableConfigurationProperties(SqlInitializationProperties.class)
@Import({ DatabaseInitializationDependencyConfigurer.class, R2dbcInitializationConfiguration.class,
DataSourceInitializationConfiguration.class })
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java
index 2a9e109d80..56ee075564 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.java
@@ -25,10 +25,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
-import org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
-import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
-import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -48,8 +44,7 @@ import org.springframework.transaction.support.TransactionTemplate;
* @author Stephane Nicoll
* @since 1.3.0
*/
-@AutoConfiguration(after = { JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
- DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
+@AutoConfiguration
@ConditionalOnClass(PlatformTransactionManager.class)
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java
index 8634584fae..1e61e6f52f 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java
@@ -24,6 +24,7 @@ import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.context.annotation.Import;
/**
@@ -35,7 +36,7 @@ import org.springframework.context.annotation.Import;
* @since 1.2.0
*/
@AutoConfiguration(before = { XADataSourceAutoConfiguration.class, ActiveMQAutoConfiguration.class,
- ArtemisAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
+ ArtemisAutoConfiguration.class, HibernateJpaAutoConfiguration.class, TransactionAutoConfiguration.class })
@ConditionalOnClass(javax.transaction.Transaction.class)
@ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true)
@Import({ JndiJtaConfiguration.class, AtomikosJtaConfiguration.class })
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonComponentModuleTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonComponentModuleTests.java
index 2d7b575710..11ffa101a0 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonComponentModuleTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonComponentModuleTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
+import org.springframework.boot.jackson.types.Name;
+import org.springframework.boot.jackson.types.NameAndAge;
+import org.springframework.boot.jackson.types.NameAndCareer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonMixinModuleTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonMixinModuleTests.java
index b6a1430e3d..7b4bc40931 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonMixinModuleTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonMixinModuleTests.java
@@ -30,6 +30,8 @@ import org.springframework.boot.jackson.scan.a.RenameMixInClass;
import org.springframework.boot.jackson.scan.b.RenameMixInAbstractClass;
import org.springframework.boot.jackson.scan.c.RenameMixInInterface;
import org.springframework.boot.jackson.scan.d.EmptyMixInClass;
+import org.springframework.boot.jackson.types.Name;
+import org.springframework.boot.jackson.types.NameAndAge;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.ClassUtils;
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectDeserializerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectDeserializerTests.java
index 9eac6ae63c..b680ce4310 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectDeserializerTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectDeserializerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.databind.node.NullNode;
import org.junit.jupiter.api.Test;
import org.springframework.boot.jackson.NameAndAgeJsonComponent.Deserializer;
+import org.springframework.boot.jackson.types.NameAndAge;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectSerializerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectSerializerTests.java
index 25eb5327da..67fc452e3b 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectSerializerTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/JsonObjectSerializerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.jupiter.api.Test;
import org.springframework.boot.jackson.NameAndAgeJsonComponent.Serializer;
+import org.springframework.boot.jackson.types.NameAndAge;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonComponent.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonComponent.java
index c1575a8b5c..43fb58626c 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonComponent.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -25,6 +25,8 @@ import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
+import org.springframework.boot.jackson.types.NameAndAge;
+
/**
* Sample {@link JsonComponent @JsonComponent} used for tests.
*
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonKeyComponent.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonKeyComponent.java
index f98d7b5927..fdf5f9175d 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonKeyComponent.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAgeJsonKeyComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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 com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.SerializerProvider;
+import org.springframework.boot.jackson.types.NameAndAge;
+
/**
* Sample {@link JsonComponent @JsonComponent} used for tests.
*
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareerJsonComponent.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareerJsonComponent.java
index 4ea1914e1e..e22c43aab9 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareerJsonComponent.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareerJsonComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -25,6 +25,9 @@ import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;
+import org.springframework.boot.jackson.types.Name;
+import org.springframework.boot.jackson.types.NameAndCareer;
+
/**
* Sample {@link JsonComponent @JsonComponent} used for tests.
*
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/a/RenameMixInClass.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/a/RenameMixInClass.java
index 15d401f598..11fce2da7a 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/a/RenameMixInClass.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/a/RenameMixInClass.java
@@ -19,8 +19,8 @@ package org.springframework.boot.jackson.scan.a;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.boot.jackson.JsonMixin;
-import org.springframework.boot.jackson.Name;
-import org.springframework.boot.jackson.NameAndAge;
+import org.springframework.boot.jackson.types.Name;
+import org.springframework.boot.jackson.types.NameAndAge;
@JsonMixin(type = { Name.class, NameAndAge.class })
public class RenameMixInClass {
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/b/RenameMixInAbstractClass.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/b/RenameMixInAbstractClass.java
index 0ee9bf1913..538af6cc3b 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/b/RenameMixInAbstractClass.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/b/RenameMixInAbstractClass.java
@@ -19,7 +19,7 @@ package org.springframework.boot.jackson.scan.b;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.boot.jackson.JsonMixin;
-import org.springframework.boot.jackson.NameAndAge;
+import org.springframework.boot.jackson.types.NameAndAge;
@JsonMixin(type = NameAndAge.class)
public abstract class RenameMixInAbstractClass {
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/c/RenameMixInInterface.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/c/RenameMixInInterface.java
index cfff37fe32..b0bf524e14 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/c/RenameMixInInterface.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/c/RenameMixInInterface.java
@@ -19,7 +19,7 @@ package org.springframework.boot.jackson.scan.c;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.boot.jackson.JsonMixin;
-import org.springframework.boot.jackson.NameAndAge;
+import org.springframework.boot.jackson.types.NameAndAge;
@JsonMixin(type = NameAndAge.class)
public interface RenameMixInInterface {
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/d/EmptyMixInClass.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/d/EmptyMixInClass.java
index 358f9cb378..805ed8081b 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/d/EmptyMixInClass.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/scan/d/EmptyMixInClass.java
@@ -17,8 +17,8 @@
package org.springframework.boot.jackson.scan.d;
import org.springframework.boot.jackson.JsonMixin;
-import org.springframework.boot.jackson.Name;
-import org.springframework.boot.jackson.NameAndAge;
+import org.springframework.boot.jackson.types.Name;
+import org.springframework.boot.jackson.types.NameAndAge;
@JsonMixin(type = { Name.class, NameAndAge.class })
public class EmptyMixInClass {
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/Name.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/Name.java
similarity index 88%
rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/Name.java
rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/Name.java
index 02fa57f06e..4da8746ef8 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/Name.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/Name.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.jackson;
+package org.springframework.boot.jackson.types;
/**
* Sample object used for tests.
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAge.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/NameAndAge.java
similarity index 94%
rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAge.java
rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/NameAndAge.java
index 7935b13723..ef6f700f02 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndAge.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/NameAndAge.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.jackson;
+package org.springframework.boot.jackson.types;
import org.springframework.util.ObjectUtils;
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareer.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/NameAndCareer.java
similarity index 89%
rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareer.java
rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/NameAndCareer.java
index b16df5bd1d..37acbc68c7 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/NameAndCareer.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jackson/types/NameAndCareer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2019 the original author or authors.
+ * Copyright 2012-2022 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.boot.jackson;
+package org.springframework.boot.jackson.types;
/**
* Sample object used for tests.