Compare commits
20 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
4b8db9b630 | |
|
|
85bbbc99ad | |
|
|
01d93513c7 | |
|
|
40453e76f0 | |
|
|
7459fe0163 | |
|
|
859606ae13 | |
|
|
fc8f9a322d | |
|
|
bd5264e28e | |
|
|
d4408ab9cd | |
|
|
1650092890 | |
|
|
7bc6ebc169 | |
|
|
1e96c6cd02 | |
|
|
2f27912aea | |
|
|
5bb8d711ce | |
|
|
977be74768 | |
|
|
0f4de3c4f4 | |
|
|
39c0d17b87 | |
|
|
4d94fcba9a | |
|
|
0884005212 | |
|
|
384e8b9b74 |
|
|
@ -13,6 +13,6 @@
|
|||
"@springio/asciidoctor-extensions": "1.0.0-alpha.17"
|
||||
},
|
||||
"config": {
|
||||
"ui-bundle-url": "https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.21/ui-bundle.zip"
|
||||
"ui-bundle-url": "https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.24/ui-bundle.zip"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -230,10 +230,18 @@ class JavaConventions {
|
|||
CoreJavadocOptions options = (CoreJavadocOptions) javadoc.getOptions();
|
||||
options.source("17");
|
||||
options.encoding("UTF-8");
|
||||
options.addStringOption("Xdoclint:none", "-quiet");
|
||||
addValuelessOption(options, "Xdoclint:none");
|
||||
addValuelessOption(options, "quiet");
|
||||
if (!javadoc.getName().contains("aggregated")) {
|
||||
addValuelessOption(options, "-no-fonts");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addValuelessOption(CoreJavadocOptions options, String option) {
|
||||
options.addMultilineMultiValueOption(option).setValue(List.of(Collections.emptyList()));
|
||||
}
|
||||
|
||||
private void configureJavaConventions(Project project) {
|
||||
if (!project.hasProperty("toolchainVersion")) {
|
||||
JavaPluginExtension javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class);
|
||||
|
|
|
|||
|
|
@ -16,17 +16,17 @@
|
|||
|
||||
package org.springframework.boot.build.architecture;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskProvider;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin;
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTool;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -46,28 +46,45 @@ public class ArchitecturePlugin implements Plugin<Project> {
|
|||
|
||||
private void registerTasks(Project project, ArchitectureCheckExtension extension) {
|
||||
JavaPluginExtension javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class);
|
||||
List<TaskProvider<ArchitectureCheck>> packageTangleChecks = new ArrayList<>();
|
||||
for (SourceSet sourceSet : javaPluginExtension.getSourceSets()) {
|
||||
TaskProvider<ArchitectureCheck> checkPackageTangles = project.getTasks()
|
||||
.register("checkArchitecture" + StringUtils.capitalize(sourceSet.getName()), ArchitectureCheck.class,
|
||||
(task) -> {
|
||||
task.getSourceSet().set(sourceSet.getName());
|
||||
task.getCompileClasspath().from(sourceSet.getCompileClasspath());
|
||||
task.setClasses(sourceSet.getOutput().getClassesDirs());
|
||||
task.getResourcesDirectory().set(sourceSet.getOutput().getResourcesDir());
|
||||
task.dependsOn(sourceSet.getProcessResourcesTaskName());
|
||||
task.setDescription("Checks the architecture of the classes of the " + sourceSet.getName()
|
||||
+ " source set.");
|
||||
task.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
|
||||
registerArchitectureCheck(sourceSet, "java", project).configure((task) -> {
|
||||
task.setClasses(project.files(project.getTasks()
|
||||
.named(sourceSet.getCompileTaskName("java"), JavaCompile.class)
|
||||
.flatMap((compile) -> compile.getDestinationDirectory())));
|
||||
task.getNullMarkedEnabled().set(extension.getNullMarked().getEnabled());
|
||||
task.getNullMarkedIgnoredPackages().set(extension.getNullMarked().getIgnoredPackages());
|
||||
});
|
||||
packageTangleChecks.add(checkPackageTangles);
|
||||
}
|
||||
if (!packageTangleChecks.isEmpty()) {
|
||||
TaskProvider<Task> checkTask = project.getTasks().named(LifecycleBasePlugin.CHECK_TASK_NAME);
|
||||
checkTask.configure((check) -> check.dependsOn(packageTangleChecks));
|
||||
project.getPlugins()
|
||||
.withId("org.jetbrains.kotlin.jvm",
|
||||
(kotlinPlugin) -> registerArchitectureCheck(sourceSet, "kotlin", project).configure((task) -> {
|
||||
task.setClasses(project.files(project.getTasks()
|
||||
.named(sourceSet.getCompileTaskName("kotlin"), KotlinCompileTool.class)
|
||||
.flatMap((compile) -> compile.getDestinationDirectory())));
|
||||
task.getNullMarkedEnabled().set(false);
|
||||
task.getNullMarkedIgnoredPackages().set(Collections.emptySet());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private TaskProvider<ArchitectureCheck> registerArchitectureCheck(SourceSet sourceSet, String language,
|
||||
Project project) {
|
||||
TaskProvider<ArchitectureCheck> checkArchitecture = project.getTasks()
|
||||
.register(
|
||||
"checkArchitecture"
|
||||
+ StringUtils.capitalize(sourceSet.getName() + StringUtils.capitalize(language)),
|
||||
ArchitectureCheck.class, (task) -> {
|
||||
task.getSourceSet().set(sourceSet.getName());
|
||||
task.getCompileClasspath().from(sourceSet.getCompileClasspath());
|
||||
task.getResourcesDirectory().set(sourceSet.getOutput().getResourcesDir());
|
||||
task.dependsOn(sourceSet.getProcessResourcesTaskName());
|
||||
task.setDescription("Checks the architecture of the " + language + " classes of the "
|
||||
+ sourceSet.getName() + " source set.");
|
||||
task.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
|
||||
});
|
||||
project.getTasks()
|
||||
.named(LifecycleBasePlugin.CHECK_TASK_NAME)
|
||||
.configure((check) -> check.dependsOn(checkArchitecture));
|
||||
return checkArchitecture;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -421,6 +421,8 @@ final class ArchitectureRules {
|
|||
return ArchRuleDefinition.members()
|
||||
.that()
|
||||
.areDeclaredInClassesThat(areRegularAutoConfiguration())
|
||||
.and()
|
||||
.areDeclaredInClassesThat(areNotKotlinClasses())
|
||||
.and(areNotDefaultConstructors())
|
||||
.and(areNotConstants())
|
||||
.and(dontOverridePublicMethods())
|
||||
|
|
@ -440,13 +442,18 @@ final class ArchitectureRules {
|
|||
}
|
||||
|
||||
static DescribedPredicate<JavaClass> areRegularAutoConfiguration() {
|
||||
return DescribedPredicate.describe("Regular @AutoConfiguration",
|
||||
return DescribedPredicate.describe("are regular @AutoConfiguration",
|
||||
(javaClass) -> javaClass.isAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
|
||||
&& !javaClass.getName().contains("TestAutoConfiguration") && !javaClass.isAnnotation());
|
||||
}
|
||||
|
||||
static DescribedPredicate<JavaClass> areNotKotlinClasses() {
|
||||
return DescribedPredicate.describe("are not Kotlin classes",
|
||||
(javaClass) -> !javaClass.isAnnotatedWith("kotlin.Metadata"));
|
||||
}
|
||||
|
||||
static DescribedPredicate<JavaClass> areTestAutoConfiguration() {
|
||||
return DescribedPredicate.describe("Test @AutoConfiguration",
|
||||
return DescribedPredicate.describe("are test @AutoConfiguration",
|
||||
(javaClass) -> javaClass.isAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
|
||||
&& javaClass.getName().contains("TestAutoConfiguration") && !javaClass.isAnnotation());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,12 +31,16 @@ import org.springframework.util.ReflectionUtils;
|
|||
/**
|
||||
* Finds all configurations from auto-configurations (either nested configurations or
|
||||
* imported ones) and checks that these classes don't contain public members.
|
||||
* <p>
|
||||
* Kotlin classes are ignored as Kotlin does not have package-private visibility and
|
||||
* {@code internal} isn't a good substitute.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class AutoConfigurationChecker {
|
||||
|
||||
private final DescribedPredicate<JavaClass> isAutoConfiguration = ArchitectureRules.areRegularAutoConfiguration();
|
||||
private final DescribedPredicate<JavaClass> isAutoConfiguration = ArchitectureRules.areRegularAutoConfiguration()
|
||||
.and(ArchitectureRules.areNotKotlinClasses());
|
||||
|
||||
EvaluationResult check(JavaClasses javaClasses) {
|
||||
AutoConfigurations autoConfigurations = new AutoConfigurations();
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ class ArchitectureCheckTests {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "checkArchitecture" + StringUtils.capitalize(this.sourceSetName);
|
||||
return "checkArchitecture" + StringUtils.capitalize(this.sourceSetName) + "Java";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,41 +207,20 @@ This file will not be packaged in your uber jar or your container.
|
|||
[[howto.data-initialization.migration-tool.liquibase-tests]]
|
||||
=== Use Liquibase for Test-only Migrations
|
||||
|
||||
If you want to create Liquibase migrations which populate your test database, you have to create a test changelog which also includes the production changelog.
|
||||
If you want to create Liquibase migrations which populate your test database, you can leverage https://docs.liquibase.com/reference-guide/changelog-attributes/what-are-contexts[Liquibase contexts].
|
||||
See also the related https://www.liquibase.com/blog/contexts-vs-labels[blog post].
|
||||
|
||||
First, you need to configure Liquibase to use a different changelog when running the tests.
|
||||
One way to do this is to create a Spring Boot `test` profile and put the Liquibase properties in there.
|
||||
For that, create a file named `src/test/resources/application-test.properties` and put the following property in there:
|
||||
In practical terms, this translates into adding a `context:@test` attribute to changesets containing test data, for example:
|
||||
|
||||
[configprops,yaml]
|
||||
[source,sql]
|
||||
----
|
||||
spring:
|
||||
liquibase:
|
||||
change-log: "classpath:/db/changelog/db.changelog-test.yaml"
|
||||
--liquibase formatted sql
|
||||
|
||||
--changeset alice:1 context:@test
|
||||
insert into project (id, name) values (1, 'Spring Boot');
|
||||
----
|
||||
|
||||
This configures Liquibase to use a different changelog when running in the `test` profile.
|
||||
|
||||
Now create the changelog file at `src/test/resources/db/changelog/db.changelog-test.yaml`:
|
||||
|
||||
[source,yaml]
|
||||
----
|
||||
databaseChangeLog:
|
||||
- include:
|
||||
file: classpath:/db/changelog/db.changelog-master.yaml
|
||||
- changeSet:
|
||||
runOrder: "last"
|
||||
id: "test"
|
||||
changes:
|
||||
# Insert your changes here
|
||||
----
|
||||
|
||||
This changelog will be used when the tests are run and it will not be packaged in your uber jar or your container.
|
||||
It includes the production changelog and then declares a new changeset, whose `runOrder: last` setting specifies that it runs after all the production changesets have been run.
|
||||
You can now use for example the https://docs.liquibase.com/change-types/insert.html[insert changeset] to insert data or the https://docs.liquibase.com/change-types/sql.html[sql changeset] to execute SQL directly.
|
||||
|
||||
The last thing to do is to configure Spring Boot to activate the `test` profile when running tests.
|
||||
To do this, you can add the `@ActiveProfiles("test")` annotation to your javadoc:org.springframework.boot.test.context.SpringBootTest[format=annotation] annotated test classes.
|
||||
And using `spring.liquibase.contexts=test` in environments where you would like changesets containing test data to be applied.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -142,10 +142,7 @@ spring:
|
|||
Caches can be created on startup by setting the configprop:spring.cache.cache-names[] property.
|
||||
If a custom javadoc:org.infinispan.configuration.cache.ConfigurationBuilder[] bean is defined, it is used to customize the caches.
|
||||
|
||||
To be compatible with Spring Boot's Jakarta EE 9 baseline, Infinispan's `-jakarta` modules must be used.
|
||||
For every module with a `-jakarta` variant, the variant must be used in place of the standard module.
|
||||
For example, `infinispan-core-jakarta` and `infinispan-commons-jakarta` must be used in place of `infinispan-core` and `infinispan-commons` respectively.
|
||||
|
||||
For more details, see https://infinispan.org/docs/stable/titles/spring/spring.html[the documentation].
|
||||
|
||||
|
||||
[[io.caching.provider.couchbase]]
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ public final class MyAutoConfiguration {
|
|||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(SomeService.class)
|
||||
public static class SomeServiceConfiguration {
|
||||
static class SomeServiceConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SomeService someService() {
|
||||
SomeService someService() {
|
||||
return new SomeService();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package org.springframework.boot.docs.features.developingautoconfiguration.conditionannotations.beanconditions
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfiguration
|
||||
class MyAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@
|
|||
|
||||
package org.springframework.boot.docs.features.developingautoconfiguration.conditionannotations.classconditions
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfiguration
|
||||
// Some conditions ...
|
||||
class MyAutoConfiguration {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version=4.0.0-SNAPSHOT
|
||||
version=4.0.1-SNAPSHOT
|
||||
latestVersion=true
|
||||
spring.build-type=oss
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ dependencies {
|
|||
}
|
||||
|
||||
tasks.configureEach {
|
||||
if ("checkArchitectureMain".equals(it.name)) {
|
||||
if ("checkArchitectureMainJava".equals(it.name)) {
|
||||
prohibitObjectsRequireNonNull = false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,24 @@
|
|||
"description": "Whether to create an AmqpAdmin bean.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.rabbitmq.listener.direct.retry.max-attempts",
|
||||
"type": "java.lang.Long",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "spring.rabbitmq.listener.direct.retry.max-retries",
|
||||
"since": "4.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.rabbitmq.listener.simple.retry.max-attempts",
|
||||
"type": "java.lang.Long",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "spring.rabbitmq.listener.simple.retry.max-retries",
|
||||
"since": "4.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.rabbitmq.listener.simple.transaction-size",
|
||||
"type": "java.lang.Integer",
|
||||
|
|
@ -37,6 +55,15 @@
|
|||
"level": "error",
|
||||
"since": "2.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "spring.rabbitmq.template.retry.max-attempts",
|
||||
"type": "java.lang.Long",
|
||||
"deprecation": {
|
||||
"level": "error",
|
||||
"replacement": "spring.rabbitmq.template.retry.max-retries",
|
||||
"since": "4.0.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue