Migrate to Antora
Closes gh-33766
This commit is contained in:
@@ -17,7 +17,7 @@ def versions = [:]
|
||||
new File(projectDir.parentFile, "gradle.properties").withInputStream {
|
||||
def properties = new Properties()
|
||||
properties.load(it)
|
||||
["assertj", "commonsCodec", "hamcrest", "junitJupiter", "kotlin", "maven"].each {
|
||||
["assertj", "commonsCodec", "hamcrest", "junitJupiter", "kotlin", "maven", "snakeYaml"].each {
|
||||
versions[it] = properties[it + "Version"]
|
||||
}
|
||||
}
|
||||
@@ -42,20 +42,23 @@ dependencies {
|
||||
implementation(platform("org.springframework:spring-framework-bom:${versions.springFramework}"))
|
||||
implementation("com.diffplug.gradle:goomph:3.37.2")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:${versions.jackson}")
|
||||
implementation("com.github.node-gradle:gradle-node-plugin:3.5.1")
|
||||
implementation("com.gradle:gradle-enterprise-gradle-plugin:3.12.1")
|
||||
implementation("com.tngtech.archunit:archunit:1.0.0")
|
||||
implementation("commons-codec:commons-codec:${versions.commonsCodec}")
|
||||
implementation("de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0")
|
||||
implementation("io.spring.gradle.antora:spring-antora-plugin:0.0.1")
|
||||
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}")
|
||||
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
|
||||
implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")
|
||||
implementation("org.apache.maven:maven-embedder:${versions.maven}")
|
||||
implementation("org.asciidoctor:asciidoctor-gradle-jvm:3.3.2")
|
||||
implementation("org.antora:gradle-antora-plugin:1.0.0")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:${versions.kotlin}")
|
||||
implementation("org.springframework:spring-context")
|
||||
implementation("org.springframework:spring-core")
|
||||
implementation("org.springframework:spring-web")
|
||||
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
|
||||
implementation("org.yaml:snakeyaml:${versions.snakeYaml}")
|
||||
|
||||
testImplementation("org.assertj:assertj-core:${versions.assertj}")
|
||||
testImplementation("org.hamcrest:hamcrest:${versions.hamcrest}")
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2023-2024 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.github.gradle.node.NodeExtension;
|
||||
import io.spring.gradle.antora.GenerateAntoraYmlPlugin;
|
||||
import io.spring.gradle.antora.GenerateAntoraYmlTask;
|
||||
import org.antora.gradle.AntoraExtension;
|
||||
import org.antora.gradle.AntoraPlugin;
|
||||
import org.antora.gradle.AntoraTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.RegularFile;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.logging.LogLevel;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
|
||||
import org.springframework.boot.build.antora.AntoraAsciidocAttributes;
|
||||
import org.springframework.boot.build.antora.Extensions;
|
||||
import org.springframework.boot.build.antora.GenerateAntoraPlaybook;
|
||||
import org.springframework.boot.build.bom.BomExtension;
|
||||
import org.springframework.boot.build.constraints.ExtractVersionConstraints;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Conventions that are applied in the presence of the {@link AntoraPlugin} and
|
||||
* {@link GenerateAntoraYmlPlugin}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AntoraConventions {
|
||||
|
||||
private static final String DEPENDENCIES_PATH = ":spring-boot-project:spring-boot-dependencies";
|
||||
|
||||
private static final String ANTORA_VERSION = "3.2.0-alpha.4";
|
||||
|
||||
private static final String ANTORA_SOURCE_DIR = "src/docs/antora";
|
||||
|
||||
private static final List<String> NAV_FILES = List.of("nav.adoc", "local-nav.adoc");
|
||||
|
||||
void apply(Project project) {
|
||||
project.getPlugins().withType(AntoraPlugin.class, (antoraPlugin) -> apply(project, antoraPlugin));
|
||||
}
|
||||
|
||||
private void apply(Project project, AntoraPlugin antoraPlugin) {
|
||||
ExtractVersionConstraints dependencyVersionsTask = addDependencyVersionsTask(project);
|
||||
project.getPlugins().apply(GenerateAntoraYmlPlugin.class);
|
||||
TaskContainer tasks = project.getTasks();
|
||||
GenerateAntoraPlaybook generateAntoraPlaybookTask = tasks.create("generateAntoraPlaybook",
|
||||
GenerateAntoraPlaybook.class);
|
||||
tasks.withType(GenerateAntoraYmlTask.class, (generateAntoraYmlTask) -> configureGenerateAntoraYmlTask(project,
|
||||
generateAntoraYmlTask, dependencyVersionsTask));
|
||||
tasks.withType(AntoraTask.class,
|
||||
(antoraTask) -> configureAntoraTask(project, antoraTask, generateAntoraPlaybookTask));
|
||||
project.getExtensions().configure(AntoraExtension.class, (antoraExtension) -> {
|
||||
RegularFileProperty outputFile = generateAntoraPlaybookTask.getOutputFile();
|
||||
configureAntoraExtension(project, antoraExtension, outputFile);
|
||||
});
|
||||
project.getExtensions()
|
||||
.configure(NodeExtension.class, (nodeExtension) -> configureNodeExtension(project, nodeExtension));
|
||||
}
|
||||
|
||||
private ExtractVersionConstraints addDependencyVersionsTask(Project project) {
|
||||
return project.getTasks()
|
||||
.create("dependencyVersions", ExtractVersionConstraints.class,
|
||||
(task) -> task.enforcedPlatform(DEPENDENCIES_PATH));
|
||||
}
|
||||
|
||||
private void configureGenerateAntoraYmlTask(Project project, GenerateAntoraYmlTask generateAntoraYmlTask,
|
||||
ExtractVersionConstraints dependencyVersionsTask) {
|
||||
generateAntoraYmlTask.getOutputs().doNotCacheIf("getAsciidocAttributes() changes output", (task) -> true);
|
||||
generateAntoraYmlTask.dependsOn(dependencyVersionsTask);
|
||||
generateAntoraYmlTask.setProperty("componentName", "spring-boot");
|
||||
generateAntoraYmlTask.setProperty("outputFile",
|
||||
new File(project.getBuildDir(), "generated/docs/antora-yml/antora.yml"));
|
||||
generateAntoraYmlTask.setProperty("yml", getDefaultYml(project));
|
||||
generateAntoraYmlTask.doFirst((task) -> generateAntoraYmlTask.getAsciidocAttributes()
|
||||
.putAll(project.provider(() -> getAsciidocAttributes(project, dependencyVersionsTask))));
|
||||
}
|
||||
|
||||
private Map<String, ?> getDefaultYml(Project project) {
|
||||
String navFile = null;
|
||||
for (String candidate : NAV_FILES) {
|
||||
if (project.file(ANTORA_SOURCE_DIR + "/" + candidate).exists()) {
|
||||
Assert.state(navFile == null, "Multiple nav files found");
|
||||
navFile = candidate;
|
||||
}
|
||||
}
|
||||
Map<String, Object> defaultYml = new LinkedHashMap<>();
|
||||
defaultYml.put("title", "Spring Boot");
|
||||
if (navFile != null) {
|
||||
defaultYml.put("nav", List.of(navFile));
|
||||
}
|
||||
return defaultYml;
|
||||
}
|
||||
|
||||
private Map<String, String> getAsciidocAttributes(Project project,
|
||||
ExtractVersionConstraints dependencyVersionsTask) {
|
||||
BomExtension bom = (BomExtension) project.project(DEPENDENCIES_PATH).getExtensions().getByName("bom");
|
||||
Map<String, String> dependencyVersions = dependencyVersionsTask.getVersionConstraints();
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes(project, bom, dependencyVersions);
|
||||
return attributes.get();
|
||||
}
|
||||
|
||||
private void configureAntoraTask(Project project, AntoraTask antoraTask,
|
||||
GenerateAntoraPlaybook generateAntoraPlaybookTask) {
|
||||
antoraTask.setGroup("Documentation");
|
||||
antoraTask.getDependsOn().add(generateAntoraPlaybookTask);
|
||||
project.getPlugins()
|
||||
.withType(JavaBasePlugin.class,
|
||||
(javaBasePlugin) -> project.getTasks()
|
||||
.getByName(JavaBasePlugin.CHECK_TASK_NAME)
|
||||
.dependsOn(antoraTask));
|
||||
}
|
||||
|
||||
private void configureAntoraExtension(Project project, AntoraExtension antoraExtension,
|
||||
Provider<RegularFile> playbook) {
|
||||
antoraExtension.getVersion().convention(ANTORA_VERSION);
|
||||
antoraExtension.getPackages().convention(Extensions.packages());
|
||||
antoraExtension.getPlaybook().convention(playbook.map(RegularFile::getAsFile));
|
||||
if (project.getGradle().getStartParameter().getLogLevel() != LogLevel.DEBUG) {
|
||||
antoraExtension.getOptions().add("--quiet");
|
||||
}
|
||||
else {
|
||||
antoraExtension.getOptions().addAll("--log-level", "all");
|
||||
}
|
||||
}
|
||||
|
||||
private void configureNodeExtension(Project project, NodeExtension nodeExtension) {
|
||||
File buildDir = project.getBuildDir();
|
||||
nodeExtension.getWorkDir().set(buildDir.toPath().resolve(".gradle/nodejs").toFile());
|
||||
nodeExtension.getNpmWorkDir().set(buildDir.toPath().resolve(".gradle/npm").toFile());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask;
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorJExtension;
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorJPlugin;
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorTask;
|
||||
import org.gradle.api.JavaVersion;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.Sync;
|
||||
|
||||
import org.springframework.boot.build.artifacts.ArtifactRelease;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Conventions that are applied in the presence of the {@link AsciidoctorJPlugin}. When
|
||||
* the plugin is applied:
|
||||
*
|
||||
* <ul>
|
||||
* <li>All warnings are made fatal.
|
||||
* <li>The version of AsciidoctorJ is upgraded to 2.4.3.
|
||||
* <li>An {@code asciidoctorExtensions} configuration is created.
|
||||
* <li>For each {@link AsciidoctorTask} (HTML only):
|
||||
* <ul>
|
||||
* <li>A task is created to sync the documentation resources to its output directory.
|
||||
* <li>{@code doctype} {@link AsciidoctorTask#options(Map) option} is configured.
|
||||
* <li>The {@code backend} is configured.
|
||||
* </ul>
|
||||
* <li>For each {@link AbstractAsciidoctorTask} (HTML and PDF):
|
||||
* <ul>
|
||||
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured to enable
|
||||
* warnings for references to missing attributes, the GitHub tag, the Artifactory repo for
|
||||
* the current version, etc.
|
||||
* <li>{@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()}
|
||||
* is enabled.
|
||||
* <li>{@code asciidoctorExtensions} is added to the task's configurations.
|
||||
* </ul>
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class AsciidoctorConventions {
|
||||
|
||||
private static final String ASCIIDOCTORJ_VERSION = "2.4.3";
|
||||
|
||||
private static final String EXTENSIONS_CONFIGURATION_NAME = "asciidoctorExtensions";
|
||||
|
||||
void apply(Project project) {
|
||||
project.getPlugins().withType(AsciidoctorJPlugin.class, (asciidoctorPlugin) -> {
|
||||
makeAllWarningsFatal(project);
|
||||
upgradeAsciidoctorJVersion(project);
|
||||
createAsciidoctorExtensionsConfiguration(project);
|
||||
project.getTasks()
|
||||
.withType(AbstractAsciidoctorTask.class,
|
||||
(asciidoctorTask) -> configureAsciidoctorTask(project, asciidoctorTask));
|
||||
});
|
||||
}
|
||||
|
||||
private void makeAllWarningsFatal(Project project) {
|
||||
project.getExtensions().getByType(AsciidoctorJExtension.class).fatalWarnings(".*");
|
||||
}
|
||||
|
||||
private void upgradeAsciidoctorJVersion(Project project) {
|
||||
project.getExtensions().getByType(AsciidoctorJExtension.class).setVersion(ASCIIDOCTORJ_VERSION);
|
||||
}
|
||||
|
||||
private void createAsciidoctorExtensionsConfiguration(Project project) {
|
||||
project.getConfigurations().create(EXTENSIONS_CONFIGURATION_NAME, (configuration) -> {
|
||||
project.getConfigurations()
|
||||
.matching((candidate) -> "dependencyManagement".equals(candidate.getName()))
|
||||
.all(configuration::extendsFrom);
|
||||
configuration.getDependencies()
|
||||
.add(project.getDependencies()
|
||||
.create("io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.5"));
|
||||
configuration.getDependencies()
|
||||
.add(project.getDependencies().create("org.asciidoctor:asciidoctorj-pdf:1.5.3"));
|
||||
});
|
||||
}
|
||||
|
||||
private void configureAsciidoctorTask(Project project, AbstractAsciidoctorTask asciidoctorTask) {
|
||||
asciidoctorTask.configurations(EXTENSIONS_CONFIGURATION_NAME);
|
||||
configureCommonAttributes(project, asciidoctorTask);
|
||||
configureOptions(asciidoctorTask);
|
||||
configureForkOptions(asciidoctorTask);
|
||||
asciidoctorTask.baseDirFollowsSourceDir();
|
||||
createSyncDocumentationSourceTask(project, asciidoctorTask);
|
||||
if (asciidoctorTask instanceof AsciidoctorTask task) {
|
||||
boolean pdf = task.getName().toLowerCase().contains("pdf");
|
||||
String backend = (!pdf) ? "spring-html" : "spring-pdf";
|
||||
task.outputOptions((outputOptions) -> outputOptions.backends(backend));
|
||||
}
|
||||
}
|
||||
|
||||
private void configureCommonAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
|
||||
ArtifactRelease artifacts = ArtifactRelease.forProject(project);
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("attribute-missing", "warn");
|
||||
attributes.put("github-tag", determineGitHubTag(project));
|
||||
attributes.put("artifact-release-type", artifacts.getType());
|
||||
attributes.put("artifact-download-repo", artifacts.getDownloadRepo());
|
||||
attributes.put("revnumber", null);
|
||||
asciidoctorTask.attributes(attributes);
|
||||
}
|
||||
|
||||
// See https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/597
|
||||
private void configureForkOptions(AbstractAsciidoctorTask asciidoctorTask) {
|
||||
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16)) {
|
||||
asciidoctorTask.forkOptions((options) -> options.jvmArgs("--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED",
|
||||
"--add-opens", "java.base/java.io=ALL-UNNAMED"));
|
||||
}
|
||||
}
|
||||
|
||||
private String determineGitHubTag(Project project) {
|
||||
String version = "v" + project.getVersion();
|
||||
return (version.endsWith("-SNAPSHOT")) ? "main" : version;
|
||||
}
|
||||
|
||||
private void configureOptions(AbstractAsciidoctorTask asciidoctorTask) {
|
||||
asciidoctorTask.options(Collections.singletonMap("doctype", "book"));
|
||||
}
|
||||
|
||||
private Sync createSyncDocumentationSourceTask(Project project, AbstractAsciidoctorTask asciidoctorTask) {
|
||||
Sync syncDocumentationSource = project.getTasks()
|
||||
.create("syncDocumentationSourceFor" + StringUtils.capitalize(asciidoctorTask.getName()), Sync.class);
|
||||
File syncedSource = new File(project.getBuildDir(), "docs/src/" + asciidoctorTask.getName());
|
||||
syncDocumentationSource.setDestinationDir(syncedSource);
|
||||
syncDocumentationSource.from("src/docs/");
|
||||
asciidoctorTask.dependsOn(syncDocumentationSource);
|
||||
asciidoctorTask.getInputs()
|
||||
.dir(syncedSource)
|
||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
.withPropertyName("synced source");
|
||||
asciidoctorTask.setSourceDir(project.relativePath(new File(syncedSource, "asciidoc/")));
|
||||
return syncDocumentationSource;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.boot.build;
|
||||
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorJPlugin;
|
||||
import org.antora.gradle.AntoraPlugin;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
@@ -32,8 +32,8 @@ import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
|
||||
* When the {@link MavenPublishPlugin} is applied, the conventions in
|
||||
* {@link MavenPublishingConventions} are applied.
|
||||
*
|
||||
* When the {@link AsciidoctorJPlugin} is applied, the conventions in
|
||||
* {@link AsciidoctorConventions} are applied.
|
||||
* When the {@link AntoraPlugin} is applied, the conventions in {@link AntoraConventions}
|
||||
* are applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Christoph Dreis
|
||||
@@ -46,7 +46,7 @@ public class ConventionsPlugin implements Plugin<Project> {
|
||||
new NoHttpConventions().apply(project);
|
||||
new JavaConventions().apply(project);
|
||||
new MavenPublishingConventions().apply(project);
|
||||
new AsciidoctorConventions().apply(project);
|
||||
new AntoraConventions().apply(project);
|
||||
new KotlinConventions().apply(project);
|
||||
new WarConventions().apply(project);
|
||||
new EclipseConventions().apply(project);
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.antora;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import org.springframework.boot.build.artifacts.ArtifactRelease;
|
||||
import org.springframework.boot.build.bom.BomExtension;
|
||||
import org.springframework.boot.build.bom.Library;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Generates Asciidoctor attributes for use with Antora.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AntoraAsciidocAttributes {
|
||||
|
||||
private static final String DASH_SNAPSHOT = "-SNAPSHOT";
|
||||
|
||||
private final String version;
|
||||
|
||||
private final boolean latestVersion;
|
||||
|
||||
private final ArtifactRelease artifactRelease;
|
||||
|
||||
private final List<Library> libraries;
|
||||
|
||||
private final Map<String, String> dependencyVersions;
|
||||
|
||||
private final Map<String, ?> projectProperties;
|
||||
|
||||
public AntoraAsciidocAttributes(Project project, BomExtension dependencyBom,
|
||||
Map<String, String> dependencyVersions) {
|
||||
this.version = String.valueOf(project.getVersion());
|
||||
this.latestVersion = Boolean.valueOf(String.valueOf(project.findProperty("latestVersion")));
|
||||
this.artifactRelease = ArtifactRelease.forProject(project);
|
||||
this.libraries = dependencyBom.getLibraries();
|
||||
this.dependencyVersions = dependencyVersions;
|
||||
this.projectProperties = project.getProperties();
|
||||
}
|
||||
|
||||
AntoraAsciidocAttributes(String version, boolean latestVersion, List<Library> libraries,
|
||||
Map<String, String> dependencyVersions, Map<String, ?> projectProperties) {
|
||||
this.version = version;
|
||||
this.latestVersion = latestVersion;
|
||||
this.artifactRelease = ArtifactRelease.forVersion(version);
|
||||
this.libraries = (libraries != null) ? libraries : Collections.emptyList();
|
||||
this.dependencyVersions = (dependencyVersions != null) ? dependencyVersions : Collections.emptyMap();
|
||||
this.projectProperties = (projectProperties != null) ? projectProperties : Collections.emptyMap();
|
||||
}
|
||||
|
||||
public Map<String, String> get() {
|
||||
Map<String, String> attributes = new LinkedHashMap<>();
|
||||
addGitHubAttributes(attributes);
|
||||
addVersionAttributes(attributes);
|
||||
addUrlArtifactRepository(attributes);
|
||||
addUrlLibraryLinkAttributes(attributes);
|
||||
addPropertyAttributes(attributes);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private void addGitHubAttributes(Map<String, String> attributes) {
|
||||
attributes.put("github-repo", "spring-projects/spring-boot");
|
||||
attributes.put("github-ref", determineGitHubRef());
|
||||
}
|
||||
|
||||
private String determineGitHubRef() {
|
||||
int snapshotIndex = this.version.lastIndexOf(DASH_SNAPSHOT);
|
||||
if (snapshotIndex == -1) {
|
||||
return "v" + this.version;
|
||||
}
|
||||
if (this.latestVersion) {
|
||||
return "main";
|
||||
}
|
||||
String versionRoot = this.version.substring(0, snapshotIndex);
|
||||
int lastDot = versionRoot.lastIndexOf('.');
|
||||
return versionRoot.substring(0, lastDot) + ".x";
|
||||
}
|
||||
|
||||
private void addVersionAttributes(Map<String, String> attributes) {
|
||||
this.libraries.forEach((library) -> {
|
||||
String name = "version-" + library.getLinkRootName();
|
||||
String value = library.getVersion().toString();
|
||||
attributes.put(name, value);
|
||||
});
|
||||
attributes.put("version-native-build-tools", (String) this.projectProperties.get("nativeBuildToolsVersion"));
|
||||
attributes.put("version-graal", (String) this.projectProperties.get("graalVersion"));
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-commons");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-couchbase");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-elasticsearch");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-jdbc");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-jpa");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-mongodb");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-neo4j");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-r2dbc");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-rest", "spring-data-rest-core");
|
||||
}
|
||||
|
||||
private void addSpringDataDependencyVersion(Map<String, String> attributes, String artifactId) {
|
||||
addSpringDataDependencyVersion(attributes, artifactId, artifactId);
|
||||
}
|
||||
|
||||
private void addSpringDataDependencyVersion(Map<String, String> attributes, String name, String artifactId) {
|
||||
String version = this.dependencyVersions.get("org.springframework.data:" + artifactId);
|
||||
Assert.notNull(version, () -> "No version found for Spring Data artificat " + artifactId);
|
||||
attributes.put("version-" + name, version);
|
||||
}
|
||||
|
||||
private void addUrlArtifactRepository(Map<String, String> attributes) {
|
||||
attributes.put("url-artifact-repository", this.artifactRelease.getDownloadRepo());
|
||||
}
|
||||
|
||||
private void addUrlLibraryLinkAttributes(Map<String, String> attributes) {
|
||||
this.libraries.forEach((library) -> {
|
||||
String prefix = "url-" + library.getLinkRootName() + "-";
|
||||
library.getLinks().forEach((name, link) -> attributes.put(prefix + name, link));
|
||||
});
|
||||
}
|
||||
|
||||
private void addPropertyAttributes(Map<String, String> attributes) {
|
||||
Properties properties = new Properties() {
|
||||
|
||||
@Override
|
||||
public synchronized Object put(Object key, Object value) {
|
||||
// Put directly because order is important for us
|
||||
return attributes.put(key.toString(), value.toString());
|
||||
}
|
||||
|
||||
};
|
||||
try (InputStream in = getClass().getResourceAsStream("antora-asciidoc-attributes.properties")) {
|
||||
properties.load(in);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.antora;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Antora and Asciidoc extensions used by Spring Boot.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public final class Extensions {
|
||||
|
||||
private static final String ROOT_COMPONENT_EXTENSION = "@springio/antora-extensions/root-component-extension";
|
||||
|
||||
private static final List<Extension> antora;
|
||||
static {
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
extensions.add(new Extension("@springio/antora-extensions", "1.8.2", ROOT_COMPONENT_EXTENSION,
|
||||
"@springio/antora-extensions/static-page-extension"));
|
||||
extensions.add(new Extension("@springio/antora-xref-extension", "1.0.0-alpha.3"));
|
||||
extensions.add(new Extension("@springio/antora-zip-contents-collector-extension", "1.0.0-alpha.2"));
|
||||
antora = List.copyOf(extensions);
|
||||
}
|
||||
|
||||
private static final List<Extension> asciidoc;
|
||||
static {
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
extensions.add(new Extension("@asciidoctor/tabs", "1.0.0-beta.6"));
|
||||
extensions
|
||||
.add(new Extension("@springio/asciidoctor-extensions", "1.0.0-alpha.10", "@springio/asciidoctor-extensions",
|
||||
"@springio/asciidoctor-extensions/configuration-properties-extension",
|
||||
"@springio/asciidoctor-extensions/section-ids-extension"));
|
||||
asciidoc = List.copyOf(extensions);
|
||||
}
|
||||
|
||||
private static final Map<String, String> localOverrides = Collections.emptyMap();
|
||||
|
||||
private Extensions() {
|
||||
}
|
||||
|
||||
public static Map<String, String> packages() {
|
||||
Map<String, String> packages = new TreeMap<>();
|
||||
antora.stream().forEach((extension) -> packages.put(extension.name(), extension.version()));
|
||||
asciidoc.stream().forEach((extension) -> packages.put(extension.name(), extension.version()));
|
||||
return Collections.unmodifiableMap(packages);
|
||||
}
|
||||
|
||||
static List<Map<String, Object>> antora(Consumer<AntoraExtensionsConfiguration> extensions) {
|
||||
AntoraExtensionsConfiguration result = new AntoraExtensionsConfiguration(
|
||||
antora.stream().flatMap(Extension::names).sorted().toList());
|
||||
extensions.accept(result);
|
||||
return result.config();
|
||||
}
|
||||
|
||||
static List<String> asciidoc() {
|
||||
return asciidoc.stream().flatMap(Extension::names).sorted().toList();
|
||||
}
|
||||
|
||||
private record Extension(String name, String version, String... includeNames) {
|
||||
|
||||
Stream<String> names() {
|
||||
return (this.includeNames.length != 0) ? Arrays.stream(this.includeNames) : Stream.of(this.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class AntoraExtensionsConfiguration {
|
||||
|
||||
private Map<String, Map<String, Object>> extensions = new TreeMap<>();
|
||||
|
||||
private AntoraExtensionsConfiguration(List<String> names) {
|
||||
names.forEach((name) -> this.extensions.put(name, null));
|
||||
}
|
||||
|
||||
void xref(Consumer<Xref> xref) {
|
||||
xref.accept(new Xref());
|
||||
}
|
||||
|
||||
void zipContentsCollector(Consumer<ZipContentsCollector> zipContentsCollector) {
|
||||
zipContentsCollector.accept(new ZipContentsCollector());
|
||||
}
|
||||
|
||||
void rootComponent(Consumer<RootComponent> rootComponent) {
|
||||
rootComponent.accept(new RootComponent());
|
||||
}
|
||||
|
||||
List<Map<String, Object>> config() {
|
||||
List<Map<String, Object>> config = new ArrayList<>();
|
||||
Map<String, Map<String, Object>> orderedExtensions = new LinkedHashMap<>(this.extensions);
|
||||
// The root component extension must be last
|
||||
Map<String, Object> rootComponentConfig = orderedExtensions.remove(ROOT_COMPONENT_EXTENSION);
|
||||
orderedExtensions.put(ROOT_COMPONENT_EXTENSION, rootComponentConfig);
|
||||
orderedExtensions.forEach((name, customizations) -> {
|
||||
Map<String, Object> extensionConfig = new LinkedHashMap<>();
|
||||
extensionConfig.put("require", localOverrides.getOrDefault(name, name));
|
||||
if (customizations != null) {
|
||||
extensionConfig.putAll(customizations);
|
||||
}
|
||||
config.add(extensionConfig);
|
||||
});
|
||||
return List.copyOf(config);
|
||||
}
|
||||
|
||||
abstract class Customizer {
|
||||
|
||||
private final String name;
|
||||
|
||||
Customizer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void customize(String key, Object value) {
|
||||
AntoraExtensionsConfiguration.this.extensions.computeIfAbsent(this.name, (name) -> new TreeMap<>())
|
||||
.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Xref extends Customizer {
|
||||
|
||||
Xref() {
|
||||
super("@springio/antora-xref-extension");
|
||||
}
|
||||
|
||||
void stub(List<String> stub) {
|
||||
if (stub != null && !stub.isEmpty()) {
|
||||
customize("stub", stub);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ZipContentsCollector extends Customizer {
|
||||
|
||||
ZipContentsCollector() {
|
||||
super("@springio/antora-zip-contents-collector-extension");
|
||||
}
|
||||
|
||||
void versionFile(String versionFile) {
|
||||
customize("version_file", versionFile);
|
||||
}
|
||||
|
||||
void locations(Path... locations) {
|
||||
locations(Arrays.stream(locations).map(Path::toString).toList());
|
||||
}
|
||||
|
||||
private void locations(List<String> locations) {
|
||||
customize("locations", locations);
|
||||
}
|
||||
|
||||
void alwaysInclude(Map<String, String> alwaysInclude) {
|
||||
if (alwaysInclude != null && !alwaysInclude.isEmpty()) {
|
||||
customize("always_include", List.of(new TreeMap<>(alwaysInclude)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RootComponent extends Customizer {
|
||||
|
||||
RootComponent() {
|
||||
super(ROOT_COMPONENT_EXTENSION);
|
||||
}
|
||||
|
||||
void name(String name) {
|
||||
customize("root_component_name", name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.antora;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
/**
|
||||
* Task to generate a local Antora playbook.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class GenerateAntoraPlaybook extends DefaultTask {
|
||||
|
||||
private static final String ANTORA_SOURCE_DIR = "src/docs/antora";
|
||||
|
||||
private static final String GENERATED_DOCS = "build/generated/docs/";
|
||||
|
||||
@OutputFile
|
||||
public abstract RegularFileProperty getOutputFile();
|
||||
|
||||
@Input
|
||||
public abstract Property<String> getContentSourceConfiguration();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract ListProperty<String> getXrefStubs();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract MapProperty<String, String> getAlwaysInclude();
|
||||
|
||||
public GenerateAntoraPlaybook() {
|
||||
setGroup("Documentation");
|
||||
setDescription("Generates an Antora playbook.yml file for local use");
|
||||
getOutputFile().convention(getProject().getLayout()
|
||||
.getBuildDirectory()
|
||||
.file("generated/docs/antora-playbook/antora-playbook.yml"));
|
||||
getContentSourceConfiguration().convention("antoraContent");
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void writePlaybookYml() throws IOException {
|
||||
File file = getOutputFile().get().getAsFile();
|
||||
file.getParentFile().mkdirs();
|
||||
try (FileWriter out = new FileWriter(file)) {
|
||||
createYaml().dump(getData(), out);
|
||||
}
|
||||
}
|
||||
|
||||
@Input
|
||||
final Map<String, Object> getData() throws IOException {
|
||||
Map<String, Object> data = loadPlaybookTemplate();
|
||||
addExtensions(data);
|
||||
addSources(data);
|
||||
addDir(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> loadPlaybookTemplate() throws IOException {
|
||||
try (InputStream resource = getClass().getResourceAsStream("antora-playbook-template.yml")) {
|
||||
return createYaml().loadAs(resource, LinkedHashMap.class);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addExtensions(Map<String, Object> data) {
|
||||
Map<String, Object> antora = (Map<String, Object>) data.get("antora");
|
||||
antora.put("extensions", Extensions.antora((extensions) -> {
|
||||
extensions.xref((xref) -> xref.stub(getXrefStubs().getOrElse(Collections.emptyList())));
|
||||
extensions.zipContentsCollector((zipContentsCollector) -> {
|
||||
zipContentsCollector.versionFile("gradle.properties");
|
||||
String locationName = getProject().getName() + "-${version}-${name}-${classifier}.zip";
|
||||
Path antoraContent = getRelativeProjectPath()
|
||||
.resolve(GENERATED_DOCS + "antora-content/" + locationName);
|
||||
Path antoraDepenencies = getRelativeProjectPath()
|
||||
.resolve(GENERATED_DOCS + "antora-dependencies-content/" + locationName);
|
||||
zipContentsCollector.locations(antoraContent, antoraDepenencies);
|
||||
zipContentsCollector.alwaysInclude(getAlwaysInclude().getOrNull());
|
||||
});
|
||||
extensions.rootComponent((rootComponent) -> rootComponent.name("spring-boot"));
|
||||
}));
|
||||
Map<String, Object> asciidoc = (Map<String, Object>) data.get("asciidoc");
|
||||
asciidoc.put("extensions", Extensions.asciidoc());
|
||||
}
|
||||
|
||||
private void addSources(Map<String, Object> data) {
|
||||
List<Map<String, Object>> contentSources = getList(data, "content.sources");
|
||||
contentSources.add(createContentSource());
|
||||
}
|
||||
|
||||
private Map<String, Object> createContentSource() {
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
Path playbookPath = getOutputFile().get().getAsFile().toPath().getParent();
|
||||
Path antoraSrc = getProjectPath(getProject()).resolve(ANTORA_SOURCE_DIR);
|
||||
StringBuilder url = new StringBuilder(".");
|
||||
relativizeFromRootProject(playbookPath).normalize().forEach((path) -> url.append("/.."));
|
||||
source.put("url", url.toString());
|
||||
source.put("branches", "HEAD");
|
||||
source.put("version", getProject().getVersion().toString());
|
||||
Set<String> startPaths = new LinkedHashSet<>();
|
||||
addAntoraContentStartPaths(startPaths);
|
||||
startPaths.add(relativizeFromRootProject(antoraSrc).toString());
|
||||
source.put("start_paths", startPaths.stream().toList());
|
||||
return source;
|
||||
}
|
||||
|
||||
private void addAntoraContentStartPaths(Set<String> startPaths) {
|
||||
Configuration configuration = getProject().getConfigurations().findByName("antoraContent");
|
||||
if (configuration != null) {
|
||||
for (ProjectDependency dependency : configuration.getAllDependencies().withType(ProjectDependency.class)) {
|
||||
Path path = dependency.getDependencyProject().getProjectDir().toPath();
|
||||
startPaths.add(relativizeFromRootProject(path).resolve(ANTORA_SOURCE_DIR).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDir(Map<String, Object> data) {
|
||||
Path playbookDir = toRealPath(getOutputFile().get().getAsFile().toPath()).getParent();
|
||||
Path outputDir = toRealPath(getProject().getBuildDir().toPath().resolve("site"));
|
||||
data.put("output", Map.of("dir", "./" + playbookDir.relativize(outputDir).toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> getList(Map<String, Object> data, String location) {
|
||||
return (List<T>) get(data, location);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object get(Map<String, Object> data, String location) {
|
||||
Object result = data;
|
||||
String[] keys = location.split("\\.");
|
||||
for (String key : keys) {
|
||||
result = ((Map<String, Object>) result).get(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Yaml createYaml() {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
options.setPrettyFlow(true);
|
||||
return new Yaml(options);
|
||||
}
|
||||
|
||||
private Path getRelativeProjectPath() {
|
||||
return relativizeFromRootProject(getProjectPath(getProject()));
|
||||
}
|
||||
|
||||
private Path relativizeFromRootProject(Path subPath) {
|
||||
Path rootProjectPath = getProjectPath(getProject().getRootProject());
|
||||
return rootProjectPath.relativize(subPath).normalize();
|
||||
}
|
||||
|
||||
private Path getProjectPath(Project project) {
|
||||
return toRealPath(project.getProjectDir().toPath());
|
||||
}
|
||||
|
||||
private Path toRealPath(Path path) {
|
||||
try {
|
||||
return Files.exists(path) ? path.toRealPath() : path;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -26,24 +26,18 @@ import org.gradle.api.Project;
|
||||
*/
|
||||
public final class ArtifactRelease {
|
||||
|
||||
private static final String SNAPSHOT = "snapshot";
|
||||
|
||||
private static final String MILESTONE = "milestone";
|
||||
|
||||
private static final String RELEASE = "release";
|
||||
|
||||
private static final String SPRING_REPO = "https://repo.spring.io/%s";
|
||||
|
||||
private static final String MAVEN_REPO = "https://repo.maven.apache.org/maven2";
|
||||
|
||||
private final String type;
|
||||
private final Type type;
|
||||
|
||||
private ArtifactRelease(String type) {
|
||||
private ArtifactRelease(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
return this.type.toString().toLowerCase();
|
||||
}
|
||||
|
||||
public String getDownloadRepo() {
|
||||
@@ -51,24 +45,34 @@ public final class ArtifactRelease {
|
||||
}
|
||||
|
||||
public boolean isRelease() {
|
||||
return RELEASE.equals(this.type);
|
||||
return this.type == Type.RELEASE;
|
||||
}
|
||||
|
||||
public static ArtifactRelease forProject(Project project) {
|
||||
return new ArtifactRelease(determineReleaseType(project));
|
||||
return forVersion(project.getVersion().toString());
|
||||
}
|
||||
|
||||
private static String determineReleaseType(Project project) {
|
||||
String version = project.getVersion().toString();
|
||||
int modifierIndex = version.lastIndexOf('-');
|
||||
if (modifierIndex == -1) {
|
||||
return RELEASE;
|
||||
public static ArtifactRelease forVersion(String version) {
|
||||
return new ArtifactRelease(Type.forVersion(version));
|
||||
}
|
||||
|
||||
enum Type {
|
||||
|
||||
SNAPSHOT, MILESTONE, RELEASE;
|
||||
|
||||
static Type forVersion(String version) {
|
||||
int modifierIndex = version.lastIndexOf('-');
|
||||
if (modifierIndex == -1) {
|
||||
return RELEASE;
|
||||
}
|
||||
String type = version.substring(modifierIndex + 1);
|
||||
if (type.startsWith("M") || type.startsWith("RC")) {
|
||||
return MILESTONE;
|
||||
}
|
||||
return SNAPSHOT;
|
||||
|
||||
}
|
||||
String type = version.substring(modifierIndex + 1);
|
||||
if (type.startsWith("M") || type.startsWith("RC")) {
|
||||
return MILESTONE;
|
||||
}
|
||||
return SNAPSHOT;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -89,9 +89,9 @@ public class DocumentAutoConfigurationClasses extends DefaultTask {
|
||||
|
||||
for (AutoConfigurationClass autoConfigurationClass : autoConfigurationClasses.classes) {
|
||||
writer.println();
|
||||
writer.printf("| {spring-boot-code}/spring-boot-project/%s/src/main/java/%s.java[`%s`]%n",
|
||||
writer.printf("| {code-spring-boot}/spring-boot-project/%s/src/main/java/%s.java[`%s`]%n",
|
||||
autoConfigurationClasses.module, autoConfigurationClass.path, autoConfigurationClass.name);
|
||||
writer.printf("| {spring-boot-api}/%s.html[javadoc]%n", autoConfigurationClass.path);
|
||||
writer.printf("| xref:api:java/%s.html[javadoc]%n", autoConfigurationClass.path);
|
||||
}
|
||||
|
||||
writer.println("|===");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -29,6 +29,7 @@ import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.artifacts.ComponentMetadataDetails;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.DependencyConstraint;
|
||||
import org.gradle.api.artifacts.DependencyConstraintMetadata;
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler;
|
||||
@@ -64,10 +65,9 @@ public class ExtractVersionConstraints extends DefaultTask {
|
||||
}
|
||||
|
||||
public void enforcedPlatform(String projectPath) {
|
||||
this.configuration.getDependencies()
|
||||
.add(getProject().getDependencies()
|
||||
.enforcedPlatform(
|
||||
getProject().getDependencies().project(Collections.singletonMap("path", projectPath))));
|
||||
Dependency project = getProject().getDependencies().project(Map.of("path", projectPath));
|
||||
Dependency dependency = getProject().getDependencies().enforcedPlatform(project);
|
||||
this.configuration.getDependencies().add(dependency);
|
||||
this.projectPaths.add(projectPath);
|
||||
}
|
||||
|
||||
@@ -104,9 +104,8 @@ public class ExtractVersionConstraints extends DefaultTask {
|
||||
}
|
||||
|
||||
private void extractVersionProperties(String projectPath) {
|
||||
Object bom = getProject().project(projectPath).getExtensions().getByName("bom");
|
||||
BomExtension bomExtension = (BomExtension) bom;
|
||||
for (Library lib : bomExtension.getLibraries()) {
|
||||
BomExtension bom = (BomExtension) getProject().project(projectPath).getExtensions().getByName("bom");
|
||||
for (Library lib : bom.getLibraries()) {
|
||||
String versionProperty = lib.getVersionProperty();
|
||||
if (versionProperty != null) {
|
||||
this.versionProperties.add(new VersionProperty(lib.getName(), versionProperty));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -102,11 +102,7 @@ class Snippets {
|
||||
|
||||
private void writeAsciidoc(Path outputDirectory, Snippet snippet, Asciidoc asciidoc) throws IOException {
|
||||
String[] parts = (snippet.getAnchor()).split("\\.");
|
||||
Path path = outputDirectory;
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String name = (i < parts.length - 1) ? parts[i] : parts[i] + ".adoc";
|
||||
path = path.resolve(name);
|
||||
}
|
||||
Path path = outputDirectory.resolve(parts[parts.length - 1] + ".adoc");
|
||||
createDirectory(path.getParent());
|
||||
Files.deleteIfExists(path);
|
||||
try (OutputStream outputStream = Files.newOutputStream(path)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -50,7 +50,7 @@ public class DocumentDevtoolsPropertyDefaults extends DefaultTask {
|
||||
this.outputFile = getProject().getObjects().fileProperty();
|
||||
this.outputFile.convention(getProject().getLayout()
|
||||
.getBuildDirectory()
|
||||
.file("docs/generated/using/devtools-property-defaults.adoc"));
|
||||
.file("generated/docs/using/devtools-property-defaults.adoc"));
|
||||
Map<String, String> dependency = new HashMap<>();
|
||||
dependency.put("path", ":spring-boot-project:spring-boot-devtools");
|
||||
dependency.put("configuration", "propertyDefaults");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -92,7 +92,7 @@ public class DocumentPluginGoals extends DefaultTask {
|
||||
writer.println("| Goal | Description");
|
||||
writer.println();
|
||||
for (Mojo mojo : plugin.getMojos()) {
|
||||
writer.printf("| <<%s,%s:%s>>%n", goalSectionId(mojo), plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("| xref:%s[%s:%s]%n", goalSectionId(mojo, false), plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("| %s%n", mojo.getDescription());
|
||||
writer.println();
|
||||
}
|
||||
@@ -102,11 +102,9 @@ public class DocumentPluginGoals extends DefaultTask {
|
||||
|
||||
private void documentMojo(Plugin plugin, Mojo mojo) throws IOException {
|
||||
try (PrintWriter writer = new PrintWriter(new FileWriter(new File(this.outputDir, mojo.getGoal() + ".adoc")))) {
|
||||
String sectionId = goalSectionId(mojo);
|
||||
writer.println();
|
||||
writer.println();
|
||||
String sectionId = goalSectionId(mojo, true);
|
||||
writer.printf("[[%s]]%n", sectionId);
|
||||
writer.printf("= `%s:%s`%n", plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("= `%s:%s`%n%n", plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("`%s:%s:%s`%n", plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion());
|
||||
writer.println();
|
||||
writer.println(mojo.getDescription());
|
||||
@@ -114,37 +112,43 @@ public class DocumentPluginGoals extends DefaultTask {
|
||||
List<Parameter> requiredParameters = parameters.stream().filter(Parameter::isRequired).toList();
|
||||
String detailsSectionId = sectionId + ".parameter-details";
|
||||
if (!requiredParameters.isEmpty()) {
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.printf("[[%s.required-parameters]]%n", sectionId);
|
||||
writer.println("== Required parameters");
|
||||
writer.println();
|
||||
writeParametersTable(writer, detailsSectionId, requiredParameters);
|
||||
}
|
||||
List<Parameter> optionalParameters = parameters.stream()
|
||||
.filter((parameter) -> !parameter.isRequired())
|
||||
.toList();
|
||||
if (!optionalParameters.isEmpty()) {
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.printf("[[%s.optional-parameters]]%n", sectionId);
|
||||
writer.println("== Optional parameters");
|
||||
writer.println();
|
||||
writeParametersTable(writer, detailsSectionId, optionalParameters);
|
||||
}
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.printf("[[%s]]%n", detailsSectionId);
|
||||
writer.println("== Parameter details");
|
||||
writer.println();
|
||||
writeParameterDetails(writer, parameters, detailsSectionId);
|
||||
}
|
||||
}
|
||||
|
||||
private String goalSectionId(Mojo mojo) {
|
||||
private String goalSectionId(Mojo mojo, boolean innerReference) {
|
||||
String goalSection = this.goalSections.get(mojo.getGoal());
|
||||
if (goalSection == null) {
|
||||
throw new IllegalStateException("Goal '" + mojo.getGoal() + "' has not be assigned to a section");
|
||||
}
|
||||
String sectionId = goalSection + "." + mojo.getGoal() + "-goal";
|
||||
return sectionId;
|
||||
return (!innerReference) ? goalSection + "#" + sectionId : sectionId;
|
||||
}
|
||||
|
||||
private void writeParametersTable(PrintWriter writer, String detailsSectionId, List<Parameter> parameters) {
|
||||
@@ -236,10 +240,10 @@ public class DocumentPluginGoals extends DefaultTask {
|
||||
|
||||
private String typeNameToJavadocLink(String shortName, String name) {
|
||||
if (name.startsWith("org.springframework.boot.maven")) {
|
||||
return "{spring-boot-docs}/maven-plugin/api/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
return "xref:maven-plugin:api/java/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
}
|
||||
if (name.startsWith("org.springframework.boot")) {
|
||||
return "{spring-boot-docs}/api/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
return "xref:api:java/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
}
|
||||
return shortName;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -158,7 +158,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
|
||||
DocumentPluginGoals task = project.getTasks().create("documentPluginGoals", DocumentPluginGoals.class);
|
||||
File pluginXml = new File(generatePluginDescriptorTask.getOutputs().getFiles().getSingleFile(), "plugin.xml");
|
||||
task.setPluginXml(pluginXml);
|
||||
task.setOutputDir(new File(project.getBuildDir(), "docs/generated/goals/"));
|
||||
task.setOutputDir(new File(project.getBuildDir(), "generated/docs/maven-plugin-goals/"));
|
||||
task.dependsOn(generatePluginDescriptorTask);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# === INCLUDE-CODE LOCATIONS ===
|
||||
|
||||
include-java=ROOT:example$java/org/springframework/boot/docs
|
||||
include-kotlin= ROOT:example$kotlin/org/springframework/boot/docs
|
||||
|
||||
# === URLs ===
|
||||
|
||||
url-ant-docs=https://ant.apache.org/manual
|
||||
url-buildpacks-docs=https://buildpacks.io/docs
|
||||
url-dynatrace-docs=https://docs.dynatrace.com/docs
|
||||
url-dynatrace-docs-shortlink={url-dynatrace-docs}/shortlink
|
||||
url-github-raw=https://raw.githubusercontent.com/{github-repo}/{github-ref}
|
||||
url-github-issues=https://github.com/{github-repo}/issues
|
||||
url-github-wiki=https://github.com/{github-repo}/wiki
|
||||
url-github=https://github.com/{github-repo}
|
||||
url-graal-docs=https://www.graalvm.org/{version-graal}/reference-manual
|
||||
url-graal-docs-native-image={url-graal-docs}/native-image
|
||||
url-gradle-docs=https://docs.gradle.org/current/userguide
|
||||
url-gradle-docs-application-plugin={url-gradle-docs}/application_plugin.html
|
||||
url-gradle-docs-groovy-plugin={url-gradle-docs}/groovy_plugin.html
|
||||
url-gradle-docs-java-plugin={url-gradle-docs}/java_plugin.html
|
||||
url-gradle-docs-war-plugin={url-gradle-docs}/war_plugin.html
|
||||
url-gradle-dsl=https://docs.gradle.org/current/dsl
|
||||
url-gradle-javadoc=https://docs.gradle.org/current/javadoc
|
||||
url-kotlin-docs-kotlin-plugin={url-kotlin-docs}/using-gradle.html
|
||||
url-micrometer-docs-concepts={url-micrometer-docs}/concepts
|
||||
url-micrometer-docs-implementations={url-micrometer-docs}/implementations
|
||||
url-download-liberica-nik=https://bell-sw.com/pages/downloads/native-image-kit/#/nik-22-17
|
||||
url-native-build-tools-docs=https://graalvm.github.io/native-build-tools/{version-native-build-tools}
|
||||
url-native-build-tools-docs-gradle-plugin={url-native-build-tools-docs}/gradle-plugin.html
|
||||
url-native-build-tools-docs-maven-plugin={url-native-build-tools-docs}/maven-plugin.html
|
||||
url-paketo-docs=https://paketo.io/docs
|
||||
url-paketo-docs-java-buildpack={url-paketo-docs}/buildpacks/language-family-buildpacks/java
|
||||
url-spring-boot-for-apache-geode-docs=https://docs.spring.io/spring-boot-data-geode-build/2.0.x/reference/html5
|
||||
url-spring-boot-for-apache-geode-site=https://github.com/spring-projects/spring-boot-data-geode
|
||||
url-spring-data-cassandra-site=https://spring.io/projects/spring-data-cassandra
|
||||
url-spring-data-commons-javadoc=https://docs.spring.io/spring-data/commons/docs/{version-spring-data-commons}/api
|
||||
url-spring-data-couchbase-docs=https://docs.spring.io/spring-data/couchbase/reference/{version-spring-data-couchbase}
|
||||
url-spring-data-couchbase-site=https://spring.io/projects/spring-data-couchbase
|
||||
url-spring-data-elasticsearch-docs=https://docs.spring.io/spring-data/elasticsearch/reference/{version-spring-data-elasticsearch}
|
||||
url-spring-data-elasticsearch-site=https://spring.io/projects/spring-data-elasticsearch
|
||||
url-spring-data-envers-site=https://spring.io/projects/spring-data-envers
|
||||
url-spring-data-gemfire-site=https://spring.io/projects/spring-data-gemfire
|
||||
url-spring-data-geode-site=https://spring.io/projects/spring-data-geode
|
||||
url-spring-data-jdbc-docs=https://docs.spring.io/spring-data/relational/reference/{version-spring-data-jdbc}
|
||||
url-spring-data-jpa-javadoc=https://docs.spring.io/spring-data/jpa/docs/{version-spring-data-jpa}/api
|
||||
url-spring-data-jpa-site=https://spring.io/projects/spring-jpa
|
||||
url-spring-data-jpa-docs=https://docs.spring.io/spring-data/jpa/reference/{version-spring-data-jpa}
|
||||
url-spring-data-ldap-site=https://spring.io/projects/spring-data-ldap
|
||||
url-spring-data-mongodb-javadoc=https://docs.spring.io/spring-data/mongodb/docs/{version-spring-data-mongodb}/api
|
||||
url-spring-data-mongodb-site=https://spring.io/projects/spring-data-mongodb
|
||||
url-spring-data-mongodb-docs=https://docs.spring.io/spring-data/mongodb/reference/{version-spring-data-mongodb}
|
||||
url-spring-data-neo4j-docs=https://docs.spring.io/spring-data/neo4j/reference/{version-spring-data-neo4j}
|
||||
url-spring-data-neo4j-site=https://spring.io/projects/spring-data-neo4j
|
||||
url-spring-data-r2dbc-javadoc=https://docs.spring.io/spring-data/r2dbc/docs/{version-spring-data-r2dbc}/api
|
||||
url-spring-data-r2dbc-docs=https://docs.spring.io/spring-data/relational/reference/{version-spring-data-r2dbc}
|
||||
url-spring-data-redis-site=https://spring.io/projects/spring-data-redis
|
||||
url-spring-data-rest-javadoc=https://docs.spring.io/spring-data/rest/docs/{version-spring-data-rest}/api
|
||||
url-spring-data-site=https://spring.io/projects/spring-data
|
||||
|
||||
# === API References ===
|
||||
|
||||
apiref-gradle-plugin-boot-build-image=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.html
|
||||
apiref-gradle-plugin-boot-jar=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/bundling/BootJar.html
|
||||
apiref-gradle-plugin-boot-run=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/run/BootRun.html
|
||||
apiref-gradle-plugin-boot-war=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/bundling/BootWar.html
|
||||
apiref-gradle-plugin-boot-build-info=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfo.html
|
||||
apiref-openjdk=https://docs.oracle.com/en/java/javase/17/docs/api
|
||||
|
||||
# === Code Links ===
|
||||
|
||||
code-spring-boot=https://github.com/{github-repo}/tree/{github-ref}
|
||||
code-spring-boot-src={code-spring-boot}/spring-boot-project/spring-boot/src/main/java/org/springframework/boot
|
||||
code-spring-boot-actuator-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure
|
||||
code-spring-boot-actuator-src={code-spring-boot}/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate
|
||||
code-spring-boot-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure
|
||||
code-spring-boot-devtools-src={code-spring-boot}/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools
|
||||
code-spring-boot-test-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure
|
||||
code-spring-boot-latest=https://github.com/{github-repo}/tree/main
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
antora:
|
||||
extensions:
|
||||
site:
|
||||
title: Spring Boot
|
||||
content:
|
||||
sources: []
|
||||
asciidoc:
|
||||
sourcemap: true
|
||||
attributes:
|
||||
chomp: all
|
||||
hide-uri-scheme: '@'
|
||||
page-pagination: ''
|
||||
page-stackoverflow-url: https://stackoverflow.com/tags/spring-boot
|
||||
tabs-sync-option: '@'
|
||||
extensions:
|
||||
- '@asciidoctor/tabs'
|
||||
- '@springio/asciidoctor-extensions'
|
||||
- '@springio/asciidoctor-extensions/configuration-properties-extension'
|
||||
- '@springio/asciidoctor-extensions/section-ids-extension'
|
||||
urls:
|
||||
latest_version_segment: ''
|
||||
runtime:
|
||||
log:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.11/ui-bundle.zip
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.antora;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.build.bom.Library;
|
||||
import org.springframework.boot.build.bom.Library.Group;
|
||||
import org.springframework.boot.build.bom.Library.LibraryVersion;
|
||||
import org.springframework.boot.build.bom.Library.ProhibitedVersion;
|
||||
import org.springframework.boot.build.bom.Library.VersionAlignment;
|
||||
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AntoraAsciidocAttributes}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class AntoraAsciidocAttributesTests {
|
||||
|
||||
@Test
|
||||
void githubRefWhenReleasedVersionIsTag() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "v1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void githubRefWhenLatestSnapshotVersionIsMainBranch() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "main");
|
||||
}
|
||||
|
||||
@Test
|
||||
void githubRefWhenOlderSnapshotVersionIsBranch() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", false, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "1.2.x");
|
||||
}
|
||||
|
||||
@Test
|
||||
void githubRefWhenOlderSnapshotHotFixVersionIsBranch() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3.1-SNAPSHOT", false, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "1.2.3.x");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionReferenceFromLibrary() {
|
||||
Library library = mockLibrary(Collections.emptyMap());
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3.1-SNAPSHOT", false, List.of(library),
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("version-spring-framework", "1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionReferenceFromSpringDataDependencyVersion() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("version-spring-data-mongodb", "1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionNativeBuildTools() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), Map.of("nativeBuildToolsVersion", "3.4.5"));
|
||||
assertThat(attributes.get()).containsEntry("version-native-build-tools", "3.4.5");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlArtifactReposiroryWhenRelease() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-artifact-repository", "https://repo.maven.apache.org/maven2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlArtifactReposiroryWhenMilestone() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-M1", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-artifact-repository", "https://repo.spring.io/milestone");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlArtifactReposiroryWhenSnapshot() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-artifact-repository", "https://repo.spring.io/snapshot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlLinksFromLibrary() {
|
||||
Map<String, Function<LibraryVersion, String>> links = new LinkedHashMap<>();
|
||||
links.put("site", (version) -> "https://example.com/site/" + version);
|
||||
links.put("docs", (version) -> "https://example.com/docs/" + version);
|
||||
Library library = mockLibrary(links);
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3.1-SNAPSHOT", false, List.of(library),
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-spring-framework-site", "https://example.com/site/1.2.3")
|
||||
.containsEntry("url-spring-framework-docs", "https://example.com/docs/1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksFromProperties() {
|
||||
Map<String, String> attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", true, null,
|
||||
mockDependencyVersions(), null)
|
||||
.get();
|
||||
assertThat(attributes).containsEntry("include-java", "ROOT:example$java/org/springframework/boot/docs");
|
||||
assertThat(attributes).containsEntry("url-spring-data-cassandra-site",
|
||||
"https://spring.io/projects/spring-data-cassandra");
|
||||
List<String> keys = new ArrayList<>(attributes.keySet());
|
||||
assertThat(keys.indexOf("include-java")).isLessThan(keys.indexOf("code-spring-boot-latest"));
|
||||
}
|
||||
|
||||
private Library mockLibrary(Map<String, Function<LibraryVersion, String>> links) {
|
||||
String name = "Spring Framework";
|
||||
String calendarName = null;
|
||||
LibraryVersion version = new LibraryVersion(DependencyVersion.parse("1.2.3"));
|
||||
List<Group> groups = Collections.emptyList();
|
||||
List<ProhibitedVersion> prohibitedVersion = Collections.emptyList();
|
||||
boolean considerSnapshots = false;
|
||||
VersionAlignment versionAlignment = null;
|
||||
String linkRootName = null;
|
||||
Library library = new Library(name, calendarName, version, groups, prohibitedVersion, considerSnapshots,
|
||||
versionAlignment, linkRootName, links);
|
||||
return library;
|
||||
}
|
||||
|
||||
private Map<String, String> mockDependencyVersions() {
|
||||
Map<String, String> versions = new LinkedHashMap<>();
|
||||
addMockSpringDataVersion(versions, "spring-data-commons");
|
||||
addMockSpringDataVersion(versions, "spring-data-couchbase");
|
||||
addMockSpringDataVersion(versions, "spring-data-elasticsearch");
|
||||
addMockSpringDataVersion(versions, "spring-data-jdbc");
|
||||
addMockSpringDataVersion(versions, "spring-data-jpa");
|
||||
addMockSpringDataVersion(versions, "spring-data-mongodb");
|
||||
addMockSpringDataVersion(versions, "spring-data-neo4j");
|
||||
addMockSpringDataVersion(versions, "spring-data-r2dbc");
|
||||
addMockSpringDataVersion(versions, "spring-data-rest-core");
|
||||
return versions;
|
||||
}
|
||||
|
||||
private void addMockSpringDataVersion(Map<String, String> versions, String artifactId) {
|
||||
versions.put("org.springframework.data:" + artifactId, "1.2.3");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.antora;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
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.util.function.ThrowingConsumer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link GenerateAntoraPlaybook}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class GenerateAntoraPlaybookTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
@Test
|
||||
void writePlaybookGeneratesExpectedContent() throws Exception {
|
||||
writePlaybookYml((task) -> {
|
||||
task.getXrefStubs().addAll("appendix:.*", "api:.*", "reference:.*");
|
||||
task.getAlwaysInclude().set(Map.of("name", "test", "classifier", "local-aggregate-content"));
|
||||
});
|
||||
Path actual = this.temp.toPath()
|
||||
.resolve("rootproject/project/build/generated/docs/antora-playbook/antora-playbook.yml");
|
||||
System.out.println(Files.readString(actual));
|
||||
assertThat(actual).hasSameTextualContentAs(
|
||||
Path.of("src/test/resources/org/springframework/boot/build/antora/expected-playbook.yml"));
|
||||
}
|
||||
|
||||
private void writePlaybookYml(ThrowingConsumer<GenerateAntoraPlaybook> customizer) throws Exception {
|
||||
File rootProjectDir = new File(this.temp, "rootproject").getCanonicalFile();
|
||||
rootProjectDir.mkdirs();
|
||||
Project rootProject = ProjectBuilder.builder().withProjectDir(rootProjectDir).build();
|
||||
File projectDir = new File(rootProjectDir, "project");
|
||||
projectDir.mkdirs();
|
||||
Project project = ProjectBuilder.builder().withProjectDir(projectDir).withParent(rootProject).build();
|
||||
GenerateAntoraPlaybook task = project.getTasks().create("generateAntoraPlaybook", GenerateAntoraPlaybook.class);
|
||||
customizer.accept(task);
|
||||
task.writePlaybookYml();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -153,7 +153,6 @@ class ArchitectureCheckTests {
|
||||
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<T> {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
antora:
|
||||
extensions:
|
||||
- require: '@springio/antora-extensions/static-page-extension'
|
||||
- require: '@springio/antora-xref-extension'
|
||||
stub:
|
||||
- appendix:.*
|
||||
- api:.*
|
||||
- reference:.*
|
||||
- require: '@springio/antora-zip-contents-collector-extension'
|
||||
always_include:
|
||||
- classifier: local-aggregate-content
|
||||
name: test
|
||||
locations:
|
||||
- project/build/generated/docs/antora-content/test-${version}-${name}-${classifier}.zip
|
||||
- project/build/generated/docs/antora-dependencies-content/test-${version}-${name}-${classifier}.zip
|
||||
version_file: gradle.properties
|
||||
- require: '@springio/antora-extensions/root-component-extension'
|
||||
root_component_name: spring-boot
|
||||
site:
|
||||
title: Spring Boot
|
||||
content:
|
||||
sources:
|
||||
- url: ./../../../../..
|
||||
branches: HEAD
|
||||
version: unspecified
|
||||
start_paths:
|
||||
- project/src/docs/antora
|
||||
asciidoc:
|
||||
sourcemap: true
|
||||
attributes:
|
||||
chomp: all
|
||||
hide-uri-scheme: '@'
|
||||
page-pagination: ''
|
||||
page-stackoverflow-url: https://stackoverflow.com/tags/spring-boot
|
||||
tabs-sync-option: '@'
|
||||
extensions:
|
||||
- '@asciidoctor/tabs'
|
||||
- '@springio/asciidoctor-extensions'
|
||||
- '@springio/asciidoctor-extensions/configuration-properties-extension'
|
||||
- '@springio/asciidoctor-extensions/section-ids-extension'
|
||||
urls:
|
||||
latest_version_segment: ''
|
||||
runtime:
|
||||
log:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.11/ui-bundle.zip
|
||||
output:
|
||||
dir: ./../../../site
|
||||
@@ -64,12 +64,6 @@ anchors:
|
||||
build_number: "${BUILD_JOB_NAME}-${BUILD_NAME}"
|
||||
disable_checksum_uploads: true
|
||||
threads: 8
|
||||
artifact_set:
|
||||
- include:
|
||||
- "/**/spring-boot-docs-*.zip"
|
||||
properties:
|
||||
"zip.type": "docs"
|
||||
"zip.deployed": "false"
|
||||
slack-fail-params: &slack-fail-params
|
||||
text: >
|
||||
:concourse-failed: <!here> <https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}|${BUILD_PIPELINE_NAME} ${BUILD_JOB_NAME} failed!>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
version=3.3.0-SNAPSHOT
|
||||
latestVersion=true
|
||||
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
@@ -6,6 +7,7 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
|
||||
|
||||
assertjVersion=3.25.3
|
||||
commonsCodecVersion=1.16.1
|
||||
graalVersion=22.3
|
||||
hamcrestVersion=2.2
|
||||
jacksonVersion=2.17.0
|
||||
junitJupiterVersion=5.10.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id "java-library"
|
||||
id "org.asciidoctor.jvm.convert"
|
||||
id "org.antora"
|
||||
id "org.springframework.boot.auto-configuration"
|
||||
id "org.springframework.boot.configuration-properties"
|
||||
id "org.springframework.boot.conventions"
|
||||
@@ -11,13 +11,10 @@ plugins {
|
||||
description = "Spring Boot Actuator AutoConfigure"
|
||||
|
||||
configurations {
|
||||
documentation
|
||||
antoraContent
|
||||
}
|
||||
|
||||
dependencies {
|
||||
asciidoctorExtensions("org.springframework.restdocs:spring-restdocs-asciidoctor")
|
||||
asciidoctorExtensions("io.spring.asciidoctor:spring-asciidoctor-extensions-section-ids")
|
||||
|
||||
api(project(":spring-boot-project:spring-boot-actuator"))
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
@@ -195,38 +192,6 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
task dependencyVersions(type: org.springframework.boot.build.constraints.ExtractVersionConstraints) {
|
||||
enforcedPlatform(":spring-boot-project:spring-boot-dependencies")
|
||||
}
|
||||
|
||||
asciidoctor {
|
||||
sources {
|
||||
include "index.adoc"
|
||||
}
|
||||
}
|
||||
|
||||
task asciidoctorPdf(type: org.asciidoctor.gradle.jvm.AsciidoctorTask) {
|
||||
sources {
|
||||
include "index.adoc"
|
||||
}
|
||||
}
|
||||
|
||||
task zip(type: Zip) {
|
||||
dependsOn asciidoctor, asciidoctorPdf
|
||||
duplicatesStrategy "fail"
|
||||
from(asciidoctorPdf.outputDir) {
|
||||
into "pdf"
|
||||
rename { "spring-boot-actuator-web-api.pdf" }
|
||||
}
|
||||
from(asciidoctor.outputDir) {
|
||||
into "htmlsingle"
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
documentation zip
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED"
|
||||
filter {
|
||||
@@ -235,28 +200,46 @@ tasks.named("test") {
|
||||
}
|
||||
|
||||
def documentationTest = tasks.register("documentationTest", Test) {
|
||||
jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED"
|
||||
filter {
|
||||
includeTestsMatching("org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation.*")
|
||||
}
|
||||
jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED"
|
||||
outputs.dir("${buildDir}/generated-snippets")
|
||||
predictiveSelection {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) {
|
||||
dependsOn dependencyVersions
|
||||
doFirst {
|
||||
def versionConstraints = dependencyVersions.versionConstraints
|
||||
def toAntoraVersion = version -> {
|
||||
String formatted = version.split("\\.").take(2).join('.')
|
||||
return version.endsWith("-SNAPSHOT") ? formatted + "-SNAPSHOT" : formatted
|
||||
}
|
||||
def integrationVersion = versionConstraints["org.springframework.integration:spring-integration-core"]
|
||||
String integrationDocs = String.format("https://docs.spring.io/spring-integration/reference/%s", toAntoraVersion(integrationVersion))
|
||||
attributes "spring-integration-docs": integrationDocs
|
||||
def antoraActuatorRestApiLocalAggregateContent = tasks.register("antoraActuatorRestApiLocalAggregateContent", Zip) {
|
||||
destinationDirectory = layout.buildDirectory.dir('generated/docs/antora-content')
|
||||
archiveClassifier = "actuator-rest-api-local-aggregate-content"
|
||||
from(tasks.getByName("generateAntoraYml")) {
|
||||
into "modules"
|
||||
}
|
||||
dependsOn documentationTest
|
||||
inputs.dir("${buildDir}/generated-snippets").withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("generatedSnippets")
|
||||
}
|
||||
|
||||
def antoraActuatorRestApiAggregateContent = tasks.register("antoraActuatorRestApiAggregateContent", Zip) {
|
||||
dependsOn documentationTest
|
||||
inputs.dir("${buildDir}/generated-snippets")
|
||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
.withPropertyName("generatedSnippets")
|
||||
destinationDirectory = layout.buildDirectory.dir('generated/docs/antora-content')
|
||||
archiveClassifier = "actuator-rest-api-aggregate-content"
|
||||
from("${buildDir}/generated-snippets") {
|
||||
into "modules/api/partials/rest/actuator"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("generateAntoraPlaybook") {
|
||||
alwaysInclude = [name: "actuator-rest-api", classifier: "local-aggregate-content"]
|
||||
dependsOn antoraActuatorRestApiLocalAggregateContent
|
||||
}
|
||||
|
||||
tasks.named("antora") {
|
||||
inputs.files(antoraActuatorRestApiAggregateContent)
|
||||
}
|
||||
|
||||
artifacts {
|
||||
antoraContent antoraActuatorRestApiAggregateContent
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
name: spring-boot
|
||||
ext:
|
||||
zip_contents_collector:
|
||||
include:
|
||||
- name: actuator-rest-api
|
||||
classifier: aggregate-content
|
||||
@@ -0,0 +1 @@
|
||||
include::api:partial$nav-actuator-rest-api.adoc[]
|
||||
@@ -1,36 +1,40 @@
|
||||
[[audit-events]]
|
||||
= Audit Events (`auditevents`)
|
||||
|
||||
The `auditevents` endpoint provides information about the application's audit events.
|
||||
|
||||
|
||||
|
||||
[[audit-events.retrieving]]
|
||||
== Retrieving Audit Events
|
||||
|
||||
To retrieve the audit events, make a `GET` request to `/actuator/auditevents`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/auditevents/filtered/curl-request.adoc[]
|
||||
include::partial$rest/actuator/auditevents/filtered/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves `logout` events for the principal, `alice`, that occurred after 09:37 on 7 November 2017 in the UTC timezone.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/auditevents/filtered/http-response.adoc[]
|
||||
include::partial$rest/actuator/auditevents/filtered/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[audit-events.retrieving.query-parameters]]
|
||||
=== Query Parameters
|
||||
|
||||
The endpoint uses query parameters to limit the events that it returns.
|
||||
The following table shows the supported query parameters:
|
||||
|
||||
[cols="2,4"]
|
||||
include::{snippets}/auditevents/filtered/query-parameters.adoc[]
|
||||
include::partial$rest/actuator/auditevents/filtered/query-parameters.adoc[]
|
||||
|
||||
|
||||
|
||||
[[audit-events.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of all of the audit events that matched the query.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/auditevents/all/response-fields.adoc[]
|
||||
include::partial$rest/actuator/auditevents/all/response-fields.adoc[]
|
||||
@@ -1,25 +1,28 @@
|
||||
[[beans]]
|
||||
= Beans (`beans`)
|
||||
|
||||
The `beans` endpoint provides information about the application's beans.
|
||||
|
||||
|
||||
|
||||
[[beans.retrieving]]
|
||||
== Retrieving the Beans
|
||||
|
||||
To retrieve the beans, make a `GET` request to `/actuator/beans`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/beans/curl-request.adoc[]
|
||||
include::partial$rest/actuator/beans/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/beans/http-response.adoc[]
|
||||
include::partial$rest/actuator/beans/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[beans.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's beans.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/beans/response-fields.adoc[]
|
||||
include::partial$rest/actuator/beans/response-fields.adoc[]
|
||||
@@ -1,78 +1,86 @@
|
||||
[[caches]]
|
||||
= Caches (`caches`)
|
||||
|
||||
The `caches` endpoint provides access to the application's caches.
|
||||
|
||||
|
||||
|
||||
[[caches.all]]
|
||||
== Retrieving All Caches
|
||||
|
||||
To retrieve the application's caches, make a `GET` request to `/actuator/caches`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/caches/all/curl-request.adoc[]
|
||||
include::partial$rest/actuator/caches/all/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/caches/all/http-response.adoc[]
|
||||
include::partial$rest/actuator/caches/all/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[caches.all.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's caches.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/caches/all/response-fields.adoc[]
|
||||
include::partial$rest/actuator/caches/all/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[caches.named]]
|
||||
== Retrieving Caches by Name
|
||||
|
||||
To retrieve a cache by name, make a `GET` request to `/actuator/caches/\{name}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/caches/named/curl-request.adoc[]
|
||||
include::partial$rest/actuator/caches/named/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves information about the cache named `cities`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/caches/named/http-response.adoc[]
|
||||
include::partial$rest/actuator/caches/named/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[caches.named.query-parameters]]
|
||||
=== Query Parameters
|
||||
|
||||
If the requested name is specific enough to identify a single cache, no extra parameter is required.
|
||||
Otherwise, the `cacheManager` must be specified.
|
||||
The following table shows the supported query parameters:
|
||||
|
||||
[cols="2,4"]
|
||||
include::{snippets}/caches/named/query-parameters.adoc[]
|
||||
include::partial$rest/actuator/caches/named/query-parameters.adoc[]
|
||||
|
||||
|
||||
|
||||
[[caches.named.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the requested cache.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/caches/named/response-fields.adoc[]
|
||||
include::partial$rest/actuator/caches/named/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[caches.evict-all]]
|
||||
== Evict All Caches
|
||||
|
||||
To clear all available caches, make a `DELETE` request to `/actuator/caches` as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/caches/evict-all/curl-request.adoc[]
|
||||
include::partial$rest/actuator/caches/evict-all/curl-request.adoc[]
|
||||
|
||||
|
||||
|
||||
[[caches.evict-named]]
|
||||
== Evict a Cache by Name
|
||||
|
||||
To evict a particular cache, make a `DELETE` request to `/actuator/caches/\{name}` as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/caches/evict-named/curl-request.adoc[]
|
||||
include::partial$rest/actuator/caches/evict-named/curl-request.adoc[]
|
||||
|
||||
NOTE: As there are two caches named `countries`, the `cacheManager` has to be provided to specify which `Cache` should be cleared.
|
||||
|
||||
@@ -80,9 +88,10 @@ NOTE: As there are two caches named `countries`, the `cacheManager` has to be pr
|
||||
|
||||
[[caches.evict-named.request-structure]]
|
||||
=== Request Structure
|
||||
|
||||
If the requested name is specific enough to identify a single cache, no extra parameter is required.
|
||||
Otherwise, the `cacheManager` must be specified.
|
||||
The following table shows the supported query parameters:
|
||||
|
||||
[cols="2,4"]
|
||||
include::{snippets}/caches/evict-named/query-parameters.adoc[]
|
||||
include::partial$rest/actuator/caches/evict-named/query-parameters.adoc[]
|
||||
@@ -1,25 +1,28 @@
|
||||
[[conditions]]
|
||||
= Conditions Evaluation Report (`conditions`)
|
||||
|
||||
The `conditions` endpoint provides information about the evaluation of conditions on configuration and auto-configuration classes.
|
||||
|
||||
|
||||
|
||||
[[conditions.retrieving]]
|
||||
== Retrieving the Report
|
||||
|
||||
To retrieve the report, make a `GET` request to `/actuator/conditions`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/conditions/curl-request.adoc[]
|
||||
include::partial$rest/actuator/conditions/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/conditions/http-response.adoc[]
|
||||
include::partial$rest/actuator/conditions/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[conditions.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's condition evaluation.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/conditions/response-fields.adoc[]
|
||||
include::partial$rest/actuator/conditions/response-fields.adoc[]
|
||||
@@ -1,40 +1,44 @@
|
||||
[[configprops]]
|
||||
= Configuration Properties (`configprops`)
|
||||
|
||||
The `configprops` endpoint provides information about the application's `@ConfigurationProperties` beans.
|
||||
|
||||
|
||||
|
||||
[[configprops.retrieving]]
|
||||
== Retrieving All @ConfigurationProperties Beans
|
||||
|
||||
To retrieve all of the `@ConfigurationProperties` beans, make a `GET` request to `/actuator/configprops`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/configprops/all/curl-request.adoc[]
|
||||
include::partial$rest/actuator/configprops/all/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/configprops/all/http-response.adoc[]
|
||||
include::partial$rest/actuator/configprops/all/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[configprops.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's `@ConfigurationProperties` beans.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/configprops/all/response-fields.adoc[]
|
||||
include::partial$rest/actuator/configprops/all/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[configprops.retrieving-by-prefix]]
|
||||
== Retrieving @ConfigurationProperties Beans By Prefix
|
||||
|
||||
To retrieve the `@ConfigurationProperties` beans mapped under a certain prefix, make a `GET` request to `/actuator/configprops/\{prefix}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/configprops/prefixed/curl-request.adoc[]
|
||||
include::partial$rest/actuator/configprops/prefixed/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/configprops/prefixed/http-response.adoc[]
|
||||
include::partial$rest/actuator/configprops/prefixed/http-response.adoc[]
|
||||
|
||||
NOTE: The `\{prefix}` does not need to be exact, a more general prefix will return all beans mapped under that prefix stem.
|
||||
|
||||
@@ -42,8 +46,9 @@ NOTE: The `\{prefix}` does not need to be exact, a more general prefix will retu
|
||||
|
||||
[[configprops.retrieving-by-prefix.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's `@ConfigurationProperties` beans.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/configprops/prefixed/response-fields.adoc[]
|
||||
include::partial$rest/actuator/configprops/prefixed/response-fields.adoc[]
|
||||
@@ -1,49 +1,57 @@
|
||||
[[env]]
|
||||
= Environment (`env`)
|
||||
|
||||
The `env` endpoint provides information about the application's `Environment`.
|
||||
|
||||
|
||||
|
||||
[[env.entire]]
|
||||
== Retrieving the Entire Environment
|
||||
|
||||
To retrieve the entire environment, make a `GET` request to `/actuator/env`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/env/all/curl-request.adoc[]
|
||||
include::partial$rest/actuator/env/all/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/env/all/http-response.adoc[]
|
||||
include::partial$rest/actuator/env/all/http-response.adoc[]
|
||||
|
||||
NOTE: Sanitization of sensitive values has been switched off for this example.
|
||||
|
||||
|
||||
|
||||
[[env.entire.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's `Environment`.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/env/all/response-fields.adoc[]
|
||||
include::partial$rest/actuator/env/all/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[env.single-property]]
|
||||
== Retrieving a Single Property
|
||||
|
||||
To retrieve a single property, make a `GET` request to `/actuator/env/{property.name}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/env/single/curl-request.adoc[]
|
||||
include::partial$rest/actuator/env/single/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves information about the property named `com.example.cache.max-size`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/env/single/http-response.adoc[]
|
||||
include::partial$rest/actuator/env/single/http-response.adoc[]
|
||||
|
||||
NOTE: Sanitization of sensitive values has been switched off for this example.
|
||||
|
||||
|
||||
|
||||
[[env.single-property.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the requested property.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/env/single/response-fields.adoc[]
|
||||
include::partial$rest/actuator/env/single/response-fields.adoc[]
|
||||
@@ -1,25 +1,28 @@
|
||||
[[flyway]]
|
||||
= Flyway (`flyway`)
|
||||
|
||||
The `flyway` endpoint provides information about database migrations performed by Flyway.
|
||||
|
||||
|
||||
|
||||
[[flyway.retrieving]]
|
||||
== Retrieving the Migrations
|
||||
|
||||
To retrieve the migrations, make a `GET` request to `/actuator/flyway`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/flyway/curl-request.adoc[]
|
||||
include::partial$rest/actuator/flyway/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/flyway/http-response.adoc[]
|
||||
include::partial$rest/actuator/flyway/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[flyway.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's Flyway migrations.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/flyway/response-fields.adoc[]
|
||||
include::partial$rest/actuator/flyway/response-fields.adoc[]
|
||||
@@ -1,28 +1,31 @@
|
||||
[[health]]
|
||||
= Health (`health`)
|
||||
|
||||
The `health` endpoint provides detailed information about the health of the application.
|
||||
|
||||
|
||||
|
||||
[[health.retrieving]]
|
||||
== Retrieving the Health of the Application
|
||||
|
||||
To retrieve the health of the application, make a `GET` request to `/actuator/health`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/health/curl-request.adoc[]
|
||||
include::partial$rest/actuator/health/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/health/http-response.adoc[]
|
||||
include::partial$rest/actuator/health/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[health.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the health of the application.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/health/response-fields.adoc[]
|
||||
include::partial$rest/actuator/health/response-fields.adoc[]
|
||||
|
||||
NOTE: The response fields above are for the V3 API.
|
||||
If you need to return V2 JSON you should use an accept header or `application/vnd.spring-boot.actuator.v2+json`
|
||||
@@ -31,35 +34,38 @@ If you need to return V2 JSON you should use an accept header or `application/vn
|
||||
|
||||
[[health.retrieving-component]]
|
||||
== Retrieving the Health of a Component
|
||||
|
||||
To retrieve the health of a particular component of the application's health, make a `GET` request to `/actuator/health/\{component}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/health/component/curl-request.adoc[]
|
||||
include::partial$rest/actuator/health/component/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/health/component/http-response.adoc[]
|
||||
include::partial$rest/actuator/health/component/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[health.retrieving-component.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the health of a particular component of the application's health.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/health/component/response-fields.adoc[]
|
||||
include::partial$rest/actuator/health/component/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[health.retrieving-component-nested]]
|
||||
== Retrieving the Health of a Nested Component
|
||||
|
||||
If a particular component contains other nested components (as the `broker` indicator in the example above), the health of such a nested component can be retrieved by issuing a `GET` request to `/actuator/health/\{component}/\{subcomponent}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/health/instance/curl-request.adoc[]
|
||||
include::partial$rest/actuator/health/instance/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/health/instance/http-response.adoc[]
|
||||
include::partial$rest/actuator/health/instance/http-response.adoc[]
|
||||
|
||||
Components of an application's health may be nested arbitrarily deep depending on the application's health indicators and how they have been grouped.
|
||||
The health endpoint supports any number of `/\{component}` identifiers in the URL to allow the health of a component at any depth to be retrieved.
|
||||
@@ -68,8 +74,9 @@ The health endpoint supports any number of `/\{component}` identifiers in the UR
|
||||
|
||||
[[health.retrieving-component-nested.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the health of an instance of a particular component of the application.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/health/instance/response-fields.adoc[]
|
||||
include::partial$rest/actuator/health/instance/response-fields.adoc[]
|
||||
@@ -1,11 +1,13 @@
|
||||
[[heapdump]]
|
||||
= Heap Dump (`heapdump`)
|
||||
|
||||
The `heapdump` endpoint provides a heap dump from the application's JVM.
|
||||
|
||||
|
||||
|
||||
[[heapdump.retrieving]]
|
||||
== Retrieving the Heap Dump
|
||||
|
||||
To retrieve the heap dump, make a `GET` request to `/actuator/heapdump`.
|
||||
The response is binary data and can be large.
|
||||
Its format depends upon the JVM on which the application is running.
|
||||
@@ -14,6 +16,6 @@ and on OpenJ9 it is https://www.eclipse.org/openj9/docs/dump_heapdump/#portable-
|
||||
Typically, you should save the response to disk for subsequent analysis.
|
||||
When using curl, this can be achieved by using the `-O` option, as shown in the following example:
|
||||
|
||||
include::{snippets}/heapdump/curl-request.adoc[]
|
||||
include::partial$rest/actuator/heapdump/curl-request.adoc[]
|
||||
|
||||
The preceding example results in a file named `heapdump` being written to the current working directory.
|
||||
@@ -1,25 +1,28 @@
|
||||
[[httpexchanges]]
|
||||
= HTTP Exchanges (`httpexchanges`)
|
||||
|
||||
The `httpexchanges` endpoint provides information about HTTP request-response exchanges.
|
||||
|
||||
|
||||
|
||||
[[httpexchanges.retrieving]]
|
||||
== Retrieving the HTTP Exchanges
|
||||
|
||||
To retrieve the HTTP exchanges, make a `GET` request to `/actuator/httpexchanges`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/httpexchanges/curl-request.adoc[]
|
||||
include::partial$rest/actuator/httpexchanges/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/httpexchanges/http-response.adoc[]
|
||||
include::partial$rest/actuator/httpexchanges/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[httpexchanges.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the traced HTTP request-response exchanges.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/httpexchanges/response-fields.adoc[]
|
||||
include::partial$rest/actuator/httpexchanges/response-fields.adoc[]
|
||||
@@ -0,0 +1,41 @@
|
||||
:navtitle: Actuator
|
||||
[[overview]]
|
||||
= Actuator REST API
|
||||
|
||||
This API documentation describes Spring Boot Actuators web endpoints.
|
||||
|
||||
Before you proceed, you should read the following topics:
|
||||
|
||||
* <<overview.endpoint-urls>>
|
||||
* <<overview.timestamps>>
|
||||
|
||||
NOTE: In order to get the correct JSON responses documented below, Jackson must be available.
|
||||
|
||||
|
||||
|
||||
[[overview.endpoint-urls]]
|
||||
== URLs
|
||||
|
||||
By default, all web endpoints are available beneath the path `/actuator` with URLs of
|
||||
the form `/actuator/\{id}`. The `/actuator` base path can be configured by using the
|
||||
`management.endpoints.web.base-path` property, as shown in the following example:
|
||||
|
||||
[source,properties]
|
||||
----
|
||||
management.endpoints.web.base-path=/manage
|
||||
----
|
||||
|
||||
The preceding `application.properties` example changes the form of the endpoint URLs from
|
||||
`/actuator/\{id}` to `/manage/\{id}`. For example, the URL `info` endpoint would become
|
||||
`/manage/info`.
|
||||
|
||||
|
||||
|
||||
[[overview.timestamps]]
|
||||
== Timestamps
|
||||
|
||||
All timestamps that are consumed by the endpoints, either as query parameters or in the
|
||||
request body, must be formatted as an offset date and time as specified in
|
||||
https://en.wikipedia.org/wiki/ISO_8601[ISO 8601].
|
||||
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
[[info]]
|
||||
= Info (`info`)
|
||||
|
||||
The `info` endpoint provides general information about the application.
|
||||
|
||||
|
||||
|
||||
[[info.retrieving]]
|
||||
== Retrieving the Info
|
||||
|
||||
To retrieve the information about the application, make a `GET` request to `/actuator/info`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/info/curl-request.adoc[]
|
||||
include::partial$rest/actuator/info/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/info/http-response.adoc[]
|
||||
include::partial$rest/actuator/info/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[info.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains general information about the application.
|
||||
Each section of the response is contributed by an `InfoContributor`.
|
||||
Spring Boot provides several contributors that are described below.
|
||||
@@ -26,19 +29,21 @@ Spring Boot provides several contributors that are described below.
|
||||
|
||||
[[info.retrieving.response-structure.build]]
|
||||
==== Build Response Structure
|
||||
|
||||
The following table describe the structure of the `build` section of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/info/response-fields-beneath-build.adoc[]
|
||||
include::partial$rest/actuator/info/response-fields-beneath-build.adoc[]
|
||||
|
||||
|
||||
|
||||
[[info.retrieving.response-structure.git]]
|
||||
==== Git Response Structure
|
||||
|
||||
The following table describes the structure of the `git` section of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/info/response-fields-beneath-git.adoc[]
|
||||
include::partial$rest/actuator/info/response-fields-beneath-git.adoc[]
|
||||
|
||||
NOTE: This is the "simple" output.
|
||||
The contributor can also be configured to output all available data.
|
||||
@@ -1,34 +1,38 @@
|
||||
[[integrationgraph]]
|
||||
= Spring Integration graph (`integrationgraph`)
|
||||
|
||||
The `integrationgraph` endpoint exposes a graph containing all Spring Integration components.
|
||||
|
||||
|
||||
|
||||
[[integrationgraph.retrieving]]
|
||||
== Retrieving the Spring Integration Graph
|
||||
|
||||
To retrieve the information about the application, make a `GET` request to `/actuator/integrationgraph`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/integrationgraph/graph/curl-request.adoc[]
|
||||
include::partial$rest/actuator/integrationgraph/graph/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/integrationgraph/graph/http-response.adoc[]
|
||||
include::partial$rest/actuator/integrationgraph/graph/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[integrationgraph.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains all Spring Integration components used within the application, as well as the links between them.
|
||||
More information about the structure can be found in the {spring-integration-docs}/index.html#integration-graph[reference documentation].
|
||||
More information about the structure can be found in the {url-spring-integration-docs}/graph.html[reference documentation].
|
||||
|
||||
|
||||
|
||||
[[integrationgraph.rebuilding]]
|
||||
== Rebuilding the Spring Integration Graph
|
||||
|
||||
To rebuild the exposed graph, make a `POST` request to `/actuator/integrationgraph`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/integrationgraph/rebuild/curl-request.adoc[]
|
||||
include::partial$rest/actuator/integrationgraph/rebuild/curl-request.adoc[]
|
||||
|
||||
This will result in a `204 - No Content` response:
|
||||
|
||||
include::{snippets}/integrationgraph/rebuild/http-response.adoc[]
|
||||
include::partial$rest/actuator/integrationgraph/rebuild/http-response.adoc[]
|
||||
@@ -1,25 +1,28 @@
|
||||
[[liquibase]]
|
||||
= Liquibase (`liquibase`)
|
||||
|
||||
The `liquibase` endpoint provides information about database change sets applied by Liquibase.
|
||||
|
||||
|
||||
|
||||
[[liquibase.retrieving]]
|
||||
== Retrieving the Changes
|
||||
|
||||
To retrieve the changes, make a `GET` request to `/actuator/liquibase`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/liquibase/curl-request.adoc[]
|
||||
include::partial$rest/actuator/liquibase/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/liquibase/http-response.adoc[]
|
||||
include::partial$rest/actuator/liquibase/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[liquibase.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's Liquibase change sets.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/liquibase/response-fields.adoc[]
|
||||
include::partial$rest/actuator/liquibase/response-fields.adoc[]
|
||||
@@ -1,30 +1,33 @@
|
||||
[[logfile]]
|
||||
= Log File (`logfile`)
|
||||
|
||||
The `logfile` endpoint provides access to the contents of the application's log file.
|
||||
|
||||
|
||||
|
||||
[[logfile.retrieving]]
|
||||
== Retrieving the Log File
|
||||
|
||||
To retrieve the log file, make a `GET` request to `/actuator/logfile`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/logfile/entire/curl-request.adoc[]
|
||||
include::partial$rest/actuator/logfile/entire/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/logfile/entire/http-response.adoc[]
|
||||
include::partial$rest/actuator/logfile/entire/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[logfile.retrieving-part]]
|
||||
== Retrieving Part of the Log File
|
||||
|
||||
NOTE: Retrieving part of the log file is not supported when using Jersey.
|
||||
|
||||
To retrieve part of the log file, make a `GET` request to `/actuator/logfile` by using the `Range` header, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/logfile/range/curl-request.adoc[]
|
||||
include::partial$rest/actuator/logfile/range/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the first 1024 bytes of the log file.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/logfile/range/http-response.adoc[]
|
||||
include::partial$rest/actuator/logfile/range/http-response.adoc[]
|
||||
@@ -1,83 +1,91 @@
|
||||
[[loggers]]
|
||||
= Loggers (`loggers`)
|
||||
|
||||
The `loggers` endpoint provides access to the application's loggers and the configuration of their levels.
|
||||
|
||||
|
||||
|
||||
[[loggers.all]]
|
||||
== Retrieving All Loggers
|
||||
|
||||
To retrieve the application's loggers, make a `GET` request to `/actuator/loggers`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/loggers/all/curl-request.adoc[]
|
||||
include::partial$rest/actuator/loggers/all/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/loggers/all/http-response.adoc[]
|
||||
include::partial$rest/actuator/loggers/all/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.all.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's loggers.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/loggers/all/response-fields.adoc[]
|
||||
include::partial$rest/actuator/loggers/all/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.single]]
|
||||
== Retrieving a Single Logger
|
||||
|
||||
To retrieve a single logger, make a `GET` request to `/actuator/loggers/{logger.name}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/loggers/single/curl-request.adoc[]
|
||||
include::partial$rest/actuator/loggers/single/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves information about the logger named `com.example`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/loggers/single/http-response.adoc[]
|
||||
include::partial$rest/actuator/loggers/single/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.single.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the requested logger.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/loggers/single/response-fields.adoc[]
|
||||
include::partial$rest/actuator/loggers/single/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.group]]
|
||||
== Retrieving a Single Group
|
||||
|
||||
To retrieve a single group, make a `GET` request to `/actuator/loggers/{group.name}`,
|
||||
as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/loggers/group/curl-request.adoc[]
|
||||
include::partial$rest/actuator/loggers/group/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves information about the logger group named `test`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/loggers/group/http-response.adoc[]
|
||||
include::partial$rest/actuator/loggers/group/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.group.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the requested group.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/loggers/group/response-fields.adoc[]
|
||||
include::partial$rest/actuator/loggers/group/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.setting-level]]
|
||||
== Setting a Log Level
|
||||
|
||||
To set the level of a logger, make a `POST` request to `/actuator/loggers/{logger.name}` with a JSON body that specifies the configured level for the logger, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/loggers/set/curl-request.adoc[]
|
||||
include::partial$rest/actuator/loggers/set/curl-request.adoc[]
|
||||
|
||||
The preceding example sets the `configuredLevel` of the `com.example` logger to `DEBUG`.
|
||||
|
||||
@@ -85,19 +93,21 @@ The preceding example sets the `configuredLevel` of the `com.example` logger to
|
||||
|
||||
[[loggers.setting-level.request-structure]]
|
||||
=== Request Structure
|
||||
|
||||
The request specifies the desired level of the logger.
|
||||
The following table describes the structure of the request:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/loggers/set/request-fields.adoc[]
|
||||
include::partial$rest/actuator/loggers/set/request-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.group-setting-level]]
|
||||
== Setting a Log Level for a Group
|
||||
|
||||
To set the level of a logger, make a `POST` request to `/actuator/loggers/{group.name}` with a JSON body that specifies the configured level for the logger group, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/loggers/setGroup/curl-request.adoc[]
|
||||
include::partial$rest/actuator/loggers/setGroup/curl-request.adoc[]
|
||||
|
||||
The preceding example sets the `configuredLevel` of the `test` logger group to `DEBUG`.
|
||||
|
||||
@@ -105,18 +115,20 @@ The preceding example sets the `configuredLevel` of the `test` logger group to `
|
||||
|
||||
[[loggers.group-setting-level.request-structure]]
|
||||
=== Request Structure
|
||||
|
||||
The request specifies the desired level of the logger group.
|
||||
The following table describes the structure of the request:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/loggers/set/request-fields.adoc[]
|
||||
include::partial$rest/actuator/loggers/set/request-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[loggers.clearing-level]]
|
||||
== Clearing a Log Level
|
||||
|
||||
To clear the level of a logger, make a `POST` request to `/actuator/loggers/{logger.name}` with a JSON body containing an empty object, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/loggers/clear/curl-request.adoc[]
|
||||
include::partial$rest/actuator/loggers/clear/curl-request.adoc[]
|
||||
|
||||
The preceding example clears the configured level of the `com.example` logger.
|
||||
@@ -1,29 +1,32 @@
|
||||
[[mappings]]
|
||||
= Mappings (`mappings`)
|
||||
|
||||
The `mappings` endpoint provides information about the application's request mappings.
|
||||
|
||||
|
||||
|
||||
[[mappings.retrieving]]
|
||||
== Retrieving the Mappings
|
||||
|
||||
To retrieve the mappings, make a `GET` request to `/actuator/mappings`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/mappings/curl-request.adoc[]
|
||||
include::partial$rest/actuator/mappings/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/mappings/http-response.adoc[]
|
||||
include::partial$rest/actuator/mappings/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[mappings.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's mappings.
|
||||
The items found in the response depend on the type of web application (reactive or Servlet-based).
|
||||
The following table describes the structure of the common elements of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/mappings/response-fields.adoc[]
|
||||
include::partial$rest/actuator/mappings/response-fields.adoc[]
|
||||
|
||||
The entries that may be found in `contexts.*.mappings` are described in the following sections.
|
||||
|
||||
@@ -31,38 +34,42 @@ The entries that may be found in `contexts.*.mappings` are described in the foll
|
||||
|
||||
[[mappings.retrieving.response-structure-dispatcher-servlets]]
|
||||
=== Dispatcher Servlets Response Structure
|
||||
|
||||
When using Spring MVC, the response contains details of any `DispatcherServlet` request mappings beneath `contexts.*.mappings.dispatcherServlets`.
|
||||
The following table describes the structure of this section of the response:
|
||||
|
||||
[cols="4,1,2"]
|
||||
include::{snippets}/mappings/response-fields-dispatcher-servlets.adoc[]
|
||||
include::partial$rest/actuator/mappings/response-fields-dispatcher-servlets.adoc[]
|
||||
|
||||
|
||||
|
||||
[[mappings.retrieving.response-structure-servlets]]
|
||||
=== Servlets Response Structure
|
||||
|
||||
When using the Servlet stack, the response contains details of any `Servlet` mappings beneath `contexts.*.mappings.servlets`.
|
||||
The following table describes the structure of this section of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/mappings/response-fields-servlets.adoc[]
|
||||
include::partial$rest/actuator/mappings/response-fields-servlets.adoc[]
|
||||
|
||||
|
||||
|
||||
[[mappings.retrieving.response-structure-servlet-filters]]
|
||||
=== Servlet Filters Response Structure
|
||||
|
||||
When using the Servlet stack, the response contains details of any `Filter` mappings beneath `contexts.*.mappings.servletFilters`.
|
||||
The following table describes the structure of this section of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/mappings/response-fields-servlet-filters.adoc[]
|
||||
include::partial$rest/actuator/mappings/response-fields-servlet-filters.adoc[]
|
||||
|
||||
|
||||
|
||||
[[mappings.retrieving.response-structure-dispatcher-handlers]]
|
||||
=== Dispatcher Handlers Response Structure
|
||||
|
||||
When using Spring WebFlux, the response contains details of any `DispatcherHandler` request mappings beneath `contexts.*.mappings.dispatcherHandlers`.
|
||||
The following table describes the structure of this section of the response:
|
||||
|
||||
[cols="4,1,2"]
|
||||
include::{snippets}/mappings/response-fields-dispatcher-handlers.adoc[]
|
||||
include::partial$rest/actuator/mappings/response-fields-dispatcher-handlers.adoc[]
|
||||
@@ -1,70 +1,77 @@
|
||||
[[metrics]]
|
||||
= Metrics (`metrics`)
|
||||
|
||||
The `metrics` endpoint provides access to application metrics.
|
||||
|
||||
|
||||
|
||||
[[metrics.retrieving-names]]
|
||||
== Retrieving Metric Names
|
||||
|
||||
To retrieve the names of the available metrics, make a `GET` request to `/actuator/metrics`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/metrics/names/curl-request.adoc[]
|
||||
include::partial$rest/actuator/metrics/names/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/metrics/names/http-response.adoc[]
|
||||
include::partial$rest/actuator/metrics/names/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[metrics.retrieving-names.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the metric names.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,2"]
|
||||
include::{snippets}/metrics/names/response-fields.adoc[]
|
||||
include::partial$rest/actuator/metrics/names/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[metrics.retrieving-metric]]
|
||||
== Retrieving a Metric
|
||||
|
||||
To retrieve a metric, make a `GET` request to `/actuator/metrics/{metric.name}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/metrics/metric/curl-request.adoc[]
|
||||
include::partial$rest/actuator/metrics/metric/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves information about the metric named `jvm.memory.max`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/metrics/metric/http-response.adoc[]
|
||||
include::partial$rest/actuator/metrics/metric/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[metrics.retrieving-metric.query-parameters]]
|
||||
=== Query Parameters
|
||||
The endpoint uses query parameters to <<metrics.drilling-down,drill down>> into a metric by using its tags.
|
||||
|
||||
The endpoint uses query parameters to xref:rest/actuator/metrics.adoc#metrics.drilling-down[drill down] into a metric by using its tags.
|
||||
The following table shows the single supported query parameter:
|
||||
|
||||
[cols="2,4"]
|
||||
include::{snippets}/metrics/metric-with-tags/query-parameters.adoc[]
|
||||
include::partial$rest/actuator/metrics/metric-with-tags/query-parameters.adoc[]
|
||||
|
||||
|
||||
|
||||
[[metrics.retrieving-metric.response-structure]]
|
||||
=== Response structure
|
||||
|
||||
The response contains details of the metric.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
include::{snippets}/metrics/metric/response-fields.adoc[]
|
||||
include::partial$rest/actuator/metrics/metric/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[metrics.drilling-down]]
|
||||
== Drilling Down
|
||||
|
||||
To drill down into a metric, make a `GET` request to `/actuator/metrics/{metric.name}` using the `tag` query parameter, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/metrics/metric-with-tags/curl-request.adoc[]
|
||||
include::partial$rest/actuator/metrics/metric-with-tags/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the `jvm.memory.max` metric, where the `area` tag has a value of `nonheap` and the `id` attribute has a value of `Compressed Class Space`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/metrics/metric-with-tags/http-response.adoc[]
|
||||
include::partial$rest/actuator/metrics/metric-with-tags/http-response.adoc[]
|
||||
@@ -1,47 +1,51 @@
|
||||
[[prometheus]]
|
||||
= Prometheus (`prometheus`)
|
||||
|
||||
The `prometheus` endpoint provides Spring Boot application's metrics in the format required for scraping by a Prometheus server.
|
||||
|
||||
|
||||
|
||||
[[prometheus.retrieving]]
|
||||
== Retrieving All Metrics
|
||||
|
||||
To retrieve all metrics, make a `GET` request to `/actuator/prometheus`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/prometheus/all/curl-request.adoc[]
|
||||
include::partial$rest/actuator/prometheus/all/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/prometheus/all/http-response.adoc[]
|
||||
include::partial$rest/actuator/prometheus/all/http-response.adoc[]
|
||||
|
||||
The default response content type is `text/plain;version=0.0.4`.
|
||||
The endpoint can also produce `application/openmetrics-text;version=1.0.0` when called with an appropriate `Accept` header, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/prometheus/openmetrics/curl-request.adoc[]
|
||||
include::partial$rest/actuator/prometheus/openmetrics/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/prometheus/openmetrics/http-response.adoc[]
|
||||
include::partial$rest/actuator/prometheus/openmetrics/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[prometheus.retrieving.query-parameters]]
|
||||
=== Query Parameters
|
||||
|
||||
The endpoint uses query parameters to limit the samples that it returns.
|
||||
The following table shows the supported query parameters:
|
||||
|
||||
[cols="2,4"]
|
||||
include::{snippets}/prometheus/names/query-parameters.adoc[]
|
||||
include::partial$rest/actuator/prometheus/names/query-parameters.adoc[]
|
||||
|
||||
|
||||
|
||||
[[prometheus.retrieving-names]]
|
||||
== Retrieving Filtered Metrics
|
||||
|
||||
To retrieve metrics matching specific names, make a `GET` request to `/actuator/prometheus` with the `includedNames` query parameter, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/prometheus/names/curl-request.adoc[]
|
||||
include::partial$rest/actuator/prometheus/names/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/prometheus/names/http-response.adoc[]
|
||||
include::partial$rest/actuator/prometheus/names/http-response.adoc[]
|
||||
|
||||
@@ -1,96 +1,105 @@
|
||||
[[quartz]]
|
||||
= Quartz (`quartz`)
|
||||
|
||||
The `quartz` endpoint provides information about jobs and triggers that are managed by the Quartz Scheduler.
|
||||
|
||||
|
||||
|
||||
[[quartz.report]]
|
||||
== Retrieving Registered Groups
|
||||
|
||||
Jobs and triggers are managed in groups.
|
||||
To retrieve the list of registered job and trigger groups, make a `GET` request to `/actuator/quartz`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/report/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/report/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/report/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/report/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.report.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains the groups names for registered jobs and triggers.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/quartz/report/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/report/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.job-groups]]
|
||||
== Retrieving Registered Job Names
|
||||
|
||||
To retrieve the list of registered job names, make a `GET` request to `/actuator/quartz/jobs`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/jobs/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/jobs/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/jobs/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/jobs/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.job-groups.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains the registered job names for each group.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/quartz/jobs/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/jobs/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger-groups]]
|
||||
== Retrieving Registered Trigger Names
|
||||
|
||||
To retrieve the list of registered trigger names, make a `GET` request to `/actuator/quartz/triggers`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/triggers/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/triggers/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/triggers/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/triggers/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger-groups.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains the registered trigger names for each group.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/quartz/triggers/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/triggers/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.job-group]]
|
||||
== Retrieving Overview of a Job Group
|
||||
|
||||
To retrieve an overview of the jobs in a particular group, make a `GET` request to `/actuator/quartz/jobs/\{groupName}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/job-group/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/job-group/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the summary for jobs in the `samples` group.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/job-group/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/job-group/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.job-group.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains an overview of jobs in a particular group.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/quartz/job-group/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/job-group/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
@@ -99,36 +108,38 @@ include::{snippets}/quartz/job-group/response-fields.adoc[]
|
||||
|
||||
To retrieve an overview of the triggers in a particular group, make a `GET` request to `/actuator/quartz/triggers/\{groupName}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/trigger-group/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-group/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the summary for triggers in the `tests` group.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/trigger-group/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-group/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger-group.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains an overview of triggers in a particular group.
|
||||
Trigger implementation specific details are available.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/quartz/trigger-group/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-group/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.job]]
|
||||
== Retrieving Details of a Job
|
||||
|
||||
To retrieve the details about a particular job, make a `GET` request to `/actuator/quartz/jobs/\{groupName}/\{jobName}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/job-details/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/job-details/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the details of the job identified by the `samples` group and `jobOne` name.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/job-details/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/job-details/http-response.adoc[]
|
||||
|
||||
If a key in the data map is identified as sensitive, its value is sanitized.
|
||||
|
||||
@@ -136,20 +147,22 @@ If a key in the data map is identified as sensitive, its value is sanitized.
|
||||
|
||||
[[quartz.job.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains the full details of a job including a summary of the triggers associated with it, if any.
|
||||
The triggers are sorted by next fire time and priority.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/job-details/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/job-details/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger]]
|
||||
== Retrieving Details of a Trigger
|
||||
|
||||
To retrieve the details about a particular trigger, make a `GET` request to `/actuator/quartz/triggers/\{groupName}/\{triggerName}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/quartz/trigger-details-cron/curl-request.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-cron/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the details of trigger identified by the `samples` group and `example` name.
|
||||
|
||||
@@ -157,6 +170,7 @@ The preceding example retrieves the details of trigger identified by the `sample
|
||||
|
||||
[[quartz.trigger.common-response-structure]]
|
||||
=== Common Response Structure
|
||||
|
||||
The response has a common structure and an additional object that is specific to the trigger's type.
|
||||
There are five supported types:
|
||||
|
||||
@@ -169,89 +183,94 @@ There are five supported types:
|
||||
The following table describes the structure of the common elements of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/trigger-details-common/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-common/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger.cron-response-structure]]
|
||||
=== Cron Trigger Response Structure
|
||||
|
||||
A cron trigger defines the cron expression that is used to determine when it has to fire.
|
||||
The resulting response for such a trigger implementation is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/trigger-details-cron/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-cron/http-response.adoc[]
|
||||
|
||||
|
||||
Much of the response is common to all trigger types.
|
||||
The structure of the common elements of the response was <<quartz.trigger.common-response-structure,described previously>>.
|
||||
The structure of the common elements of the response was xref:rest/actuator/quartz.adoc#quartz.trigger.common-response-structure[described previously].
|
||||
The following table describes the structure of the parts of the response that are specific to cron triggers:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/trigger-details-cron/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-cron/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger.simple-response-structure]]
|
||||
=== Simple Trigger Response Structure
|
||||
|
||||
A simple trigger is used to fire a Job at a given moment in time, and optionally repeated at a specified interval.
|
||||
The resulting response for such a trigger implementation is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/trigger-details-simple/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-simple/http-response.adoc[]
|
||||
|
||||
|
||||
Much of the response is common to all trigger types.
|
||||
The structure of the common elements of the response was <<quartz.trigger.common-response-structure,described previously>>.
|
||||
The structure of the common elements of the response was xref:rest/actuator/quartz.adoc#quartz.trigger.common-response-structure[described previously].
|
||||
The following table describes the structure of the parts of the response that are specific to simple triggers:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/trigger-details-simple/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-simple/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger.daily-time-interval-response-structure]]
|
||||
=== Daily Time Interval Trigger Response Structure
|
||||
|
||||
A daily time interval trigger is used to fire a Job based upon daily repeating time intervals.
|
||||
The resulting response for such a trigger implementation is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/trigger-details-daily-time-interval/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-daily-time-interval/http-response.adoc[]
|
||||
|
||||
|
||||
Much of the response is common to all trigger types.
|
||||
The structure of the common elements of the response was <<quartz.trigger.common-response-structure,described previously>>.
|
||||
The structure of the common elements of the response was xref:rest/actuator/quartz.adoc#quartz.trigger.common-response-structure[described previously].
|
||||
The following table describes the structure of the parts of the response that are specific to daily time interval triggers:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/trigger-details-daily-time-interval/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-daily-time-interval/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger.calendar-interval-response-structure]]
|
||||
=== Calendar Interval Trigger Response Structure
|
||||
|
||||
A calendar interval trigger is used to fire a Job based upon repeating calendar time intervals.
|
||||
The resulting response for such a trigger implementation is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/trigger-details-calendar-interval/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-calendar-interval/http-response.adoc[]
|
||||
|
||||
|
||||
Much of the response is common to all trigger types.
|
||||
The structure of the common elements of the response was <<quartz.trigger.common-response-structure,described previously>>.
|
||||
The structure of the common elements of the response was xref:rest/actuator/quartz.adoc#quartz.trigger.common-response-structure[described previously].
|
||||
The following table describes the structure of the parts of the response that are specific to calendar interval triggers:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/trigger-details-calendar-interval/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-calendar-interval/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[quartz.trigger.custom-response-structure]]
|
||||
=== Custom Trigger Response Structure
|
||||
|
||||
A custom trigger is any other implementation.
|
||||
The resulting response for such a trigger implementation is similar to the following:
|
||||
|
||||
include::{snippets}/quartz/trigger-details-custom/http-response.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-custom/http-response.adoc[]
|
||||
|
||||
|
||||
Much of the response is common to all trigger types.
|
||||
The structure of the common elements of the response was <<quartz.trigger.common-response-structure,described previously>>.
|
||||
The structure of the common elements of the response was xref:rest/actuator/quartz.adoc#quartz.trigger.common-response-structure[described previously].
|
||||
The following table describes the structure of the parts of the response that are specific to custom triggers:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/quartz/trigger-details-custom/response-fields.adoc[]
|
||||
include::partial$rest/actuator/quartz/trigger-details-custom/response-fields.adoc[]
|
||||
@@ -1,25 +1,28 @@
|
||||
[[scheduled-tasks]]
|
||||
= Scheduled Tasks (`scheduledtasks`)
|
||||
|
||||
The `scheduledtasks` endpoint provides information about the application's scheduled tasks.
|
||||
|
||||
|
||||
|
||||
[[scheduled-tasks.retrieving]]
|
||||
== Retrieving the Scheduled Tasks
|
||||
|
||||
To retrieve the scheduled tasks, make a `GET` request to `/actuator/scheduledtasks`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/scheduled-tasks/curl-request.adoc[]
|
||||
include::partial$rest/actuator/scheduled-tasks/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/scheduled-tasks/http-response.adoc[]
|
||||
include::partial$rest/actuator/scheduled-tasks/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[scheduled-tasks.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application's scheduled tasks.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/scheduled-tasks/response-fields.adoc[]
|
||||
include::partial$rest/actuator/scheduled-tasks/response-fields.adoc[]
|
||||
@@ -1,69 +1,76 @@
|
||||
[[sessions]]
|
||||
= Sessions (`sessions`)
|
||||
|
||||
The `sessions` endpoint provides information about the application's HTTP sessions that are managed by Spring Session.
|
||||
|
||||
|
||||
|
||||
[[sessions.retrieving]]
|
||||
== Retrieving Sessions
|
||||
|
||||
To retrieve the sessions, make a `GET` request to `/actuator/sessions`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/sessions/username/curl-request.adoc[]
|
||||
include::partial$rest/actuator/sessions/username/curl-request.adoc[]
|
||||
|
||||
The preceding examples retrieves all of the sessions for the user whose username is `alice`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/sessions/username/http-response.adoc[]
|
||||
include::partial$rest/actuator/sessions/username/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[sessions.retrieving.query-parameters]]
|
||||
=== Query Parameters
|
||||
|
||||
The endpoint uses query parameters to limit the sessions that it returns.
|
||||
The following table shows the single required query parameter:
|
||||
|
||||
[cols="2,4"]
|
||||
include::{snippets}/sessions/username/query-parameters.adoc[]
|
||||
include::partial$rest/actuator/sessions/username/query-parameters.adoc[]
|
||||
|
||||
|
||||
|
||||
[[sessions.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the matching sessions.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/sessions/username/response-fields.adoc[]
|
||||
include::partial$rest/actuator/sessions/username/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[sessions.retrieving-id]]
|
||||
== Retrieving a Single Session
|
||||
|
||||
To retrieve a single session, make a `GET` request to `/actuator/sessions/\{id}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/sessions/id/curl-request.adoc[]
|
||||
include::partial$rest/actuator/sessions/id/curl-request.adoc[]
|
||||
|
||||
The preceding example retrieves the session with the `id` of `4db5efcc-99cb-4d05-a52c-b49acfbb7ea9`.
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/sessions/id/http-response.adoc[]
|
||||
include::partial$rest/actuator/sessions/id/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[sessions.retrieving-id.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the requested session.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/sessions/id/response-fields.adoc[]
|
||||
include::partial$rest/actuator/sessions/id/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[sessions.deleting]]
|
||||
== Deleting a Session
|
||||
|
||||
To delete a session, make a `DELETE` request to `/actuator/sessions/\{id}`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/sessions/delete/curl-request.adoc[]
|
||||
include::partial$rest/actuator/sessions/delete/curl-request.adoc[]
|
||||
|
||||
The preceding example deletes the session with the `id` of `4db5efcc-99cb-4d05-a52c-b49acfbb7ea9`.
|
||||
@@ -1,25 +1,28 @@
|
||||
[[shutdown]]
|
||||
= Shutdown (`shutdown`)
|
||||
|
||||
The `shutdown` endpoint is used to shut down the application.
|
||||
|
||||
|
||||
|
||||
[[shutdown.shutting-down]]
|
||||
== Shutting Down the Application
|
||||
|
||||
To shut down the application, make a `POST` request to `/actuator/shutdown`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/shutdown/curl-request.adoc[]
|
||||
include::partial$rest/actuator/shutdown/curl-request.adoc[]
|
||||
|
||||
A response similar to the following is produced:
|
||||
|
||||
include::{snippets}/shutdown/http-response.adoc[]
|
||||
include::partial$rest/actuator/shutdown/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[shutdown.shutting-down.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the result of the shutdown request.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,3"]
|
||||
include::{snippets}/shutdown/response-fields.adoc[]
|
||||
include::partial$rest/actuator/shutdown/response-fields.adoc[]
|
||||
@@ -1,43 +1,48 @@
|
||||
[[startup]]
|
||||
= Application Startup (`startup`)
|
||||
|
||||
The `startup` endpoint provides information about the application's startup sequence.
|
||||
|
||||
|
||||
|
||||
[[startup.retrieving]]
|
||||
== Retrieving the Application Startup Steps
|
||||
|
||||
The application startup steps can either be retrieved as a snapshot (`GET`) or drained from the buffer (`POST`).
|
||||
|
||||
|
||||
|
||||
[[startup.retrieving.snapshot]]
|
||||
=== Retrieving a snapshot of the Application Startup Steps
|
||||
|
||||
To retrieve the steps recorded so far during the application startup phase, make a `GET` request to `/actuator/startup`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/startup-snapshot/curl-request.adoc[]
|
||||
include::partial$rest/actuator/startup-snapshot/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/startup-snapshot/http-response.adoc[]
|
||||
include::partial$rest/actuator/startup-snapshot/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[startup.retrieving.drain]]
|
||||
=== Draining the Application Startup Steps
|
||||
|
||||
To drain and return the steps recorded so far during the application startup phase, make a `POST` request to `/actuator/startup`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/startup/curl-request.adoc[]
|
||||
include::partial$rest/actuator/startup/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/startup/http-response.adoc[]
|
||||
include::partial$rest/actuator/startup/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[startup.retrieving.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the application startup steps.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="2,1,3"]
|
||||
include::{snippets}/startup/response-fields.adoc[]
|
||||
include::partial$rest/actuator/startup/response-fields.adoc[]
|
||||
@@ -1,38 +1,42 @@
|
||||
[[threaddump]]
|
||||
= Thread Dump (`threaddump`)
|
||||
|
||||
The `threaddump` endpoint provides a thread dump from the application's JVM.
|
||||
|
||||
|
||||
|
||||
[[threaddump.retrieving-json]]
|
||||
== Retrieving the Thread Dump as JSON
|
||||
|
||||
To retrieve the thread dump as JSON, make a `GET` request to `/actuator/threaddump` with an appropriate `Accept` header, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/threaddump/json/curl-request.adoc[]
|
||||
include::partial$rest/actuator/threaddump/json/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/threaddump/json/http-response.adoc[]
|
||||
include::partial$rest/actuator/threaddump/json/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
[[threaddump.retrieving-json.response-structure]]
|
||||
=== Response Structure
|
||||
|
||||
The response contains details of the JVM's threads.
|
||||
The following table describes the structure of the response:
|
||||
|
||||
[cols="3,1,2"]
|
||||
include::{snippets}/threaddump/json/response-fields.adoc[]
|
||||
include::partial$rest/actuator/threaddump/json/response-fields.adoc[]
|
||||
|
||||
|
||||
|
||||
[[threaddump.retrieving-text]]
|
||||
== Retrieving the Thread Dump as Text
|
||||
|
||||
To retrieve the thread dump as text, make a `GET` request to `/actuator/threaddump` that
|
||||
accepts `text/plain`, as shown in the following curl-based example:
|
||||
|
||||
include::{snippets}/threaddump/text/curl-request.adoc[]
|
||||
include::partial$rest/actuator/threaddump/text/curl-request.adoc[]
|
||||
|
||||
The resulting response is similar to the following:
|
||||
|
||||
include::{snippets}/threaddump/text/http-response.adoc[]
|
||||
include::partial$rest/actuator/threaddump/text/http-response.adoc[]
|
||||
@@ -0,0 +1,25 @@
|
||||
* xref:api:rest/actuator/index.adoc[]
|
||||
** xref:api:rest/actuator/auditevents.adoc[]
|
||||
** xref:api:rest/actuator/beans.adoc[]
|
||||
** xref:api:rest/actuator/caches.adoc[]
|
||||
** xref:api:rest/actuator/conditions.adoc[]
|
||||
** xref:api:rest/actuator/configprops.adoc[]
|
||||
** xref:api:rest/actuator/env.adoc[]
|
||||
** xref:api:rest/actuator/flyway.adoc[]
|
||||
** xref:api:rest/actuator/health.adoc[]
|
||||
** xref:api:rest/actuator/heapdump.adoc[]
|
||||
** xref:api:rest/actuator/httpexchanges.adoc[]
|
||||
** xref:api:rest/actuator/info.adoc[]
|
||||
** xref:api:rest/actuator/integrationgraph.adoc[]
|
||||
** xref:api:rest/actuator/liquibase.adoc[]
|
||||
** xref:api:rest/actuator/logfile.adoc[]
|
||||
** xref:api:rest/actuator/loggers.adoc[]
|
||||
** xref:api:rest/actuator/mappings.adoc[]
|
||||
** xref:api:rest/actuator/metrics.adoc[]
|
||||
** xref:api:rest/actuator/prometheus.adoc[]
|
||||
** xref:api:rest/actuator/quartz.adoc[]
|
||||
** xref:api:rest/actuator/scheduledtasks.adoc[]
|
||||
** xref:api:rest/actuator/sessions.adoc[]
|
||||
** xref:api:rest/actuator/shutdown.adoc[]
|
||||
** xref:api:rest/actuator/startup.adoc[]
|
||||
** xref:api:rest/actuator/threaddump.adoc[]
|
||||
@@ -1,103 +0,0 @@
|
||||
[[spring-boot-actuator-web-api-documentation]]
|
||||
= Spring Boot Actuator Web API Documentation
|
||||
Andy Wilkinson; Stephane Nicoll
|
||||
v{gradle-project-version}
|
||||
:!version-label:
|
||||
:doctype: book
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:numbered:
|
||||
:icons: font
|
||||
:hide-uri-scheme:
|
||||
:docinfo: shared,private
|
||||
:attribute-missing: warn
|
||||
|
||||
|
||||
|
||||
This API documentation describes Spring Boot Actuators web endpoints.
|
||||
|
||||
|
||||
|
||||
[[overview]]
|
||||
== Overview
|
||||
Before you proceed, you should read the following topics:
|
||||
|
||||
* <<overview.endpoint-urls>>
|
||||
* <<overview.timestamps>>
|
||||
|
||||
NOTE: In order to get the correct JSON responses documented below, Jackson must be available.
|
||||
|
||||
|
||||
|
||||
[[overview.endpoint-urls]]
|
||||
=== URLs
|
||||
By default, all web endpoints are available beneath the path `/actuator` with URLs of
|
||||
the form `/actuator/\{id}`. The `/actuator` base path can be configured by using the
|
||||
`management.endpoints.web.base-path` property, as shown in the following example:
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
management.endpoints.web.base-path=/manage
|
||||
----
|
||||
|
||||
The preceding `application.properties` example changes the form of the endpoint URLs from
|
||||
`/actuator/\{id}` to `/manage/\{id}`. For example, the URL `info` endpoint would become
|
||||
`/manage/info`.
|
||||
|
||||
|
||||
|
||||
[[overview.timestamps]]
|
||||
=== Timestamps
|
||||
All timestamps that are consumed by the endpoints, either as query parameters or in the
|
||||
request body, must be formatted as an offset date and time as specified in
|
||||
https://en.wikipedia.org/wiki/ISO_8601[ISO 8601].
|
||||
|
||||
|
||||
|
||||
include::endpoints/auditevents.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/beans.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/caches.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/conditions.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/configprops.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/env.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/flyway.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/health.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/heapdump.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/httpexchanges.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/info.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/integrationgraph.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/liquibase.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/logfile.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/loggers.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/mappings.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/metrics.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/prometheus.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/quartz.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/scheduledtasks.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/sessions.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/shutdown.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/startup.adoc[leveloffset=+1]
|
||||
|
||||
include::endpoints/threaddump.adoc[leveloffset=+1]
|
||||
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id "java"
|
||||
id "org.asciidoctor.jvm.convert"
|
||||
id "org.antora"
|
||||
id "org.springframework.boot.conventions"
|
||||
id "org.springframework.boot.deployed"
|
||||
id 'org.jetbrains.kotlin.jvm'
|
||||
@@ -9,25 +9,12 @@ plugins {
|
||||
description = "Spring Boot Docs"
|
||||
|
||||
configurations {
|
||||
actuatorApiDocumentation
|
||||
autoConfiguration
|
||||
configurationProperties
|
||||
gradlePluginDocumentation
|
||||
mavenPluginDocumentation
|
||||
remoteSpringApplicationExample
|
||||
springApplicationExample
|
||||
testSlices
|
||||
asciidoctorExtensions {
|
||||
resolutionStrategy {
|
||||
eachDependency { dependency ->
|
||||
// Downgrade SnakeYAML as Asciidoctor fails due to an incompatibility
|
||||
// in the Pysch gem
|
||||
if (dependency.requested.group.equals("org.yaml")) {
|
||||
dependency.useVersion("1.33")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
antoraContent
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -53,16 +40,6 @@ plugins.withType(EclipsePlugin) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
actuatorApiDocumentation(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure", configuration: "documentation"))
|
||||
|
||||
asciidoctorExtensions("io.spring.asciidoctor:spring-asciidoctor-extensions-spring-boot")
|
||||
asciidoctorExtensions("io.spring.asciidoctor:spring-asciidoctor-extensions-section-ids")
|
||||
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure"))
|
||||
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-autoconfigure"))
|
||||
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-devtools"))
|
||||
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-docker-compose"))
|
||||
asciidoctorExtensions(project(path: ":spring-boot-project:spring-boot-testcontainers"))
|
||||
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-autoconfigure", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure", configuration: "autoConfigurationMetadata"))
|
||||
autoConfiguration(project(path: ":spring-boot-project:spring-boot-devtools", configuration: "autoConfigurationMetadata"))
|
||||
@@ -77,8 +54,6 @@ dependencies {
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-test-autoconfigure", configuration: "configurationPropertiesMetadata"))
|
||||
configurationProperties(project(path: ":spring-boot-project:spring-boot-testcontainers", configuration: "configurationPropertiesMetadata"))
|
||||
|
||||
gradlePluginDocumentation(project(path: ":spring-boot-project:spring-boot-tools:spring-boot-gradle-plugin", configuration: "documentation"))
|
||||
|
||||
implementation(project(path: ":spring-boot-project:spring-boot-actuator"))
|
||||
implementation(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure"))
|
||||
implementation(project(path: ":spring-boot-project:spring-boot-autoconfigure"))
|
||||
@@ -184,8 +159,6 @@ dependencies {
|
||||
implementation("org.junit.jupiter:junit-jupiter")
|
||||
implementation("org.yaml:snakeyaml")
|
||||
|
||||
mavenPluginDocumentation(project(path: ":spring-boot-project:spring-boot-tools:spring-boot-maven-plugin", configuration: "documentation"))
|
||||
|
||||
remoteSpringApplicationExample(platform(project(":spring-boot-project:spring-boot-dependencies")))
|
||||
remoteSpringApplicationExample(project(":spring-boot-project:spring-boot-devtools"))
|
||||
remoteSpringApplicationExample(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-logging"))
|
||||
@@ -194,6 +167,10 @@ dependencies {
|
||||
springApplicationExample(platform(project(":spring-boot-project:spring-boot-dependencies")))
|
||||
springApplicationExample(project(path: ":spring-boot-project:spring-boot-starters:spring-boot-starter-web"))
|
||||
|
||||
antoraContent(project(path: ":spring-boot-project:spring-boot-actuator-autoconfigure", configuration: "antoraContent"))
|
||||
antoraContent(project(path: ":spring-boot-project:spring-boot-tools:spring-boot-gradle-plugin", configuration: "antoraContent"))
|
||||
antoraContent(project(path: ":spring-boot-project:spring-boot-tools:spring-boot-maven-plugin", configuration: "antoraContent"))
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-actuator-autoconfigure"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
@@ -206,16 +183,14 @@ dependencies {
|
||||
testSlices(project(path: ":spring-boot-project:spring-boot-test-autoconfigure", configuration: "testSliceMetadata"))
|
||||
}
|
||||
|
||||
task dependencyVersions(type: org.springframework.boot.build.constraints.ExtractVersionConstraints) {
|
||||
enforcedPlatform(":spring-boot-project:spring-boot-dependencies")
|
||||
}
|
||||
|
||||
task aggregatedJavadoc(type: Javadoc) {
|
||||
dependsOn dependencyVersions
|
||||
project.rootProject.gradle.projectsEvaluated {
|
||||
Set<Project> publishedProjects = rootProject.subprojects.findAll { it != project }
|
||||
.findAll { it.plugins.hasPlugin(JavaPlugin) && it.plugins.hasPlugin(MavenPublishPlugin) }
|
||||
.findAll { !it.path.contains(":spring-boot-tools:") }
|
||||
.findAll { !it.path.contains(":spring-boot-tools:") ||
|
||||
it.path.contains(":spring-boot-tools:spring-boot-buildpack-platform") ||
|
||||
it.path.contains(":spring-boot-tools:spring-boot-loader-tools") }
|
||||
.findAll { !it.name.startsWith('spring-boot-starter') }
|
||||
dependsOn publishedProjects.javadoc
|
||||
source publishedProjects.javadoc.source
|
||||
@@ -247,33 +222,33 @@ task aggregatedJavadoc(type: Javadoc) {
|
||||
|
||||
task documentTestSlices(type: org.springframework.boot.build.test.autoconfigure.DocumentTestSlices) {
|
||||
testSlices = configurations.testSlices
|
||||
outputFile = file("${buildDir}/docs/generated/test-auto-configuration/documented-slices.adoc")
|
||||
outputFile = file("${buildDir}/generated/docs/test-auto-configuration/documented-slices.adoc")
|
||||
}
|
||||
|
||||
task documentStarters(type: org.springframework.boot.build.starters.DocumentStarters) {
|
||||
outputDir = file("${buildDir}/docs/generated/using/starters/")
|
||||
outputDir = file("${buildDir}/generated/docs/using/starters/")
|
||||
}
|
||||
|
||||
task documentAutoConfigurationClasses(type: org.springframework.boot.build.autoconfigure.DocumentAutoConfigurationClasses) {
|
||||
autoConfiguration = configurations.autoConfiguration
|
||||
outputDir = file("${buildDir}/docs/generated/auto-configuration-classes/documented-auto-configuration-classes/")
|
||||
outputDir = file("${buildDir}/generated/docs/auto-configuration-classes/documented-auto-configuration-classes/")
|
||||
}
|
||||
|
||||
task documentDependencyVersions(type: org.springframework.boot.build.constraints.DocumentConstrainedVersions) {
|
||||
task documentDependencyVersionCoordinates(type: org.springframework.boot.build.constraints.DocumentConstrainedVersions) {
|
||||
dependsOn dependencyVersions
|
||||
constrainedVersions.set(providers.provider { dependencyVersions.constrainedVersions })
|
||||
outputFile = file("${buildDir}/docs/generated/dependency-versions/documented-coordinates.adoc")
|
||||
outputFile = file("${buildDir}/generated/docs/dependency-versions/documented-coordinates.adoc")
|
||||
}
|
||||
|
||||
task documentVersionProperties(type: org.springframework.boot.build.constraints.DocumentVersionProperties) {
|
||||
task documentDependencyVersionProperties(type: org.springframework.boot.build.constraints.DocumentVersionProperties) {
|
||||
dependsOn dependencyVersions
|
||||
versionProperties.set(providers.provider { dependencyVersions.versionProperties})
|
||||
outputFile = file("${buildDir}/docs/generated/dependency-versions/documented-properties.adoc")
|
||||
outputFile = file("${buildDir}/generated/docs/dependency-versions/documented-properties.adoc")
|
||||
}
|
||||
|
||||
task documentConfigurationProperties(type: org.springframework.boot.build.context.properties.DocumentConfigurationProperties) {
|
||||
configurationPropertyMetadata = configurations.configurationProperties
|
||||
outputDir = file("${buildDir}/docs/generated/")
|
||||
outputDir = file("${buildDir}/generated/docs/application-properties")
|
||||
}
|
||||
|
||||
task documentDevtoolsPropertyDefaults(type: org.springframework.boot.build.devtools.DocumentDevtoolsPropertyDefaults) {}
|
||||
@@ -306,203 +281,92 @@ task runLoggingFormatExample(type: org.springframework.boot.build.docs.Applicati
|
||||
normalizeTomcatPort()
|
||||
}
|
||||
|
||||
tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) {
|
||||
outputs.doNotCacheIf("This task uses log files as inputs which contain changing data (timestamp, pid)") { true }
|
||||
dependsOn dependencyVersions
|
||||
inputs.files(runRemoteSpringApplicationExample).withPropertyName("runRemoteSpringApplicationExample").withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
inputs.files(runSpringApplicationExample).withPropertyName("runSpringApplicationExample").withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
inputs.files(runLoggingFormatExample).withPropertyName("runLoggingFormatExample").withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
asciidoctorj {
|
||||
fatalWarnings = ['^((?!successfully validated).)*$']
|
||||
def getRelativeExamplesPath(var outputs) {
|
||||
def fileName = outputs.files.singleFile.name
|
||||
'example$example-output/' + fileName
|
||||
}
|
||||
|
||||
def antoraRootAggregateContent = tasks.register("antoraRootAggregateContent", Zip) {
|
||||
destinationDirectory = layout.buildDirectory.dir('generated/docs/antora-content')
|
||||
archiveClassifier = "root-aggregate-content"
|
||||
from("src/main") {
|
||||
into "modules/ROOT/examples"
|
||||
}
|
||||
doFirst {
|
||||
def versionConstraints = dependencyVersions.versionConstraints
|
||||
def toAntoraVersion = version -> {
|
||||
String formatted = version.split("\\.").take(2).join('.')
|
||||
return version.endsWith("-SNAPSHOT") ? formatted + "-SNAPSHOT" : formatted
|
||||
from(project.configurations.configurationProperties) {
|
||||
eachFile {
|
||||
it.path = it.file.toString()
|
||||
.replaceFirst('/build/(?:classes|resources)/java/main/', '/')
|
||||
.replaceFirst('^.*/([^/]+)/META-INF/(spring-configuration-metadata\\.json)$', 'modules/ROOT/partials/$1/$2')
|
||||
}
|
||||
attributes "hibernate-version": versionConstraints["org.hibernate.orm:hibernate-core"].split("\\.").take(2).join('.'),
|
||||
"jetty-version": versionConstraints["org.eclipse.jetty:jetty-server"],
|
||||
"jooq-version": versionConstraints["org.jooq:jooq"],
|
||||
"lettuce-version": versionConstraints["io.lettuce:lettuce-core"],
|
||||
"native-build-tools-version": nativeBuildToolsVersion,
|
||||
"spring-amqp-version": versionConstraints["org.springframework.amqp:spring-amqp"],
|
||||
"spring-batch-version": versionConstraints["org.springframework.batch:spring-batch-core"],
|
||||
"spring-batch-version-antora": toAntoraVersion(versionConstraints["org.springframework.batch:spring-batch-core"]),
|
||||
"spring-boot-version": project.version,
|
||||
"spring-data-commons-version": versionConstraints["org.springframework.data:spring-data-commons"],
|
||||
"spring-data-couchbase-version": versionConstraints["org.springframework.data:spring-data-couchbase"],
|
||||
"spring-data-jdbc-version": versionConstraints["org.springframework.data:spring-data-jdbc"],
|
||||
"spring-data-jpa-version": versionConstraints["org.springframework.data:spring-data-jpa"],
|
||||
"spring-data-mongodb-version": versionConstraints["org.springframework.data:spring-data-mongodb"],
|
||||
"spring-data-neo4j-version": versionConstraints["org.springframework.data:spring-data-neo4j"],
|
||||
"spring-data-r2dbc-version": versionConstraints["org.springframework.data:spring-data-r2dbc"],
|
||||
"spring-data-rest-version": versionConstraints["org.springframework.data:spring-data-rest-core"],
|
||||
"spring-framework-version": versionConstraints["org.springframework:spring-core"],
|
||||
"spring-framework-version-antora": toAntoraVersion(versionConstraints["org.springframework:spring-core"]),
|
||||
"spring-graphql-version-antora": toAntoraVersion(versionConstraints["org.springframework.graphql:spring-graphql"]),
|
||||
"spring-integration-version-antora": toAntoraVersion(versionConstraints["org.springframework.integration:spring-integration-core"]),
|
||||
"spring-kafka-version": versionConstraints["org.springframework.kafka:spring-kafka"],
|
||||
"spring-pulsar-version": versionConstraints["org.springframework.pulsar:spring-pulsar"],
|
||||
"spring-security-version-antora": toAntoraVersion(versionConstraints["org.springframework.security:spring-security-core"]),
|
||||
"spring-authorization-server-version-antora": toAntoraVersion(versionConstraints["org.springframework.security:spring-security-oauth2-authorization-server"]),
|
||||
"spring-webservices-version": versionConstraints["org.springframework.ws:spring-ws-core"],
|
||||
"tomcat-version": tomcatVersion.split("\\.").take(2).join('.'),
|
||||
"remote-spring-application-output": runRemoteSpringApplicationExample.outputs.files.singleFile,
|
||||
"spring-application-output": runSpringApplicationExample.outputs.files.singleFile,
|
||||
"logging-format-output": runLoggingFormatExample.outputs.files.singleFile
|
||||
}
|
||||
from(runRemoteSpringApplicationExample) {
|
||||
into "modules/ROOT/examples"
|
||||
}
|
||||
from(documentDevtoolsPropertyDefaults) {
|
||||
into "modules/ROOT/partials/propertydefaults"
|
||||
}
|
||||
from(documentStarters) {
|
||||
into "modules/ROOT/partials/starters"
|
||||
}
|
||||
from(documentTestSlices) {
|
||||
into "modules/appendix/partials/slices"
|
||||
}
|
||||
from(runSpringApplicationExample) {
|
||||
into "modules/ROOT/partials/application"
|
||||
}
|
||||
from(runLoggingFormatExample) {
|
||||
into "modules/ROOT/partials/logging"
|
||||
}
|
||||
from(documentDependencyVersionCoordinates) {
|
||||
into "modules/appendix/partials/dependency-versions"
|
||||
}
|
||||
from(documentDependencyVersionProperties) {
|
||||
into "modules/appendix/partials/dependency-versions"
|
||||
}
|
||||
from(documentAutoConfigurationClasses) {
|
||||
into "modules/appendix/partials/auto-configuration-classes"
|
||||
}
|
||||
from(documentConfigurationProperties) {
|
||||
into "modules/appendix/partials/configuration-properties"
|
||||
}
|
||||
from(tasks.getByName("generateAntoraYml")) {
|
||||
into "modules"
|
||||
}
|
||||
}
|
||||
|
||||
asciidoctor {
|
||||
sources {
|
||||
include "*.singleadoc"
|
||||
}
|
||||
}
|
||||
|
||||
task asciidoctorPdf(type: org.asciidoctor.gradle.jvm.AsciidoctorTask) {
|
||||
sources {
|
||||
include "*.singleadoc"
|
||||
}
|
||||
}
|
||||
|
||||
task asciidoctorMultipage(type: org.asciidoctor.gradle.jvm.AsciidoctorTask) {
|
||||
sources {
|
||||
include "*.adoc"
|
||||
}
|
||||
}
|
||||
|
||||
syncDocumentationSourceForAsciidoctor {
|
||||
dependsOn documentTestSlices
|
||||
dependsOn documentStarters
|
||||
dependsOn documentAutoConfigurationClasses
|
||||
dependsOn documentDependencyVersions
|
||||
dependsOn documentVersionProperties
|
||||
dependsOn documentConfigurationProperties
|
||||
dependsOn documentDevtoolsPropertyDefaults
|
||||
from("${buildDir}/docs/generated") {
|
||||
into "asciidoc"
|
||||
}
|
||||
from("src/main/java") {
|
||||
into "main/java"
|
||||
}
|
||||
from("src/test/java") {
|
||||
into "test/java"
|
||||
}
|
||||
from("src/main/kotlin") {
|
||||
into "main/kotlin"
|
||||
}
|
||||
from("src/main/groovy") {
|
||||
into "main/groovy"
|
||||
}
|
||||
from("src/main/resources") {
|
||||
into "main/resources"
|
||||
}
|
||||
}
|
||||
|
||||
syncDocumentationSourceForAsciidoctorMultipage {
|
||||
dependsOn documentTestSlices
|
||||
dependsOn documentStarters
|
||||
dependsOn documentAutoConfigurationClasses
|
||||
dependsOn documentDependencyVersions
|
||||
dependsOn documentVersionProperties
|
||||
dependsOn documentConfigurationProperties
|
||||
dependsOn documentDevtoolsPropertyDefaults
|
||||
from("${buildDir}/docs/generated") {
|
||||
into "asciidoc"
|
||||
}
|
||||
from("src/main/java") {
|
||||
into "main/java"
|
||||
}
|
||||
from("src/test/java") {
|
||||
into "test/java"
|
||||
}
|
||||
from("src/main/kotlin") {
|
||||
into "main/kotlin"
|
||||
}
|
||||
from("src/main/groovy") {
|
||||
into "main/groovy"
|
||||
}
|
||||
from("src/main/resources") {
|
||||
into "main/resources"
|
||||
}
|
||||
}
|
||||
|
||||
syncDocumentationSourceForAsciidoctorPdf {
|
||||
dependsOn documentTestSlices
|
||||
dependsOn documentStarters
|
||||
dependsOn documentAutoConfigurationClasses
|
||||
dependsOn documentDependencyVersions
|
||||
dependsOn documentVersionProperties
|
||||
dependsOn documentConfigurationProperties
|
||||
dependsOn documentDevtoolsPropertyDefaults
|
||||
from("${buildDir}/docs/generated") {
|
||||
into "asciidoc"
|
||||
}
|
||||
from("src/main/java") {
|
||||
into "main/java"
|
||||
}
|
||||
from("src/test/java") {
|
||||
into "test/java"
|
||||
}
|
||||
from("src/main/kotlin") {
|
||||
into "main/kotlin"
|
||||
}
|
||||
from("src/main/groovy") {
|
||||
into "main/groovy"
|
||||
}
|
||||
from("src/main/resources") {
|
||||
into "main/resources"
|
||||
}
|
||||
}
|
||||
|
||||
task zip(type: Zip) {
|
||||
dependsOn asciidoctor,
|
||||
asciidoctorMultipage,
|
||||
asciidoctorPdf,
|
||||
configurations.gradlePluginDocumentation,
|
||||
configurations.actuatorApiDocumentation,
|
||||
configurations.mavenPluginDocumentation
|
||||
duplicatesStrategy "fail"
|
||||
from(asciidoctor.outputDir) {
|
||||
into "reference/htmlsingle"
|
||||
}
|
||||
from(asciidoctorPdf.outputDir) {
|
||||
into "reference/pdf"
|
||||
include "index.pdf"
|
||||
rename { "spring-boot-reference.pdf" }
|
||||
}
|
||||
from(asciidoctorMultipage.outputDir) {
|
||||
into "reference/html"
|
||||
}
|
||||
def antoraApiCatalogContent = tasks.register("antoraApiCatalogContent", Zip) {
|
||||
destinationDirectory = layout.buildDirectory.dir('generated/docs/antora-content')
|
||||
archiveClassifier = "api-catalog-content"
|
||||
from(aggregatedJavadoc) {
|
||||
into "api"
|
||||
}
|
||||
into("gradle-plugin") {
|
||||
from {
|
||||
zipTree(configurations.gradlePluginDocumentation.singleFile)
|
||||
}
|
||||
}
|
||||
into("actuator-api") {
|
||||
from {
|
||||
zipTree(configurations.actuatorApiDocumentation.singleFile)
|
||||
}
|
||||
}
|
||||
into("maven-plugin") {
|
||||
from {
|
||||
zipTree(configurations.mavenPluginDocumentation.singleFile)
|
||||
}
|
||||
into "java"
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives zip
|
||||
def copyAntoraContentDependencies = tasks.register("copyAntoraContentDependencies", Copy) {
|
||||
into layout.buildDirectory.dir('generated/docs/antora-dependencies-content')
|
||||
from(configurations.antoraContent)
|
||||
rename("spring-boot-actuator-autoconfigure", "spring-boot-docs")
|
||||
rename("spring-boot-maven-plugin", "spring-boot-docs")
|
||||
rename("spring-boot-gradle-plugin", "spring-boot-docs")
|
||||
}
|
||||
|
||||
tasks.named("antora") {
|
||||
inputs.files(antoraRootAggregateContent, antoraApiCatalogContent, copyAntoraContentDependencies)
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
def mavenPublication = publishing.publications.getByName("maven");
|
||||
configurations.antoraContent.dependencies.forEach { dependency ->
|
||||
dependency.dependencyProject.configurations.getByName(dependency.targetConfiguration)
|
||||
.artifacts.forEach(mavenPublication::artifact)
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
artifact zip
|
||||
getByName("maven") {
|
||||
artifact antoraRootAggregateContent
|
||||
artifact antoraApiCatalogContent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
name: spring-boot
|
||||
ext:
|
||||
zip_contents_collector:
|
||||
include:
|
||||
- name: root
|
||||
classifier: aggregate-content
|
||||
- name: api
|
||||
classifier: catalog-content
|
||||
module: api
|
||||
destination: content-catalog
|
||||
@@ -1,10 +1,9 @@
|
||||
[[getting-help]]
|
||||
= Getting Help
|
||||
include::attributes.adoc[]
|
||||
:navicon: question
|
||||
= Community
|
||||
|
||||
If you have trouble with Spring Boot, we would like to help.
|
||||
|
||||
* Try the <<howto#howto, How-to documents>>.
|
||||
* Try the xref:how-to:index.adoc[How-to documents].
|
||||
They provide solutions to the most common questions.
|
||||
* Learn the Spring basics.
|
||||
Spring Boot builds on many other Spring projects.
|
||||
@@ -15,4 +14,4 @@ We monitor https://stackoverflow.com[stackoverflow.com] for questions tagged wit
|
||||
* Report bugs with Spring Boot at https://github.com/spring-projects/spring-boot/issues.
|
||||
|
||||
NOTE: All of Spring Boot is open source, including the documentation.
|
||||
If you find problems with the docs or if you want to improve them, please {spring-boot-code}[get involved].
|
||||
If you find problems with the docs or if you want to improve them, please {url-github}[get involved].
|
||||
@@ -0,0 +1,156 @@
|
||||
:navtitle: Documentation
|
||||
:navicon: book
|
||||
[[documentation]]
|
||||
= Documentation Overview
|
||||
|
||||
This section provides a brief overview of Spring Boot reference documentation.
|
||||
It serves as a map for the rest of the document.
|
||||
|
||||
|
||||
|
||||
[[documentation.first-steps]]
|
||||
== First Steps
|
||||
|
||||
If you are getting started with Spring Boot or 'Spring' in general, start with the following topics:
|
||||
|
||||
* *From scratch:* xref:index.adoc[Overview] | xref:system-requirements.adoc[Requirements] | xref:installing.adoc[Installation]
|
||||
* *Tutorial:* xref:tutorial:first-application/index.adoc[Part 1] | xref:tutorial:first-application/index.adoc#getting-started.first-application.code[Part 2]
|
||||
* *Running your example:* xref:tutorial:first-application/index.adoc#getting-started.first-application.run[Part 1] | xref:tutorial:first-application/index.adoc#getting-started.first-application.executable-jar[Part 2]
|
||||
|
||||
|
||||
|
||||
[[documentation.upgrading]]
|
||||
== Upgrading From an Earlier Version
|
||||
|
||||
You should always ensure that you are running a {url-github-wiki}/Supported-Versions[supported version] of Spring Boot.
|
||||
|
||||
Depending on the version that you are upgrading to, you can find some additional tips here:
|
||||
|
||||
* *From 1.x:* xref:upgrading.adoc#upgrading.from-1x[Upgrading from 1.x]
|
||||
* *To a new feature release:* xref:upgrading.adoc#upgrading.to-feature[Upgrading to New Feature Release]
|
||||
* *Spring Boot CLI:* xref:upgrading.adoc#upgrading.cli[Upgrading the Spring Boot CLI]
|
||||
|
||||
|
||||
|
||||
[[documentation.using]]
|
||||
== Developing With Spring Boot
|
||||
|
||||
Ready to actually start using Spring Boot? xref:reference:using/index.adoc[We have you covered]:
|
||||
|
||||
* *Build systems:* xref:reference:using/build-systems.adoc#using.build-systems.maven[Maven] | xref:reference:using/build-systems.adoc#using.build-systems.gradle[Gradle] | xref:reference:using/build-systems.adoc#using.build-systems.ant[Ant] | xref:reference:using/build-systems.adoc#using.build-systems.starters[Starters]
|
||||
* *Best practices:* xref:reference:using/structuring-your-code.adoc[Code Structure] | xref:reference:using/configuration-classes.adoc[@Configuration] | xref:reference:using/auto-configuration.adoc[@EnableAutoConfiguration] | xref:reference:using/spring-beans-and-dependency-injection.adoc[Beans and Dependency Injection]
|
||||
* *Running your code:* xref:reference:using/running-your-application.adoc#using.running-your-application.from-an-ide[IDE] | xref:reference:using/running-your-application.adoc#using.running-your-application.as-a-packaged-application[Packaged] | xref:reference:using/running-your-application.adoc#using.running-your-application.with-the-maven-plugin[Maven] | xref:reference:using/running-your-application.adoc#using.running-your-application.with-the-gradle-plugin[Gradle]
|
||||
* *Packaging your app:* xref:reference:using/packaging-for-production.adoc[Production jars]
|
||||
* *Spring Boot CLI:* xref:cli:index.adoc[Using the CLI]
|
||||
|
||||
|
||||
|
||||
[[documentation.features]]
|
||||
== Learning About Spring Boot Features
|
||||
|
||||
Need more details about Spring Boot's core features?
|
||||
xref:reference:features/index.adoc[The following content is for you]:
|
||||
|
||||
* *Spring Application:* xref:reference:features/spring-application.adoc[SpringApplication]
|
||||
* *External Configuration:* xref:reference:features/external-config.adoc[External Configuration]
|
||||
* *Profiles:* xref:reference:features/profiles.adoc[Profiles]
|
||||
* *Logging:* xref:reference:features/logging.adoc[Logging]
|
||||
|
||||
|
||||
|
||||
[[documentation.web]]
|
||||
== Web
|
||||
|
||||
If you develop Spring Boot web applications, take a look at the following content:
|
||||
|
||||
* *Servlet Web Applications:* xref:reference:web/servlet.adoc[Spring MVC, Jersey, Embedded Servlet Containers]
|
||||
* *Reactive Web Applications:* xref:reference:web/reactive.adoc[Spring Webflux, Embedded Servlet Containers]
|
||||
* *Graceful Shutdown:* xref:reference:web/graceful-shutdown.adoc[Graceful Shutdown]
|
||||
* *Spring Security:* xref:reference:web/spring-security.adoc[Default Security Configuration, Auto-configuration for OAuth2, SAML]
|
||||
* *Spring Session:* xref:reference:web/spring-session.adoc[Auto-configuration for Spring Session]
|
||||
* *Spring HATEOAS:* xref:reference:web/spring-hateoas.adoc[Auto-configuration for Spring HATEOAS]
|
||||
|
||||
|
||||
|
||||
[[documentation.data]]
|
||||
== Data
|
||||
|
||||
If your application deals with a datastore, you can see how to configure that here:
|
||||
|
||||
* *SQL:* xref:reference:data/sql.adoc[Configuring a SQL Datastore, Embedded Database support, Connection pools, and more.]
|
||||
* *NOSQL:* xref:reference:data/nosql.adoc[Auto-configuration for NOSQL stores such as Redis, MongoDB, Neo4j, and others.]
|
||||
|
||||
|
||||
|
||||
[[documentation.messaging]]
|
||||
== Messaging
|
||||
|
||||
If your application uses any messaging protocol, see one or more of the following sections:
|
||||
|
||||
* *JMS:* xref:reference:messaging/jms.adoc[Auto-configuration for ActiveMQ and Artemis, Sending and Receiving messages through JMS]
|
||||
* *AMQP:* xref:reference:messaging/amqp.adoc[Auto-configuration for RabbitMQ]
|
||||
* *Kafka:* xref:reference:messaging/kafka.adoc[Auto-configuration for Spring Kafka]
|
||||
* *Pulsar:* xref:reference:messaging/pulsar.adoc[Auto-configuration for Spring for Apache Pulsar]
|
||||
* *RSocket:* xref:reference:messaging/rsocket.adoc[Auto-configuration for Spring Framework's RSocket Support]
|
||||
* *Spring Integration:* xref:reference:messaging/spring-integration.adoc[Auto-configuration for Spring Integration]
|
||||
|
||||
|
||||
|
||||
[[documentation.io]]
|
||||
== IO
|
||||
|
||||
If your application needs IO capabilities, see one or more of the following sections:
|
||||
|
||||
* *Caching:* xref:reference:io/caching.adoc[Caching support with EhCache, Hazelcast, Infinispan, and more]
|
||||
* *Quartz:* xref:reference:io/quartz.adoc[Quartz Scheduling]
|
||||
* *Mail:* xref:reference:io/email.adoc[Sending Email]
|
||||
* *Validation:* xref:reference:io/validation.adoc[JSR-303 Validation]
|
||||
* *REST Clients:* xref:reference:io/rest-client.adoc[Calling REST Services with RestTemplate and WebClient]
|
||||
* *Webservices:* xref:reference:io/webservices.adoc[Auto-configuration for Spring Web Services]
|
||||
* *JTA:* xref:reference:io/jta.adoc[Distributed Transactions with JTA]
|
||||
|
||||
|
||||
|
||||
[[documentation.container-images]]
|
||||
== Container Images
|
||||
|
||||
Spring Boot provides first-class support for building efficient container images. You can read more about it here:
|
||||
|
||||
* *Efficient Container Images:* xref:reference:container-images/efficient-images.adoc[Tips to optimize container images such as Docker images]
|
||||
* *Dockerfiles:* xref:reference:container-images/dockerfiles.adoc[Building container images using dockerfiles]
|
||||
* *Cloud Native Buildpacks:* xref:reference:container-images/cloud-native-buildpacks.adoc[Support for Cloud Native Buildpacks with Maven and Gradle]
|
||||
|
||||
|
||||
|
||||
[[documentation.actuator]]
|
||||
== Moving to Production
|
||||
|
||||
When you are ready to push your Spring Boot application to production, we have xref:how-to:actuator.adoc[some tricks] that you might like:
|
||||
|
||||
* *Management endpoints:* xref:reference:actuator/endpoints.adoc[Overview]
|
||||
* *Connection options:* xref:reference:actuator/monitoring.adoc[HTTP] | xref:reference:actuator/jmx.adoc[JMX]
|
||||
* *Monitoring:* xref:reference:actuator/metrics.adoc[Metrics] | xref:reference:actuator/auditing.adoc[Auditing] | xref:reference:actuator/http-exchanges.adoc[HTTP Exchanges] | xref:reference:actuator/process-monitoring.adoc[Process]
|
||||
|
||||
|
||||
|
||||
[[documentation.native-images]]
|
||||
== GraalVM Native Images
|
||||
|
||||
Spring Boot applications can be converted into native executables using GraalVM.
|
||||
You can read more about our native image support here:
|
||||
|
||||
* *GraalVM Native Images:* xref:reference:native-image/introducing-graalvm-native-images.adoc[Introduction] | xref:reference:native-image/introducing-graalvm-native-images.adoc#native-image.introducing-graalvm-native-images.key-differences-with-jvm-deployments[Key Differences with the JVM] | xref:reference:native-image/introducing-graalvm-native-images.adoc#native-image.introducing-graalvm-native-images.understanding-aot-processing[Ahead-of-Time Processing]
|
||||
* *Getting Started:* xref:reference:native-image/developing-your-first-application.adoc#native-image.developing-your-first-application.buildpacks[Buildpacks] | xref:reference:native-image/developing-your-first-application.adoc#native-image.developing-your-first-application.native-build-tools[Native Build Tools]
|
||||
* *Testing:* xref:reference:native-image/testing-native-applications.adoc#native-image.testing.with-the-jvm[JVM] | xref:reference:native-image/testing-native-applications.adoc#native-image.testing.with-native-build-tools[Native Build Tools]
|
||||
* *Advanced Topics:* xref:reference:native-image/advanced-topics.adoc#native-image.advanced.nested-configuration-properties[Nested Configuration Properties] | xref:reference:native-image/advanced-topics.adoc#native-image.advanced.converting-executable-jars[Converting JARs] | xref:reference:native-image/advanced-topics.adoc#native-image.advanced.known-limitations[Known Limitations]
|
||||
|
||||
|
||||
|
||||
[[documentation.advanced]]
|
||||
== Advanced Topics
|
||||
|
||||
Finally, we have a few topics for more advanced users:
|
||||
|
||||
* *Spring Boot Applications Deployment:* xref:reference:deployment/cloud.adoc[Cloud Deployment] | xref:reference:deployment/installing.adoc[OS Service]
|
||||
* *Build tool plugins:* xref:maven-plugin:index.adoc[Maven] | xref:gradle-plugin:index.adoc[Gradle]
|
||||
* *Appendix:* xref:appendix:application-properties/index.adoc[Application Properties] | xref:specification:configuration-metadata/index.adoc[Configuration Metadata] | xref:appendix:auto-configuration-classes/index.adoc[Auto-configuration Classes] | xref:appendix:test-auto-configuration/index.adoc[Test Auto-configuration Annotations] | xref:specification:executable-jar/index.adoc[Executable Jars] | xref:appendix:dependency-versions/index.adoc[Dependency Versions]
|
||||
@@ -1,5 +1,7 @@
|
||||
[[getting-started.introducing-spring-boot]]
|
||||
== Introducing Spring Boot
|
||||
:navtitle: Overview
|
||||
:navicon: home
|
||||
= Spring Boot
|
||||
|
||||
Spring Boot helps you to create stand-alone, production-grade Spring-based applications that you can run.
|
||||
We take an opinionated view of the Spring platform and third-party libraries, so that you can get started with minimum fuss.
|
||||
Most Spring Boot applications need very little Spring configuration.
|
||||
@@ -1,21 +1,24 @@
|
||||
:navicon: gift
|
||||
[[getting-started.installing]]
|
||||
== Installing Spring Boot
|
||||
= Installing Spring Boot
|
||||
|
||||
Spring Boot can be used with "`classic`" Java development tools or installed as a command line tool.
|
||||
Either way, you need https://www.java.com[Java SDK v17] or higher.
|
||||
Before you begin, you should check your current Java installation by using the following command:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
[source,shell]
|
||||
----
|
||||
$ java -version
|
||||
$ java -version
|
||||
----
|
||||
|
||||
If you are new to Java development or if you want to experiment with Spring Boot, you might want to try the <<getting-started#getting-started.installing.cli, Spring Boot CLI>> (Command Line Interface) first.
|
||||
If you are new to Java development or if you want to experiment with Spring Boot, you might want to try the xref:installing.adoc#getting-started.installing.cli[Spring Boot CLI] (Command Line Interface) first.
|
||||
Otherwise, read on for "`classic`" installation instructions.
|
||||
|
||||
|
||||
|
||||
[[getting-started.installing.java]]
|
||||
=== Installation Instructions for the Java Developer
|
||||
== Installation Instructions for the Java Developer
|
||||
|
||||
You can use Spring Boot in the same way as any standard Java library.
|
||||
To do so, include the appropriate `+spring-boot-*.jar+` files on your classpath.
|
||||
Spring Boot does not require any special tools integration, so you can use any IDE or text editor.
|
||||
@@ -26,7 +29,8 @@ Although you _could_ copy Spring Boot jars, we generally recommend that you use
|
||||
|
||||
|
||||
[[getting-started.installing.java.maven]]
|
||||
==== Maven Installation
|
||||
=== Maven Installation
|
||||
|
||||
Spring Boot is compatible with Apache Maven 3.6.3 or later.
|
||||
If you do not already have Maven installed, you can follow the instructions at https://maven.apache.org.
|
||||
|
||||
@@ -36,35 +40,37 @@ Ubuntu users can run `sudo apt-get install maven`.
|
||||
Windows users with https://chocolatey.org/[Chocolatey] can run `choco install maven` from an elevated (administrator) prompt.
|
||||
|
||||
Spring Boot dependencies use the `org.springframework.boot` group id.
|
||||
Typically, your Maven POM file inherits from the `spring-boot-starter-parent` project and declares dependencies to one or more <<using#using.build-systems.starters,"`Starters`">>.
|
||||
Spring Boot also provides an optional <<build-tool-plugins#build-tool-plugins.maven, Maven plugin>> to create executable jars.
|
||||
Typically, your Maven POM file inherits from the `spring-boot-starter-parent` project and declares dependencies to one or more xref:reference:using/build-systems.adoc#using.build-systems.starters["`Starters`"].
|
||||
Spring Boot also provides an optional xref:maven-plugin:index.adoc[Maven plugin] to create executable jars.
|
||||
|
||||
More details on getting started with Spring Boot and Maven can be found in the {spring-boot-maven-plugin-docs}#getting-started[Getting Started section] of the Maven plugin's reference guide.
|
||||
More details on getting started with Spring Boot and Maven can be found in the xref:maven-plugin:getting-started.adoc[Getting Started section] of the Maven plugin's reference guide.
|
||||
|
||||
|
||||
|
||||
[[getting-started.installing.java.gradle]]
|
||||
==== Gradle Installation
|
||||
=== Gradle Installation
|
||||
|
||||
Spring Boot is compatible with Gradle 7.x (7.5 or later) and 8.x.
|
||||
If you do not already have Gradle installed, you can follow the instructions at https://gradle.org.
|
||||
|
||||
Spring Boot dependencies can be declared by using the `org.springframework.boot` `group`.
|
||||
Typically, your project declares dependencies to one or more <<using#using.build-systems.starters, "`Starters`">>.
|
||||
Spring Boot provides a useful <<build-tool-plugins#build-tool-plugins.gradle, Gradle plugin>> that can be used to simplify dependency declarations and to create executable jars.
|
||||
Typically, your project declares dependencies to one or more xref:reference:using/build-systems.adoc#using.build-systems.starters["`Starters`"].
|
||||
Spring Boot provides a useful xref:gradle-plugin:index.adoc[Gradle plugin] that can be used to simplify dependency declarations and to create executable jars.
|
||||
|
||||
.Gradle Wrapper
|
||||
****
|
||||
The Gradle Wrapper provides a nice way of "`obtaining`" Gradle when you need to build a project.
|
||||
It is a small script and library that you commit alongside your code to bootstrap the build process.
|
||||
See {gradle-docs}/gradle_wrapper.html for details.
|
||||
See {url-gradle-docs}/gradle_wrapper.html for details.
|
||||
****
|
||||
|
||||
More details on getting started with Spring Boot and Gradle can be found in the {spring-boot-gradle-plugin-docs}#getting-started[Getting Started section] of the Gradle plugin's reference guide.
|
||||
More details on getting started with Spring Boot and Gradle can be found in the xref:gradle-plugin:getting-started.adoc[Getting Started section] of the Gradle plugin's reference guide.
|
||||
|
||||
|
||||
|
||||
[[getting-started.installing.cli]]
|
||||
=== Installing the Spring Boot CLI
|
||||
== Installing the Spring Boot CLI
|
||||
|
||||
The Spring Boot CLI (Command Line Interface) is a command line tool that you can use to quickly prototype with Spring.
|
||||
|
||||
You do not need to use the CLI to work with Spring Boot, but it is a quick way to get a Spring application off the ground without an IDE.
|
||||
@@ -72,44 +78,46 @@ You do not need to use the CLI to work with Spring Boot, but it is a quick way t
|
||||
|
||||
|
||||
[[getting-started.installing.cli.manual-installation]]
|
||||
==== Manual Installation
|
||||
=== Manual Installation
|
||||
|
||||
ifeval::["{artifact-release-type}" == "snapshot"]
|
||||
You can download one of the `spring-boot-cli-\*-bin.zip` or `spring-boot-cli-*-bin.tar.gz` files from the {artifact-download-repo}/org/springframework/boot/spring-boot-cli/{spring-boot-version}/[Spring software repository].
|
||||
You can download one of the `spring-boot-cli-\*-bin.zip` or `spring-boot-cli-*-bin.tar.gz` files from the {url-artifact-repository}/org/springframework/boot/spring-boot-cli/{version-spring-boot}/[Spring software repository].
|
||||
endif::[]
|
||||
ifeval::["{artifact-release-type}" != "snapshot"]
|
||||
You can download the Spring CLI distribution from one of the following locations:
|
||||
|
||||
* {artifact-download-repo}/org/springframework/boot/spring-boot-cli/{spring-boot-version}/spring-boot-cli-{spring-boot-version}-bin.zip[spring-boot-cli-{spring-boot-version}-bin.zip]
|
||||
* {artifact-download-repo}/org/springframework/boot/spring-boot-cli/{spring-boot-version}/spring-boot-cli-{spring-boot-version}-bin.tar.gz[spring-boot-cli-{spring-boot-version}-bin.tar.gz]
|
||||
* {url-artifact-repository}/org/springframework/boot/spring-boot-cli/{version-spring-boot}/spring-boot-cli-{version-spring-boot}-bin.zip[spring-boot-cli-{version-spring-boot}-bin.zip]
|
||||
* {url-artifact-repository}/org/springframework/boot/spring-boot-cli/{version-spring-boot}/spring-boot-cli-{version-spring-boot}-bin.tar.gz[spring-boot-cli-{version-spring-boot}-bin.tar.gz]
|
||||
endif::[]
|
||||
|
||||
|
||||
Once downloaded, follow the {github-raw}/spring-boot-project/spring-boot-tools/spring-boot-cli/src/main/content/INSTALL.txt[INSTALL.txt] instructions from the unpacked archive.
|
||||
Once downloaded, follow the {url-github-raw}/spring-boot-project/spring-boot-tools/spring-boot-cli/src/main/content/INSTALL.txt[INSTALL.txt] instructions from the unpacked archive.
|
||||
In summary, there is a `spring` script (`spring.bat` for Windows) in a `bin/` directory in the `.zip` file.
|
||||
Alternatively, you can use `java -jar` with the `.jar` file (the script helps you to be sure that the classpath is set correctly).
|
||||
|
||||
|
||||
|
||||
[[getting-started.installing.cli.sdkman]]
|
||||
==== Installation with SDKMAN!
|
||||
=== Installation with SDKMAN!
|
||||
|
||||
SDKMAN! (The Software Development Kit Manager) can be used for managing multiple versions of various binary SDKs, including Groovy and the Spring Boot CLI.
|
||||
Get SDKMAN! from https://sdkman.io and install Spring Boot by using the following commands:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim,attributes"]
|
||||
[source,shell,subs="verbatim,attributes"]
|
||||
----
|
||||
$ sdk install springboot
|
||||
$ spring --version
|
||||
Spring CLI v{spring-boot-version}
|
||||
$ sdk install springboot
|
||||
$ spring --version
|
||||
Spring CLI v{version-spring-boot}
|
||||
----
|
||||
|
||||
If you develop features for the CLI and want access to the version you built, use the following commands:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim,attributes"]
|
||||
[source,shell,subs="verbatim,attributes"]
|
||||
----
|
||||
$ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-{spring-boot-version}-bin/spring-{spring-boot-version}/
|
||||
$ sdk default springboot dev
|
||||
$ spring --version
|
||||
Spring CLI v{spring-boot-version}
|
||||
$ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-{version-spring-boot}-bin/spring-{version-spring-boot}/
|
||||
$ sdk default springboot dev
|
||||
$ spring --version
|
||||
Spring CLI v{version-spring-boot}
|
||||
----
|
||||
|
||||
The preceding instructions install a local instance of `spring` called the `dev` instance.
|
||||
@@ -117,33 +125,34 @@ It points at your target build location, so every time you rebuild Spring Boot,
|
||||
|
||||
You can see it by running the following command:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim,attributes"]
|
||||
[source,shell,subs="verbatim,attributes"]
|
||||
----
|
||||
$ sdk ls springboot
|
||||
$ sdk ls springboot
|
||||
|
||||
================================================================================
|
||||
Available Springboot Versions
|
||||
================================================================================
|
||||
> + dev
|
||||
* {spring-boot-version}
|
||||
================================================================================
|
||||
Available Springboot Versions
|
||||
================================================================================
|
||||
> + dev
|
||||
* {version-spring-boot}
|
||||
|
||||
================================================================================
|
||||
+ - local version
|
||||
* - installed
|
||||
> - currently in use
|
||||
================================================================================
|
||||
================================================================================
|
||||
+ - local version
|
||||
* - installed
|
||||
> - currently in use
|
||||
================================================================================
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[getting-started.installing.cli.homebrew]]
|
||||
==== OSX Homebrew Installation
|
||||
=== OSX Homebrew Installation
|
||||
|
||||
If you are on a Mac and use https://brew.sh/[Homebrew], you can install the Spring Boot CLI by using the following commands:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
[source,shell]
|
||||
----
|
||||
$ brew tap spring-io/tap
|
||||
$ brew install spring-boot
|
||||
$ brew tap spring-io/tap
|
||||
$ brew install spring-boot
|
||||
----
|
||||
|
||||
Homebrew installs `spring` to `/usr/local/bin`.
|
||||
@@ -154,28 +163,30 @@ In that case, run `brew update` and try again.
|
||||
|
||||
|
||||
[[getting-started.installing.cli.macports]]
|
||||
==== MacPorts Installation
|
||||
=== MacPorts Installation
|
||||
|
||||
If you are on a Mac and use https://www.macports.org/[MacPorts], you can install the Spring Boot CLI by using the following command:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
[source,shell]
|
||||
----
|
||||
$ sudo port install spring-boot-cli
|
||||
$ sudo port install spring-boot-cli
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[getting-started.installing.cli.completion]]
|
||||
==== Command-line Completion
|
||||
=== Command-line Completion
|
||||
|
||||
The Spring Boot CLI includes scripts that provide command completion for the https://en.wikipedia.org/wiki/Bash_%28Unix_shell%29[BASH] and https://en.wikipedia.org/wiki/Z_shell[zsh] shells.
|
||||
You can `source` the script (also named `spring`) in any shell or put it in your personal or system-wide bash completion initialization.
|
||||
On a Debian system, the system-wide scripts are in `<installation location>/shell-completion/bash` and all scripts in that directory are executed when a new shell starts.
|
||||
For example, to run the script manually if you have installed by using SDKMAN!, use the following commands:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
[source,shell]
|
||||
----
|
||||
$ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
|
||||
$ spring <HIT TAB HERE>
|
||||
grab help jar run test version
|
||||
$ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
|
||||
$ spring <HIT TAB HERE>
|
||||
grab help jar run test version
|
||||
----
|
||||
|
||||
NOTE: If you install the Spring Boot CLI by using Homebrew or MacPorts, the command-line completion scripts are automatically registered with your shell.
|
||||
@@ -183,13 +194,14 @@ NOTE: If you install the Spring Boot CLI by using Homebrew or MacPorts, the comm
|
||||
|
||||
|
||||
[[getting-started.installing.cli.scoop]]
|
||||
==== Windows Scoop Installation
|
||||
=== Windows Scoop Installation
|
||||
|
||||
If you are on a Windows and use https://scoop.sh/[Scoop], you can install the Spring Boot CLI by using the following commands:
|
||||
|
||||
[indent=0]
|
||||
[source,shell]
|
||||
----
|
||||
> scoop bucket add extras
|
||||
> scoop install springboot
|
||||
$ scoop bucket add extras
|
||||
$ scoop install springboot
|
||||
----
|
||||
|
||||
Scoop installs `spring` to `~/scoop/apps/springboot/current/bin`.
|
||||
@@ -1,7 +1,9 @@
|
||||
:navicon: server
|
||||
[[getting-started.system-requirements]]
|
||||
== System Requirements
|
||||
Spring Boot {spring-boot-version} requires https://www.java.com[Java 17] and is compatible up to and including Java 21.
|
||||
{spring-framework-docs}/[Spring Framework {spring-framework-version}] or above is also required.
|
||||
= System Requirements
|
||||
|
||||
Spring Boot {version-spring-boot} requires https://www.java.com[Java 17] and is compatible up to and including Java 21.
|
||||
{url-spring-framework-docs}/[Spring Framework {version-spring-framework}] or above is also required.
|
||||
|
||||
Explicit build support is provided for the following build tools:
|
||||
|
||||
@@ -18,7 +20,8 @@ Explicit build support is provided for the following build tools:
|
||||
|
||||
|
||||
[[getting-started.system-requirements.servlet-containers]]
|
||||
=== Servlet Containers
|
||||
== Servlet Containers
|
||||
|
||||
Spring Boot supports the following embedded servlet containers:
|
||||
|
||||
|===
|
||||
@@ -39,8 +42,9 @@ You can also deploy Spring Boot applications to any servlet 5.0+ compatible cont
|
||||
|
||||
|
||||
[[getting-started.system-requirements.graal]]
|
||||
=== GraalVM Native Images
|
||||
Spring Boot applications can be <<native-image#native-image.introducing-graalvm-native-images,converted into a Native Image>> using GraalVM {graal-version} or above.
|
||||
== GraalVM Native Images
|
||||
|
||||
Spring Boot applications can be xref:reference:native-image/introducing-graalvm-native-images.adoc[converted into a Native Image] using GraalVM {version-graal} or above.
|
||||
|
||||
Images can be created using the https://github.com/graalvm/native-build-tools[native build tools] Gradle/Maven plugins or `native-image` tool provided by GraalVM.
|
||||
You can also create native images using the https://github.com/paketo-buildpacks/native-image[native-image Paketo buildpack].
|
||||
@@ -51,8 +55,8 @@ The following versions are supported:
|
||||
| Name | Version
|
||||
|
||||
| GraalVM Community
|
||||
| {graal-version}
|
||||
| {version-graal}
|
||||
|
||||
| Native Build Tools
|
||||
| {native-build-tools-version}
|
||||
| {version-native-build-tools}
|
||||
|===
|
||||
@@ -0,0 +1,47 @@
|
||||
:navicon: rocket
|
||||
[[upgrading]]
|
||||
= Upgrading Spring Boot
|
||||
|
||||
Instructions for how to upgrade from earlier versions of Spring Boot are provided on the project {url-github-wiki}[wiki].
|
||||
Follow the links in the {url-github-wiki}#release-notes[release notes] section to find the version that you want to upgrade to.
|
||||
|
||||
Upgrading instructions are always the first item in the release notes.
|
||||
If you are more than one release behind, please make sure that you also review the release notes of the versions that you jumped.
|
||||
|
||||
|
||||
|
||||
[[upgrading.from-1x]]
|
||||
== Upgrading From 1.x
|
||||
|
||||
If you are upgrading from the `1.x` release of Spring Boot, check the {url-github-wiki}/Spring-Boot-2.0-Migration-Guide["`migration guide`" on the project wiki] that provides detailed upgrade instructions.
|
||||
Check also the {url-github-wiki}["`release notes`"] for a list of "`new and noteworthy`" features for each release.
|
||||
|
||||
|
||||
|
||||
[[upgrading.to-feature]]
|
||||
== Upgrading to a New Feature Release
|
||||
|
||||
When upgrading to a new feature release, some properties may have been renamed or removed.
|
||||
Spring Boot provides a way to analyze your application's environment and print diagnostics at startup, but also temporarily migrate properties at runtime for you.
|
||||
To enable that feature, add the following dependency to your project:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-properties-migrator</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
WARNING: Properties that are added late to the environment, such as when using `@PropertySource`, will not be taken into account.
|
||||
|
||||
NOTE: Once you finish the migration, please make sure to remove this module from your project's dependencies.
|
||||
|
||||
|
||||
|
||||
[[upgrading.cli]]
|
||||
== Upgrading the Spring Boot CLI
|
||||
|
||||
To upgrade an existing CLI installation, use the appropriate package manager command (for example, `brew upgrade`).
|
||||
If you manually installed the CLI, follow the xref:installing.adoc#getting-started.installing.cli.manual-installation[standard instructions], remembering to update your `PATH` environment variable to remove any older references.
|
||||
@@ -0,0 +1,6 @@
|
||||
* xref:index.adoc[]
|
||||
* xref:documentation.adoc[]
|
||||
* xref:community.adoc[]
|
||||
* xref:system-requirements.adoc[]
|
||||
* xref:installing.adoc[]
|
||||
* xref:upgrading.adoc[]
|
||||
@@ -0,0 +1,4 @@
|
||||
* Java APIs
|
||||
** xref:api:java/index.html[Spring Boot]
|
||||
** xref:gradle-plugin:api/java/index.html[Gradle Plugin]
|
||||
** xref:maven-plugin:api/java/index.html[Maven Plugin]
|
||||
@@ -0,0 +1,5 @@
|
||||
* Rest APIs
|
||||
+
|
||||
--
|
||||
include::api:partial$nav-actuator-rest-api.adoc[]
|
||||
--
|
||||
@@ -0,0 +1,48 @@
|
||||
[appendix]
|
||||
[[appendix.application-properties]]
|
||||
= Common Application Properties
|
||||
|
||||
Various properties can be specified inside your `application.properties` file, inside your `application.yaml` file, or as command line switches.
|
||||
This appendix provides a list of common Spring Boot properties and references to the underlying classes that consume them.
|
||||
|
||||
TIP: Spring Boot provides various conversion mechanism with advanced value formatting, make sure to review xref:reference:features/external-config.adoc#features.external-config.typesafe-configuration-properties.conversion[the properties conversion section].
|
||||
|
||||
NOTE: Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list.
|
||||
Also, you can define your own properties.
|
||||
|
||||
|
||||
include::partial$configuration-properties/core.adoc[]
|
||||
|
||||
include::partial$configuration-properties/cache.adoc[]
|
||||
|
||||
include::partial$configuration-properties/mail.adoc[]
|
||||
|
||||
include::partial$configuration-properties/json.adoc[]
|
||||
|
||||
include::partial$configuration-properties/data.adoc[]
|
||||
|
||||
include::partial$configuration-properties/transaction.adoc[]
|
||||
|
||||
include::partial$configuration-properties/data-migration.adoc[]
|
||||
|
||||
include::partial$configuration-properties/integration.adoc[]
|
||||
|
||||
include::partial$configuration-properties/web.adoc[]
|
||||
|
||||
include::partial$configuration-properties/templating.adoc[]
|
||||
|
||||
include::partial$configuration-properties/server.adoc[]
|
||||
|
||||
include::partial$configuration-properties/security.adoc[]
|
||||
|
||||
include::partial$configuration-properties/rsocket.adoc[]
|
||||
|
||||
include::partial$configuration-properties/actuator.adoc[]
|
||||
|
||||
include::partial$configuration-properties/devtools.adoc[]
|
||||
|
||||
include::partial$configuration-properties/docker-compose.adoc[]
|
||||
|
||||
include::partial$configuration-properties/testcontainers.adoc[]
|
||||
|
||||
include::partial$configuration-properties/testing.adoc[]
|
||||
@@ -1,5 +1,6 @@
|
||||
[[appendix.auto-configuration-classes.actuator]]
|
||||
== spring-boot-actuator-autoconfigure
|
||||
= spring-boot-actuator-autoconfigure
|
||||
|
||||
The following auto-configuration classes are from the `spring-boot-actuator-autoconfigure` module:
|
||||
|
||||
include::documented-auto-configuration-classes/spring-boot-actuator-autoconfigure.adoc[]
|
||||
include::partial$/auto-configuration-classes/spring-boot-actuator-autoconfigure.adoc[]
|
||||
@@ -1,5 +1,6 @@
|
||||
[[appendix.auto-configuration-classes.core]]
|
||||
== spring-boot-autoconfigure
|
||||
= spring-boot-autoconfigure
|
||||
|
||||
The following auto-configuration classes are from the `spring-boot-autoconfigure` module:
|
||||
|
||||
include::documented-auto-configuration-classes/spring-boot-autoconfigure.adoc[]
|
||||
include::partial$/auto-configuration-classes/spring-boot-autoconfigure.adoc[]
|
||||
@@ -1,16 +1,7 @@
|
||||
[appendix]
|
||||
[[appendix.auto-configuration-classes]]
|
||||
= Auto-configuration Classes
|
||||
include::attributes.adoc[]
|
||||
|
||||
|
||||
|
||||
This appendix contains details of all of the auto-configuration classes provided by Spring Boot, with links to documentation and source code.
|
||||
Remember to also look at the conditions report in your application for more details of which features are switched on.
|
||||
(To do so, start the app with `--debug` or `-Ddebug` or, in an Actuator application, use the `conditions` endpoint).
|
||||
|
||||
|
||||
|
||||
include::auto-configuration-classes/core.adoc[]
|
||||
|
||||
include::auto-configuration-classes/actuator.adoc[]
|
||||
@@ -1,7 +1,7 @@
|
||||
[[appendix.dependency-versions.coordinates]]
|
||||
== Managed Dependency Coordinates
|
||||
= Managed Dependency Coordinates
|
||||
|
||||
The following table provides details of all of the dependency versions that are provided by Spring Boot in its CLI (Command Line Interface), Maven dependency management, and Gradle plugin.
|
||||
When you declare a dependency on one of these artifacts without declaring a version, the version listed in the table is used.
|
||||
|
||||
include::documented-coordinates.adoc[]
|
||||
include::partial$dependency-versions/documented-coordinates.adoc[]
|
||||
@@ -1,14 +1,5 @@
|
||||
[appendix]
|
||||
[[appendix.dependency-versions]]
|
||||
= Dependency Versions
|
||||
include::attributes.adoc[]
|
||||
|
||||
|
||||
|
||||
This appendix provides details of the dependencies that are managed by Spring Boot.
|
||||
|
||||
|
||||
|
||||
include::dependency-versions/coordinates.adoc[]
|
||||
|
||||
include::dependency-versions/properties.adoc[]
|
||||
@@ -1,8 +1,8 @@
|
||||
[[appendix.dependency-versions.properties]]
|
||||
== Version Properties
|
||||
= Version Properties
|
||||
|
||||
The following table provides all properties that can be used to override the versions managed by Spring Boot.
|
||||
Browse the {spring-boot-code}/spring-boot-project/spring-boot-dependencies/build.gradle[`spring-boot-dependencies` build.gradle] for a complete list of dependencies.
|
||||
You can learn how to customize these versions in your application in the <<build-tool-plugins#build-tool-plugins,Build Tool Plugins documentation>>.
|
||||
Browse the {code-spring-boot}/spring-boot-project/spring-boot-dependencies/build.gradle[`spring-boot-dependencies` build.gradle] for a complete list of dependencies.
|
||||
You can learn how to customize these versions in your application in the xref:build-tool-plugin:index.adoc[Build Tool Plugins documentation].
|
||||
|
||||
include::documented-properties.adoc[]
|
||||
include::partial$dependency-versions/documented-properties.adoc[]
|
||||
@@ -1,12 +1,5 @@
|
||||
[appendix]
|
||||
[[appendix.test-auto-configuration]]
|
||||
= Test Auto-configuration Annotations
|
||||
include::attributes.adoc[]
|
||||
|
||||
|
||||
|
||||
This appendix describes the `@...Test` auto-configuration annotations that Spring Boot provides to test slices of your application.
|
||||
|
||||
|
||||
|
||||
include::test-auto-configuration/slices.adoc[]
|
||||
@@ -1,6 +1,6 @@
|
||||
[[appendix.test-auto-configuration.slices]]
|
||||
== Test Slices
|
||||
= Test Slices
|
||||
|
||||
The following table lists the various `@...Test` annotations that can be used to test slices of your application and the auto-configuration that they import by default:
|
||||
|
||||
include::documented-slices.adoc[]
|
||||
include::partial$slices/documented-slices.adoc[]
|
||||
@@ -0,0 +1,13 @@
|
||||
* Appendix
|
||||
|
||||
** xref:appendix:application-properties/index.adoc[]
|
||||
** xref:appendix:auto-configuration-classes/index.adoc[]
|
||||
*** xref:appendix:auto-configuration-classes/core.adoc[]
|
||||
*** xref:appendix:auto-configuration-classes/actuator.adoc[]
|
||||
|
||||
** xref:appendix:test-auto-configuration/index.adoc[]
|
||||
*** xref:appendix:test-auto-configuration/slices.adoc[]
|
||||
|
||||
** xref:appendix:dependency-versions/index.adoc[]
|
||||
*** xref:appendix:dependency-versions/coordinates.adoc[]
|
||||
*** xref:appendix:dependency-versions/properties.adoc[]
|
||||
@@ -1,40 +1,43 @@
|
||||
[[build-tool-plugins.antlib]]
|
||||
== Spring Boot AntLib Module
|
||||
= Spring Boot AntLib Module
|
||||
|
||||
The Spring Boot AntLib module provides basic Spring Boot support for Apache Ant.
|
||||
You can use the module to create executable jars.
|
||||
To use the module, you need to declare an additional `spring-boot` namespace in your `build.xml`, as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<project xmlns:ivy="antlib:org.apache.ivy.ant"
|
||||
xmlns:spring-boot="antlib:org.springframework.boot.ant"
|
||||
name="myapp" default="build">
|
||||
...
|
||||
</project>
|
||||
<project xmlns:ivy="antlib:org.apache.ivy.ant"
|
||||
xmlns:spring-boot="antlib:org.springframework.boot.ant"
|
||||
name="myapp" default="build">
|
||||
...
|
||||
</project>
|
||||
----
|
||||
|
||||
You need to remember to start Ant using the `-lib` option, as shown in the following example:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim,attributes"]
|
||||
[source,shell,subs="verbatim,attributes"]
|
||||
----
|
||||
$ ant -lib <directory containing spring-boot-antlib-{spring-boot-version}.jar>
|
||||
$ ant -lib <directory containing spring-boot-antlib-{version-spring-boot}.jar>
|
||||
----
|
||||
|
||||
TIP: The "`Using Spring Boot`" section includes a more complete example of <<using#using.build-systems.ant, using Apache Ant with `spring-boot-antlib`>>.
|
||||
TIP: The "`Using Spring Boot`" section includes a more complete example of xref:reference:using/build-systems.adoc#using.build-systems.ant[using Apache Ant with `spring-boot-antlib`].
|
||||
|
||||
|
||||
|
||||
[[build-tool-plugins.antlib.tasks]]
|
||||
=== Spring Boot Ant Tasks
|
||||
== Spring Boot Ant Tasks
|
||||
|
||||
Once the `spring-boot-antlib` namespace has been declared, the following additional tasks are available:
|
||||
|
||||
* <<build-tool-plugins#build-tool-plugins.antlib.tasks.exejar>>
|
||||
* <<build-tool-plugins#build-tool-plugins.antlib.findmainclass>>
|
||||
* xref:antlib.adoc#build-tool-plugins.antlib.tasks.exejar[Using the "`exejar`" Task]
|
||||
* xref:antlib.adoc#build-tool-plugins.antlib.findmainclass[Using the "`findmainclass`" Task]
|
||||
|
||||
|
||||
|
||||
[[build-tool-plugins.antlib.tasks.exejar]]
|
||||
==== Using the "`exejar`" Task
|
||||
=== Using the "`exejar`" Task
|
||||
|
||||
You can use the `exejar` task to create a Spring Boot executable jar.
|
||||
The following attributes are supported by the task:
|
||||
|
||||
@@ -62,46 +65,48 @@ The following nested elements can be used with the task:
|
||||
| Element | Description
|
||||
|
||||
| `resources`
|
||||
| One or more {ant-docs}/Types/resources.html#collection[Resource Collections] describing a set of {ant-docs}/Types/resources.html[Resources] that should be added to the content of the created +jar+ file.
|
||||
| One or more {url-ant-docs}/Types/resources.html#collection[Resource Collections] describing a set of {url-ant-docs}/Types/resources.html[Resources] that should be added to the content of the created +jar+ file.
|
||||
|
||||
| `lib`
|
||||
| One or more {ant-docs}/Types/resources.html#collection[Resource Collections] that should be added to the set of jar libraries that make up the runtime dependency classpath of the application.
|
||||
| One or more {url-ant-docs}/Types/resources.html#collection[Resource Collections] that should be added to the set of jar libraries that make up the runtime dependency classpath of the application.
|
||||
|====
|
||||
|
||||
|
||||
|
||||
[[build-tool-plugins.antlib.tasks.examples]]
|
||||
==== Examples
|
||||
=== Examples
|
||||
|
||||
This section shows two examples of Ant tasks.
|
||||
|
||||
.Specify +start-class+
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<spring-boot:exejar destfile="target/my-application.jar"
|
||||
classes="target/classes" start-class="com.example.MyApplication">
|
||||
<resources>
|
||||
<fileset dir="src/main/resources" />
|
||||
</resources>
|
||||
<lib>
|
||||
<fileset dir="lib" />
|
||||
</lib>
|
||||
</spring-boot:exejar>
|
||||
<spring-boot:exejar destfile="target/my-application.jar"
|
||||
classes="target/classes" start-class="com.example.MyApplication">
|
||||
<resources>
|
||||
<fileset dir="src/main/resources" />
|
||||
</resources>
|
||||
<lib>
|
||||
<fileset dir="lib" />
|
||||
</lib>
|
||||
</spring-boot:exejar>
|
||||
----
|
||||
|
||||
.Detect +start-class+
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<exejar destfile="target/my-application.jar" classes="target/classes">
|
||||
<lib>
|
||||
<fileset dir="lib" />
|
||||
</lib>
|
||||
</exejar>
|
||||
<exejar destfile="target/my-application.jar" classes="target/classes">
|
||||
<lib>
|
||||
<fileset dir="lib" />
|
||||
</lib>
|
||||
</exejar>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[build-tool-plugins.antlib.findmainclass]]
|
||||
=== Using the "`findmainclass`" Task
|
||||
== Using the "`findmainclass`" Task
|
||||
|
||||
The `findmainclass` task is used internally by `exejar` to locate a class declaring a `main`.
|
||||
If necessary, you can also use this task directly in your build.
|
||||
The following attributes are supported:
|
||||
@@ -126,23 +131,24 @@ The following attributes are supported:
|
||||
|
||||
|
||||
[[build-tool-plugins.antlib.findmainclass.examples]]
|
||||
==== Examples
|
||||
=== Examples
|
||||
|
||||
This section contains three examples of using `findmainclass`.
|
||||
|
||||
.Find and log
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<findmainclass classesroot="target/classes" />
|
||||
<findmainclass classesroot="target/classes" />
|
||||
----
|
||||
|
||||
.Find and set
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<findmainclass classesroot="target/classes" property="main-class" />
|
||||
<findmainclass classesroot="target/classes" property="main-class" />
|
||||
----
|
||||
|
||||
.Override and set
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<findmainclass mainclass="com.example.MainClass" property="main-class" />
|
||||
<findmainclass mainclass="com.example.MainClass" property="main-class" />
|
||||
----
|
||||
@@ -0,0 +1,8 @@
|
||||
[[build-tool-plugins]]
|
||||
= Build Tool Plugins
|
||||
|
||||
Spring Boot provides build tool plugins for Maven and Gradle.
|
||||
The plugins offer a variety of features, including the packaging of executable jars.
|
||||
This section provides more details on both plugins as well as some help should you need to extend an unsupported build system.
|
||||
If you are just getting started, you might want to read "`xref:reference:using/build-systems.adoc[Build Systems]`" from the "`xref:reference:using/index.adoc[Developing with Spring Boot]`" section first.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
[[build-tool-plugins.other-build-systems]]
|
||||
== Supporting Other Build Systems
|
||||
= Supporting Other Build Systems
|
||||
|
||||
If you want to use a build tool other than Maven, Gradle, or Ant, you likely need to develop your own plugin.
|
||||
Executable jars need to follow a specific format and certain entries need to be written in an uncompressed form (see the "`<<executable-jar#appendix.executable-jar, executable jar format>>`" section in the appendix for details).
|
||||
Executable jars need to follow a specific format and certain entries need to be written in an uncompressed form (see the "`xref:specification:/executable-jar/index.adoc[executable jar format]`" section in the appendix for details).
|
||||
|
||||
The Spring Boot Maven and Gradle plugins both make use of `spring-boot-loader-tools` to actually generate jars.
|
||||
If you need to, you may use this library directly.
|
||||
@@ -9,7 +10,8 @@ If you need to, you may use this library directly.
|
||||
|
||||
|
||||
[[build-tool-plugins.other-build-systems.repackaging-archives]]
|
||||
=== Repackaging Archives
|
||||
== Repackaging Archives
|
||||
|
||||
To repackage an existing archive so that it becomes a self-contained executable archive, use `org.springframework.boot.loader.tools.Repackager`.
|
||||
The `Repackager` class takes a single constructor argument that refers to an existing jar or war archive.
|
||||
Use one of the two available `repackage()` methods to either replace the original file or write to a new destination.
|
||||
@@ -18,7 +20,8 @@ Various settings can also be configured on the repackager before it is run.
|
||||
|
||||
|
||||
[[build-tool-plugins.other-build-systems.nested-libraries]]
|
||||
=== Nested Libraries
|
||||
== Nested Libraries
|
||||
|
||||
When repackaging an archive, you can include references to dependency files by using the `org.springframework.boot.loader.tools.Libraries` interface.
|
||||
We do not provide any concrete implementations of `Libraries` here as they are usually build-system-specific.
|
||||
|
||||
@@ -27,14 +30,16 @@ If your archive already includes libraries, you can use `Libraries.NONE`.
|
||||
|
||||
|
||||
[[build-tool-plugins.other-build-systems.finding-main-class]]
|
||||
=== Finding a Main Class
|
||||
== Finding a Main Class
|
||||
|
||||
If you do not use `Repackager.setMainClass()` to specify a main class, the repackager uses https://asm.ow2.io/[ASM] to read class files and tries to find a suitable class with a `public static void main(String[] args)` method.
|
||||
An exception is thrown if more than one candidate is found.
|
||||
|
||||
|
||||
|
||||
[[build-tool-plugins.other-build-systems.example-repackage-implementation]]
|
||||
=== Example Repackage Implementation
|
||||
== Example Repackage Implementation
|
||||
|
||||
The following example shows a typical repackage implementation:
|
||||
|
||||
include::code:MyBuildTool[]
|
||||
include-code::MyBuildTool[]
|
||||
@@ -0,0 +1,11 @@
|
||||
* xref:build-tool-plugin:index.adoc[]
|
||||
+
|
||||
--
|
||||
include::maven-plugin:partial$nav-maven-plugin.adoc[]
|
||||
--
|
||||
+
|
||||
--
|
||||
include::gradle-plugin:partial$nav-gradle-plugin.adoc[]
|
||||
--
|
||||
** xref:build-tool-plugin:antlib.adoc[]
|
||||
** xref:build-tool-plugin:other-build-systems.adoc[]
|
||||
@@ -1,12 +1,5 @@
|
||||
[[cli]]
|
||||
= Spring Boot CLI
|
||||
include::attributes.adoc[]
|
||||
|
||||
|
||||
The Spring Boot CLI is a command line tool that you can use to bootstrap a new project from https://start.spring.io or encode a password.
|
||||
|
||||
|
||||
|
||||
include::cli/installation.adoc[]
|
||||
|
||||
include::cli/using-the-cli.adoc[]
|
||||
@@ -0,0 +1,5 @@
|
||||
[[cli.installation]]
|
||||
= Installing the CLI
|
||||
|
||||
The Spring Boot CLI (Command-Line Interface) can be installed manually by using SDKMAN! (the SDK Manager) or by using Homebrew or MacPorts if you are an OSX user.
|
||||
See xref:ROOT:installing.adoc#getting-started.installing.cli[_Installing the Spring Boot CLI_] in the "`Getting started`" section for comprehensive installation instructions.
|
||||
@@ -0,0 +1,177 @@
|
||||
[[cli.using-the-cli]]
|
||||
= Using the CLI
|
||||
|
||||
Once you have installed the CLI, you can run it by typing `spring` and pressing Enter at the command line.
|
||||
If you run `spring` without any arguments, a help screen is displayed, as follows:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
$ spring
|
||||
usage: spring [--help] [--version]
|
||||
<command> [<args>]
|
||||
|
||||
Available commands are:
|
||||
|
||||
init [options] [location]
|
||||
Initialize a new project using Spring Initializr (start.spring.io)
|
||||
|
||||
encodepassword [options] <password to encode>
|
||||
Encode a password for use with Spring Security
|
||||
|
||||
shell
|
||||
Start a nested shell
|
||||
|
||||
Common options:
|
||||
|
||||
--debug Verbose mode
|
||||
Print additional status information for the command you are running
|
||||
|
||||
|
||||
See 'spring help <command>' for more information on a specific command.
|
||||
----
|
||||
|
||||
You can type `spring help` to get more details about any of the supported commands, as shown in the following example:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
$ spring help init
|
||||
spring init - Initialize a new project using Spring Initializr (start.spring.io)
|
||||
|
||||
usage: spring init [options] [location]
|
||||
|
||||
Option Description
|
||||
------ -----------
|
||||
-a, --artifact-id <String> Project coordinates; infer archive name (for
|
||||
example 'test')
|
||||
-b, --boot-version <String> Spring Boot version (for example '1.2.0.RELEASE')
|
||||
--build <String> Build system to use (for example 'maven' or
|
||||
'gradle') (default: maven)
|
||||
-d, --dependencies <String> Comma-separated list of dependency identifiers to
|
||||
include in the generated project
|
||||
--description <String> Project description
|
||||
-f, --force Force overwrite of existing files
|
||||
--format <String> Format of the generated content (for example
|
||||
'build' for a build file, 'project' for a
|
||||
project archive) (default: project)
|
||||
-g, --group-id <String> Project coordinates (for example 'org.test')
|
||||
-j, --java-version <String> Language level (for example '1.8')
|
||||
-l, --language <String> Programming language (for example 'java')
|
||||
--list List the capabilities of the service. Use it to
|
||||
discover the dependencies and the types that are
|
||||
available
|
||||
-n, --name <String> Project name; infer application name
|
||||
-p, --packaging <String> Project packaging (for example 'jar')
|
||||
--package-name <String> Package name
|
||||
-t, --type <String> Project type. Not normally needed if you use --
|
||||
build and/or --format. Check the capabilities of
|
||||
the service (--list) for more details
|
||||
--target <String> URL of the service to use (default: https://start.
|
||||
spring.io)
|
||||
-v, --version <String> Project version (for example '0.0.1-SNAPSHOT')
|
||||
-x, --extract Extract the project archive. Inferred if a
|
||||
location is specified without an extension
|
||||
|
||||
examples:
|
||||
|
||||
To list all the capabilities of the service:
|
||||
$ spring init --list
|
||||
|
||||
To creates a default project:
|
||||
$ spring init
|
||||
|
||||
To create a web my-app.zip:
|
||||
$ spring init -d=web my-app.zip
|
||||
|
||||
To create a web/data-jpa gradle project unpacked:
|
||||
$ spring init -d=web,jpa --build=gradle my-dir
|
||||
----
|
||||
|
||||
The `version` command provides a quick way to check which version of Spring Boot you are using, as follows:
|
||||
|
||||
[source,shell,subs="verbatim,attributes"]
|
||||
----
|
||||
$ spring version
|
||||
Spring CLI v{version-spring-boot}
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[cli.using-the-cli.initialize-new-project]]
|
||||
== Initialize a New Project
|
||||
|
||||
The `init` command lets you create a new project by using https://start.spring.io without leaving the shell, as shown in the following example:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
$ spring init --dependencies=web,data-jpa my-project
|
||||
Using service at https://start.spring.io
|
||||
Project extracted to '/Users/developer/example/my-project'
|
||||
----
|
||||
|
||||
The preceding example creates a `my-project` directory with a Maven-based project that uses `spring-boot-starter-web` and `spring-boot-starter-data-jpa`.
|
||||
You can list the capabilities of the service by using the `--list` flag, as shown in the following example:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
$ spring init --list
|
||||
=======================================
|
||||
Capabilities of https://start.spring.io
|
||||
=======================================
|
||||
|
||||
Available dependencies:
|
||||
-----------------------
|
||||
actuator - Actuator: Production ready features to help you monitor and manage your application
|
||||
...
|
||||
web - Web: Support for full-stack web development, including Tomcat and spring-webmvc
|
||||
websocket - Websocket: Support for WebSocket development
|
||||
ws - WS: Support for Spring Web Services
|
||||
|
||||
Available project types:
|
||||
------------------------
|
||||
gradle-build - Gradle Config [format:build, build:gradle]
|
||||
gradle-project - Gradle Project [format:project, build:gradle]
|
||||
maven-build - Maven POM [format:build, build:maven]
|
||||
maven-project - Maven Project [format:project, build:maven] (default)
|
||||
|
||||
...
|
||||
----
|
||||
|
||||
The `init` command supports many options.
|
||||
See the `help` output for more details.
|
||||
For instance, the following command creates a Gradle project that uses Java 17 and `war` packaging:
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
$ spring init --build=gradle --java-version=17 --dependencies=websocket --packaging=war sample-app.zip
|
||||
Using service at https://start.spring.io
|
||||
Content saved to 'sample-app.zip'
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[cli.using-the-cli.embedded-shell]]
|
||||
== Using the Embedded Shell
|
||||
|
||||
Spring Boot includes command-line completion scripts for the BASH and zsh shells.
|
||||
If you do not use either of these shells (perhaps you are a Windows user), you can use the `shell` command to launch an integrated shell, as shown in the following example:
|
||||
|
||||
[source,shell,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
$ spring shell
|
||||
*Spring Boot* (v{version-spring-boot})
|
||||
Hit TAB to complete. Type \'help' and hit RETURN for help, and \'exit' to quit.
|
||||
----
|
||||
|
||||
From inside the embedded shell, you can run other commands directly:
|
||||
|
||||
[source,shell,subs="verbatim,attributes"]
|
||||
----
|
||||
$ version
|
||||
Spring CLI v{version-spring-boot}
|
||||
----
|
||||
|
||||
The embedded shell supports ANSI color output as well as `tab` completion.
|
||||
If you need to run a native command, you can use the `!` prefix.
|
||||
To exit the embedded shell, press `ctrl-c`.
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
* xref:cli:index.adoc[]
|
||||
|
||||
** xref:cli:installation.adoc[]
|
||||
** xref:cli:using-the-cli.adoc[]
|
||||
@@ -1,22 +1,25 @@
|
||||
[[howto.actuator]]
|
||||
== Actuator
|
||||
= Actuator
|
||||
|
||||
Spring Boot includes the Spring Boot Actuator.
|
||||
This section answers questions that often arise from its use.
|
||||
|
||||
|
||||
|
||||
[[howto.actuator.change-http-port-or-address]]
|
||||
=== Change the HTTP Port or Address of the Actuator Endpoints
|
||||
== Change the HTTP Port or Address of the Actuator Endpoints
|
||||
|
||||
In a standalone application, the Actuator HTTP port defaults to the same as the main HTTP port.
|
||||
To make the application listen on a different port, set the external property: configprop:management.server.port[].
|
||||
To listen on a completely different network address (such as when you have an internal network for management and an external one for user applications), you can also set `management.server.address` to a valid IP address to which the server is able to bind.
|
||||
|
||||
For more detail, see the {spring-boot-actuator-autoconfigure-module-code}/web/server/ManagementServerProperties.java[`ManagementServerProperties`] source code and "`<<actuator#actuator.monitoring.customizing-management-server-port>>`" in the "`Production-ready features`" section.
|
||||
For more detail, see the {code-spring-boot-actuator-autoconfigure-src}/web/server/ManagementServerProperties.java[`ManagementServerProperties`] source code and "`xref:reference:actuator/monitoring.adoc#actuator.monitoring.customizing-management-server-port[Customizing the Management Server Port]`" in the "`Production-ready features`" section.
|
||||
|
||||
|
||||
|
||||
[[howto.actuator.customize-whitelabel-error-page]]
|
||||
=== Customize the '`whitelabel`' Error Page
|
||||
== Customize the '`whitelabel`' Error Page
|
||||
|
||||
Spring Boot installs a '`whitelabel`' error page that you see in a browser client if you encounter a server error (machine clients consuming JSON and other media types should see a sensible response with the right error code).
|
||||
|
||||
NOTE: Set `server.error.whitelabel.enabled=false` to switch the default error page off.
|
||||
@@ -28,14 +31,15 @@ For example, if you use Thymeleaf, you can add an `error.html` template.
|
||||
If you use FreeMarker, you can add an `error.ftlh` template.
|
||||
In general, you need a `View` that resolves with a name of `error` or a `@Controller` that handles the `/error` path.
|
||||
Unless you replaced some of the default configuration, you should find a `BeanNameViewResolver` in your `ApplicationContext`, so a `@Bean` named `error` would be one way of doing that.
|
||||
See {spring-boot-autoconfigure-module-code}/web/servlet/error/ErrorMvcAutoConfiguration.java[`ErrorMvcAutoConfiguration`] for more options.
|
||||
See {code-spring-boot-autoconfigure-src}/web/servlet/error/ErrorMvcAutoConfiguration.java[`ErrorMvcAutoConfiguration`] for more options.
|
||||
|
||||
See also the section on "`<<web#web.servlet.spring-mvc.error-handling, Error Handling>>`" for details of how to register handlers in the servlet container.
|
||||
See also the section on "`xref:reference:web/servlet.adoc#web.servlet.spring-mvc.error-handling[Error Handling]`" for details of how to register handlers in the servlet container.
|
||||
|
||||
|
||||
|
||||
[[howto.actuator.customizing-sanitization]]
|
||||
=== Customizing Sanitization
|
||||
== Customizing Sanitization
|
||||
|
||||
To take control over the sanitization, define a `SanitizingFunction` bean.
|
||||
The `SanitizableData` with which the function is called provides access to the key and value as well as the `PropertySource` from which they came.
|
||||
This allows you to, for example, sanitize every value that comes from a particular property source.
|
||||
@@ -44,7 +48,8 @@ Each `SanitizingFunction` is called in order until a function changes the value
|
||||
|
||||
|
||||
[[howto.actuator.map-health-indicators-to-metrics]]
|
||||
=== Map Health Indicators to Micrometer Metrics
|
||||
== Map Health Indicators to Micrometer Metrics
|
||||
|
||||
Spring Boot health indicators return a `Status` type to indicate the overall system health.
|
||||
If you want to monitor or alert on levels of health for a particular application, you can export these statuses as metrics with Micrometer.
|
||||
By default, the status codes "`UP`", "`DOWN`", "`OUT_OF_SERVICE`" and "`UNKNOWN`" are used by Spring Boot.
|
||||
@@ -52,4 +57,4 @@ To export these, you will need to convert these states to some set of numbers so
|
||||
|
||||
The following example shows one way to write such an exporter:
|
||||
|
||||
include::code:MyHealthMetricsExportConfiguration[]
|
||||
include-code::MyHealthMetricsExportConfiguration[]
|
||||
@@ -0,0 +1,55 @@
|
||||
[[howto.aot]]
|
||||
= Ahead-of-time processing
|
||||
|
||||
A number of questions often arise when people use the ahead-of-time processing of Spring Boot applications.
|
||||
This section addresses those questions.
|
||||
|
||||
|
||||
|
||||
[[howto.aot.conditions]]
|
||||
== Conditions
|
||||
|
||||
Ahead-of-time processing optimizes the application and evaluates {url-spring-framework-javadoc}/org/springframework/context/annotation/Conditional.html[conditions] based on the environment at build time.
|
||||
xref:reference:features/profiles.adoc[Profiles] are implemented through conditions and are therefore affected, too.
|
||||
|
||||
If you want beans that are created based on a condition in an ahead-of-time optimized application, you have to set up the environment when building the application.
|
||||
The beans which are created while ahead-of-time processing at build time are then always created when running the application and can't be switched off.
|
||||
To do this, you can set the profiles which should be used when building the application.
|
||||
|
||||
For Maven, this works by setting the `profiles` configuration of the `spring-boot-maven-plugin:process-aot` execution:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>process-aot</id>
|
||||
<configuration>
|
||||
<profiles>profile-a,profile-b</profiles>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</profile>
|
||||
----
|
||||
|
||||
For Gradle, you need to configure the `ProcessAot` task:
|
||||
|
||||
[source,gradle]
|
||||
----
|
||||
tasks.withType(org.springframework.boot.gradle.tasks.aot.ProcessAot).configureEach {
|
||||
args('--spring.profiles.active=profile-a,profile-b')
|
||||
}
|
||||
----
|
||||
|
||||
Profiles which only change configuration properties that don't influence conditions are supported without limitations when running ahead-of-time optimized applications.
|
||||
@@ -1,12 +1,14 @@
|
||||
[[howto.application]]
|
||||
== Spring Boot Application
|
||||
= Spring Boot Application
|
||||
|
||||
This section includes topics relating directly to Spring Boot applications.
|
||||
|
||||
|
||||
|
||||
[[howto.application.failure-analyzer]]
|
||||
=== Create Your Own FailureAnalyzer
|
||||
{spring-boot-module-api}/diagnostics/FailureAnalyzer.html[`FailureAnalyzer`] is a great way to intercept an exception on startup and turn it into a human-readable message, wrapped in a {spring-boot-module-api}/diagnostics/FailureAnalysis.html[`FailureAnalysis`].
|
||||
== Create Your Own FailureAnalyzer
|
||||
|
||||
xref:api:java/org/springframework/boot/diagnostics/FailureAnalyzer.html[`FailureAnalyzer`] is a great way to intercept an exception on startup and turn it into a human-readable message, wrapped in a xref:api:java/org/springframework/boot/diagnostics/FailureAnalysis.html[`FailureAnalysis`].
|
||||
Spring Boot provides such an analyzer for application-context-related exceptions, JSR-303 validations, and more.
|
||||
You can also create your own.
|
||||
|
||||
@@ -17,10 +19,10 @@ If, for whatever reason, you cannot handle the exception, return `null` to give
|
||||
`FailureAnalyzer` implementations must be registered in `META-INF/spring.factories`.
|
||||
The following example registers `ProjectConstraintViolationFailureAnalyzer`:
|
||||
|
||||
[source,properties,indent=0,subs="verbatim"]
|
||||
[source,properties]
|
||||
----
|
||||
org.springframework.boot.diagnostics.FailureAnalyzer=\
|
||||
com.example.ProjectConstraintViolationFailureAnalyzer
|
||||
org.springframework.boot.diagnostics.FailureAnalyzer=\
|
||||
com.example.ProjectConstraintViolationFailureAnalyzer
|
||||
----
|
||||
|
||||
NOTE: If you need access to the `BeanFactory` or the `Environment`, declare them as constructor arguments in your `FailureAnalyzer` implementation.
|
||||
@@ -28,12 +30,13 @@ NOTE: If you need access to the `BeanFactory` or the `Environment`, declare them
|
||||
|
||||
|
||||
[[howto.application.troubleshoot-auto-configuration]]
|
||||
=== Troubleshoot Auto-configuration
|
||||
== Troubleshoot Auto-configuration
|
||||
|
||||
The Spring Boot auto-configuration tries its best to "`do the right thing`", but sometimes things fail, and it can be hard to tell why.
|
||||
|
||||
There is a really useful `ConditionEvaluationReport` available in any Spring Boot `ApplicationContext`.
|
||||
You can see it if you enable `DEBUG` logging output.
|
||||
If you use the `spring-boot-actuator` (see <<actuator#actuator,the Actuator chapter>>), there is also a `conditions` endpoint that renders the report in JSON.
|
||||
If you use the `spring-boot-actuator` (see xref:actuator.adoc[the Actuator chapter]), there is also a `conditions` endpoint that renders the report in JSON.
|
||||
Use that endpoint to debug the application and see what features have been added (and which have not been added) by Spring Boot at runtime.
|
||||
|
||||
Many more questions can be answered by looking at the source code and the Javadoc.
|
||||
@@ -43,7 +46,7 @@ When reading the code, remember the following rules of thumb:
|
||||
Pay special attention to the `+@Conditional*+` annotations to find out what features they enable and when.
|
||||
Add `--debug` to the command line or a System property `-Ddebug` to get a log on the console of all the auto-configuration decisions that were made in your app.
|
||||
In a running application with actuator enabled, look at the `conditions` endpoint (`/actuator/conditions` or the JMX equivalent) for the same information.
|
||||
* Look for classes that are `@ConfigurationProperties` (such as {spring-boot-autoconfigure-module-code}/web/ServerProperties.java[`ServerProperties`]) and read from there the available external configuration options.
|
||||
* Look for classes that are `@ConfigurationProperties` (such as {code-spring-boot-autoconfigure-src}/web/ServerProperties.java[`ServerProperties`]) and read from there the available external configuration options.
|
||||
The `@ConfigurationProperties` annotation has a `name` attribute that acts as a prefix to external properties.
|
||||
Thus, `ServerProperties` has `prefix="server"` and its configuration properties are `server.port`, `server.address`, and others.
|
||||
In a running application with actuator enabled, look at the `configprops` endpoint.
|
||||
@@ -55,7 +58,8 @@ When reading the code, remember the following rules of thumb:
|
||||
|
||||
|
||||
[[howto.application.customize-the-environment-or-application-context]]
|
||||
=== Customize the Environment or ApplicationContext Before It Starts
|
||||
== Customize the Environment or ApplicationContext Before It Starts
|
||||
|
||||
A `SpringApplication` has `ApplicationListeners` and `ApplicationContextInitializers` that are used to apply customizations to the context or environment.
|
||||
Spring Boot loads a number of such customizations for use internally from `META-INF/spring.factories`.
|
||||
There is more than one way to register additional customizations:
|
||||
@@ -64,20 +68,20 @@ There is more than one way to register additional customizations:
|
||||
* Declaratively, for all applications, by adding a `META-INF/spring.factories` and packaging a jar file that the applications all use as a library.
|
||||
|
||||
The `SpringApplication` sends some special `ApplicationEvents` to the listeners (some even before the context is created) and then registers the listeners for events published by the `ApplicationContext` as well.
|
||||
See "`<<features#features.spring-application.application-events-and-listeners,Application Events and Listeners>>`" in the '`Spring Boot features`' section for a complete list.
|
||||
See "`xref:reference:features/spring-application.adoc#features.spring-application.application-events-and-listeners[Application Events and Listeners]`" in the '`Spring Boot features`' section for a complete list.
|
||||
|
||||
It is also possible to customize the `Environment` before the application context is refreshed by using `EnvironmentPostProcessor`.
|
||||
Each implementation should be registered in `META-INF/spring.factories`, as shown in the following example:
|
||||
|
||||
[indent=0]
|
||||
[source]
|
||||
----
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
|
||||
----
|
||||
|
||||
The implementation can load arbitrary files and add them to the `Environment`.
|
||||
For instance, the following example loads a YAML configuration file from the classpath:
|
||||
|
||||
include::code:MyEnvironmentPostProcessor[]
|
||||
include-code::MyEnvironmentPostProcessor[]
|
||||
|
||||
TIP: The `Environment` has already been prepared with all the usual property sources that Spring Boot loads by default.
|
||||
It is therefore possible to get the location of the file from the environment.
|
||||
@@ -91,14 +95,16 @@ This is too late to configure certain properties such as `+logging.*+` and `+spr
|
||||
|
||||
|
||||
[[howto.application.context-hierarchy]]
|
||||
=== Build an ApplicationContext Hierarchy (Adding a Parent or Root Context)
|
||||
== Build an ApplicationContext Hierarchy (Adding a Parent or Root Context)
|
||||
|
||||
You can use the `ApplicationBuilder` class to create parent/child `ApplicationContext` hierarchies.
|
||||
See "`<<features#features.spring-application.fluent-builder-api>>`" in the '`Spring Boot features`' section for more information.
|
||||
See "`xref:reference:features/spring-application.adoc#features.spring-application.fluent-builder-api[Fluent Builder API]`" in the '`Spring Boot features`' section for more information.
|
||||
|
||||
|
||||
|
||||
[[howto.application.non-web-application]]
|
||||
=== Create a Non-web Application
|
||||
== Create a Non-web Application
|
||||
|
||||
Not all Spring applications have to be web applications (or web services).
|
||||
If you want to execute some code in a `main` method but also bootstrap a Spring application to set up the infrastructure to use, you can use the `SpringApplication` features of Spring Boot.
|
||||
A `SpringApplication` changes its `ApplicationContext` class, depending on whether it thinks it needs a web application or not.
|
||||
@@ -1,61 +1,66 @@
|
||||
[[howto.batch]]
|
||||
== Batch Applications
|
||||
= Batch Applications
|
||||
|
||||
A number of questions often arise when people use Spring Batch from within a Spring Boot application.
|
||||
This section addresses those questions.
|
||||
|
||||
|
||||
|
||||
[[howto.batch.specifying-a-data-source]]
|
||||
=== Specifying a Batch Data Source
|
||||
== Specifying a Batch Data Source
|
||||
|
||||
By default, batch applications require a `DataSource` to store job details.
|
||||
Spring Batch expects a single `DataSource` by default.
|
||||
To have it use a `DataSource` other than the application’s main `DataSource`, declare a `DataSource` bean, annotating its `@Bean` method with `@BatchDataSource`.
|
||||
If you do so and want two data sources, remember to mark the other one `@Primary`.
|
||||
To take greater control, add `@EnableBatchProcessing` to one of your `@Configuration` classes or extend `DefaultBatchConfiguration`.
|
||||
See the Javadoc of {spring-batch-api}/core/configuration/annotation/EnableBatchProcessing.html[`@EnableBatchProcessing`]
|
||||
and {spring-batch-api}/core/configuration/support/DefaultBatchConfiguration.html[`DefaultBatchConfiguration`] for more details.
|
||||
See the Javadoc of {url-spring-batch-javadoc}/core/configuration/annotation/EnableBatchProcessing.html[`@EnableBatchProcessing`]
|
||||
and {url-spring-batch-javadoc}/core/configuration/support/DefaultBatchConfiguration.html[`DefaultBatchConfiguration`] for more details.
|
||||
|
||||
For more info about Spring Batch, see the {spring-batch}[Spring Batch project page].
|
||||
For more info about Spring Batch, see the {url-spring-batch-site}[Spring Batch project page].
|
||||
|
||||
|
||||
|
||||
[[howto.batch.specifying-a-transaction-manager]]
|
||||
=== Specifying a Batch Transaction Manager
|
||||
Similar to <<howto.batch.specifying-a-data-source>>, you can define a `PlatformTransactionManager` for use in the batch processing by marking it as `@BatchTransactionManager`.
|
||||
== Specifying a Batch Transaction Manager
|
||||
|
||||
Similar to xref:batch.adoc#howto.batch.specifying-a-data-source[Specifying a Batch Data Source], you can define a `PlatformTransactionManager` for use in the batch processing by marking it as `@BatchTransactionManager`.
|
||||
If you do so and want two transaction managers, remember to mark the other one as `@Primary`.
|
||||
|
||||
|
||||
|
||||
[[howto.batch.running-jobs-on-startup]]
|
||||
=== Running Spring Batch Jobs on Startup
|
||||
== Running Spring Batch Jobs on Startup
|
||||
|
||||
Spring Batch auto-configuration is enabled by adding `spring-boot-starter-batch` to your application's classpath.
|
||||
|
||||
If a single `Job` bean is found in the application context, it is executed on startup (see {spring-boot-autoconfigure-module-code}/batch/JobLauncherApplicationRunner.java[`JobLauncherApplicationRunner`] for details).
|
||||
If a single `Job` bean is found in the application context, it is executed on startup (see {code-spring-boot-autoconfigure-src}/batch/JobLauncherApplicationRunner.java[`JobLauncherApplicationRunner`] for details).
|
||||
If multiple `Job` beans are found, the job that should be executed must be specified using configprop:spring.batch.job.name[].
|
||||
|
||||
To disable running a `Job` found in the application context, set the configprop:spring.batch.job.enabled[] to `false`.
|
||||
|
||||
See {spring-boot-autoconfigure-module-code}/batch/BatchAutoConfiguration.java[BatchAutoConfiguration] for more details.
|
||||
See {code-spring-boot-autoconfigure-src}/batch/BatchAutoConfiguration.java[BatchAutoConfiguration] for more details.
|
||||
|
||||
|
||||
|
||||
[[howto.batch.running-from-the-command-line]]
|
||||
=== Running From the Command Line
|
||||
Spring Boot converts any command line argument starting with `--` to a property to add to the `Environment`, see <<features#features.external-config.command-line-args,accessing command line properties>>.
|
||||
== Running From the Command Line
|
||||
|
||||
Spring Boot converts any command line argument starting with `--` to a property to add to the `Environment`, see xref:reference:features/external-config.adoc#features.external-config.command-line-args[accessing command line properties].
|
||||
This should not be used to pass arguments to batch jobs.
|
||||
To specify batch arguments on the command line, use the regular format (that is without `--`), as shown in the following example:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
[source,shell]
|
||||
----
|
||||
$ java -jar myapp.jar someParameter=someValue anotherParameter=anotherValue
|
||||
$ java -jar myapp.jar someParameter=someValue anotherParameter=anotherValue
|
||||
----
|
||||
|
||||
If you specify a property of the `Environment` on the command line, it is ignored by the job.
|
||||
Consider the following command:
|
||||
|
||||
[source,shell,indent=0,subs="verbatim"]
|
||||
[source,shell]
|
||||
----
|
||||
$ java -jar myapp.jar --server.port=7070 someParameter=someValue
|
||||
$ java -jar myapp.jar --server.port=7070 someParameter=someValue
|
||||
----
|
||||
|
||||
This provides only one argument to the batch job: `someParameter=someValue`.
|
||||
@@ -63,7 +68,8 @@ This provides only one argument to the batch job: `someParameter=someValue`.
|
||||
|
||||
|
||||
[[howto.batch.restarting-a-failed-job]]
|
||||
=== Restarting a stopped or failed Job
|
||||
== Restarting a stopped or failed Job
|
||||
|
||||
To restart a failed `Job`, all parameters (identifying and non-identifying) must be re-specified on the command line.
|
||||
Non-identifying parameters are *not* copied from the previous execution.
|
||||
This allows them to be modified or removed.
|
||||
@@ -73,7 +79,8 @@ NOTE: When you're using a custom `JobParametersIncrementer`, you have to gather
|
||||
|
||||
|
||||
[[howto.batch.storing-job-repository]]
|
||||
=== Storing the Job Repository
|
||||
== Storing the Job Repository
|
||||
|
||||
Spring Batch requires a data store for the `Job` repository.
|
||||
If you use Spring Boot, you must use an actual database.
|
||||
Note that it can be an in-memory database, see {spring-batch-docs}/job.html#configuringJobRepository[Configuring a Job Repository].
|
||||
Note that it can be an in-memory database, see {url-spring-batch-docs}/job.html#configuringJobRepository[Configuring a Job Repository].
|
||||
@@ -1,79 +1,82 @@
|
||||
[[howto.build]]
|
||||
== Build
|
||||
= Build
|
||||
|
||||
Spring Boot includes build plugins for Maven and Gradle.
|
||||
This section answers common questions about these plugins.
|
||||
|
||||
|
||||
|
||||
[[howto.build.generate-info]]
|
||||
=== Generate Build Information
|
||||
== Generate Build Information
|
||||
|
||||
Both the Maven plugin and the Gradle plugin allow generating build information containing the coordinates, name, and version of the project.
|
||||
The plugins can also be configured to add additional properties through configuration.
|
||||
When such a file is present, Spring Boot auto-configures a `BuildProperties` bean.
|
||||
|
||||
To generate build information with Maven, add an execution for the `build-info` goal, as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
[source,xml,subs="verbatim,attributes"]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>{spring-boot-version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-info</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>{version-spring-boot}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-info</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
TIP: See the {spring-boot-maven-plugin-docs}#goals-build-info[Spring Boot Maven Plugin documentation] for more details.
|
||||
TIP: See the xref:maven-plugin:build-info.adoc[Spring Boot Maven Plugin documentation] for more details.
|
||||
|
||||
The following example does the same with Gradle:
|
||||
|
||||
[source,gradle,indent=0,subs="verbatim"]
|
||||
[source,gradle]
|
||||
----
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
----
|
||||
|
||||
TIP: See the {spring-boot-gradle-plugin-docs}#integrating-with-actuator-build-info[Spring Boot Gradle Plugin documentation] for more details.
|
||||
TIP: See the xref:gradle-plugin:integrating-with-actuator.adoc[Spring Boot Gradle Plugin documentation] for more details.
|
||||
|
||||
|
||||
|
||||
[[howto.build.generate-git-info]]
|
||||
=== Generate Git Information
|
||||
== Generate Git Information
|
||||
|
||||
Both Maven and Gradle allow generating a `git.properties` file containing information about the state of your `git` source code repository when the project was built.
|
||||
|
||||
For Maven users, the `spring-boot-starter-parent` POM includes a pre-configured plugin to generate a `git.properties` file.
|
||||
To use it, add the following declaration for the https://github.com/git-commit-id/git-commit-id-maven-plugin[`Git Commit Id Plugin`] to your POM:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.github.git-commit-id</groupId>
|
||||
<artifactId>git-commit-id-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.github.git-commit-id</groupId>
|
||||
<artifactId>git-commit-id-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
Gradle users can achieve the same result by using the https://plugins.gradle.org/plugin/com.gorylenko.gradle-git-properties[`gradle-git-properties`] plugin, as shown in the following example:
|
||||
|
||||
[source,gradle,indent=0,subs="verbatim"]
|
||||
[source,gradle]
|
||||
----
|
||||
plugins {
|
||||
id "com.gorylenko.gradle-git-properties" version "2.4.1"
|
||||
}
|
||||
plugins {
|
||||
id "com.gorylenko.gradle-git-properties" version "2.4.1"
|
||||
}
|
||||
----
|
||||
|
||||
Both the Maven and Gradle plugins allow the properties that are included in `git.properties` to be configured.
|
||||
@@ -85,71 +88,74 @@ Using this format lets the time be parsed into a `Date` and its format, when ser
|
||||
|
||||
|
||||
[[howto.build.customize-dependency-versions]]
|
||||
=== Customize Dependency Versions
|
||||
== Customize Dependency Versions
|
||||
|
||||
The `spring-boot-dependencies` POM manages the versions of common dependencies.
|
||||
The Spring Boot plugins for Maven and Gradle allow these managed dependency versions to be customized using build properties.
|
||||
|
||||
WARNING: Each Spring Boot release is designed and tested against this specific set of third-party dependencies.
|
||||
Overriding versions may cause compatibility issues.
|
||||
|
||||
To override dependency versions with Maven, see {spring-boot-maven-plugin-docs}#using[this section] of the Maven plugin's documentation.
|
||||
To override dependency versions with Maven, see xref:maven-plugin:using.adoc[this section] of the Maven plugin's documentation.
|
||||
|
||||
To override dependency versions in Gradle, see {spring-boot-gradle-plugin-docs}#managing-dependencies-dependency-management-plugin-customizing[this section] of the Gradle plugin's documentation.
|
||||
To override dependency versions in Gradle, see xref:gradle-plugin:managing-dependencies.adoc#managing-dependencies.dependency-management-plugin.customizing[this section] of the Gradle plugin's documentation.
|
||||
|
||||
|
||||
|
||||
[[howto.build.create-an-executable-jar-with-maven]]
|
||||
=== Create an Executable JAR with Maven
|
||||
== Create an Executable JAR with Maven
|
||||
|
||||
The `spring-boot-maven-plugin` can be used to create an executable "`fat`" JAR.
|
||||
If you use the `spring-boot-starter-parent` POM, you can declare the plugin and your jars are repackaged as follows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
If you do not use the parent POM, you can still use the plugin.
|
||||
However, you must additionally add an `<executions>` section, as follows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
[source,xml,subs="verbatim,attributes"]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>{spring-boot-version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>{version-spring-boot}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
See the {spring-boot-maven-plugin-docs}#repackage[plugin documentation] for full usage details.
|
||||
See the xref:maven-plugin:packaging.adoc#packaging.repackage-goal[plugin documentation] for full usage details.
|
||||
|
||||
|
||||
|
||||
[[howto.build.use-a-spring-boot-application-as-dependency]]
|
||||
=== Use a Spring Boot Application as a Dependency
|
||||
== Use a Spring Boot Application as a Dependency
|
||||
|
||||
Like a war file, a Spring Boot application is not intended to be used as a dependency.
|
||||
If your application contains classes that you want to share with other projects, the recommended approach is to move that code into a separate module.
|
||||
The separate module can then be depended upon by your application and other projects.
|
||||
|
||||
If you cannot rearrange your code as recommended above, Spring Boot's Maven and Gradle plugins must be configured to produce a separate artifact that is suitable for use as a dependency.
|
||||
The executable archive cannot be used as a dependency as the <<executable-jar#appendix.executable-jar.nested-jars.jar-structure,executable jar format>> packages application classes in `BOOT-INF/classes`.
|
||||
The executable archive cannot be used as a dependency as the xref:specification:executable-jar/nested-jars.adoc#appendix.executable-jar.nested-jars.jar-structure[executable jar format] packages application classes in `BOOT-INF/classes`.
|
||||
This means that they cannot be found when the executable jar is used as a dependency.
|
||||
|
||||
To produce the two artifacts, one that can be used as a dependency and one that is executable, a classifier must be specified.
|
||||
@@ -157,25 +163,26 @@ This classifier is applied to the name of the executable archive, leaving the de
|
||||
|
||||
To configure a classifier of `exec` in Maven, you can use the following configuration:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[howto.build.extract-specific-libraries-when-an-executable-jar-runs]]
|
||||
=== Extract Specific Libraries When an Executable Jar Runs
|
||||
== Extract Specific Libraries When an Executable Jar Runs
|
||||
|
||||
Most nested libraries in an executable jar do not need to be unpacked in order to run.
|
||||
However, certain libraries can have problems.
|
||||
For example, JRuby includes its own nested jar support, which assumes that the `jruby-complete.jar` is always directly available as a file in its own right.
|
||||
@@ -187,77 +194,80 @@ WARNING: Care should be taken to ensure that your operating system is configured
|
||||
|
||||
For example, to indicate that JRuby should be flagged for unpacking by using the Maven Plugin, you would add the following configuration:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<requiresUnpack>
|
||||
<dependency>
|
||||
<groupId>org.jruby</groupId>
|
||||
<artifactId>jruby-complete</artifactId>
|
||||
</dependency>
|
||||
</requiresUnpack>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<requiresUnpack>
|
||||
<dependency>
|
||||
<groupId>org.jruby</groupId>
|
||||
<artifactId>jruby-complete</artifactId>
|
||||
</dependency>
|
||||
</requiresUnpack>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[howto.build.create-a-nonexecutable-jar]]
|
||||
=== Create a Non-executable JAR with Exclusions
|
||||
== Create a Non-executable JAR with Exclusions
|
||||
|
||||
Often, if you have an executable and a non-executable jar as two separate build products, the executable version has additional configuration files that are not needed in a library jar.
|
||||
For example, the `application.yaml` configuration file might be excluded from the non-executable JAR.
|
||||
|
||||
In Maven, the executable jar must be the main artifact and you can add a classified jar for the library, as follows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>lib</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>lib</classifier>
|
||||
<excludes>
|
||||
<exclude>application.yaml</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>lib</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>lib</classifier>
|
||||
<excludes>
|
||||
<exclude>application.yaml</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[howto.build.remote-debug-maven]]
|
||||
=== Remote Debug a Spring Boot Application Started with Maven
|
||||
To attach a remote debugger to a Spring Boot application that was started with Maven, you can use the `jvmArguments` property of the {spring-boot-maven-plugin-docs}[maven plugin].
|
||||
== Remote Debug a Spring Boot Application Started with Maven
|
||||
|
||||
See {spring-boot-maven-plugin-docs}#run-example-debug[this example] for more details.
|
||||
To attach a remote debugger to a Spring Boot application that was started with Maven, you can use the `jvmArguments` property of the xref:maven-plugin:index.adoc[maven plugin].
|
||||
|
||||
See xref:maven-plugin:run.adoc#run.examples.debug[this example] for more details.
|
||||
|
||||
|
||||
|
||||
[[howto.build.build-an-executable-archive-with-ant-without-using-spring-boot-antlib]]
|
||||
=== Build an Executable Archive From Ant without Using spring-boot-antlib
|
||||
== Build an Executable Archive From Ant without Using spring-boot-antlib
|
||||
|
||||
To build with Ant, you need to grab dependencies, compile, and then create a jar or war archive.
|
||||
To make it executable, you can either use the `spring-boot-antlib` module or you can follow these instructions:
|
||||
|
||||
@@ -272,27 +282,27 @@ To make it executable, you can either use the `spring-boot-antlib` module or you
|
||||
|
||||
The following example shows how to build an executable archive with Ant:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<target name="build" depends="compile">
|
||||
<jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
|
||||
<mappedresources>
|
||||
<fileset dir="target/classes" />
|
||||
<globmapper from="*" to="BOOT-INF/classes/*"/>
|
||||
</mappedresources>
|
||||
<mappedresources>
|
||||
<fileset dir="src/main/resources" erroronmissingdir="false"/>
|
||||
<globmapper from="*" to="BOOT-INF/classes/*"/>
|
||||
</mappedresources>
|
||||
<mappedresources>
|
||||
<fileset dir="${lib.dir}/runtime" />
|
||||
<globmapper from="*" to="BOOT-INF/lib/*"/>
|
||||
</mappedresources>
|
||||
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="org.springframework.boot.loader.launch.JarLauncher" />
|
||||
<attribute name="Start-Class" value="${start-class}" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
<target name="build" depends="compile">
|
||||
<jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
|
||||
<mappedresources>
|
||||
<fileset dir="target/classes" />
|
||||
<globmapper from="*" to="BOOT-INF/classes/*"/>
|
||||
</mappedresources>
|
||||
<mappedresources>
|
||||
<fileset dir="src/main/resources" erroronmissingdir="false"/>
|
||||
<globmapper from="*" to="BOOT-INF/classes/*"/>
|
||||
</mappedresources>
|
||||
<mappedresources>
|
||||
<fileset dir="${lib.dir}/runtime" />
|
||||
<globmapper from="*" to="BOOT-INF/lib/*"/>
|
||||
</mappedresources>
|
||||
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="org.springframework.boot.loader.launch.JarLauncher" />
|
||||
<attribute name="Start-Class" value="${start-class}" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
----
|
||||
@@ -1,29 +1,31 @@
|
||||
[[howto.data-access]]
|
||||
== Data Access
|
||||
= Data Access
|
||||
|
||||
Spring Boot includes a number of starters for working with data sources.
|
||||
This section answers questions related to doing so.
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.configure-custom-datasource]]
|
||||
=== Configure a Custom DataSource
|
||||
== Configure a Custom DataSource
|
||||
|
||||
To configure your own `DataSource`, define a `@Bean` of that type in your configuration.
|
||||
Spring Boot reuses your `DataSource` anywhere one is required, including database initialization.
|
||||
If you need to externalize some settings, you can bind your `DataSource` to the environment (see "`<<features#features.external-config.typesafe-configuration-properties.third-party-configuration>>`").
|
||||
If you need to externalize some settings, you can bind your `DataSource` to the environment (see "`xref:reference:features/external-config.adoc#features.external-config.typesafe-configuration-properties.third-party-configuration[Third-party Configuration]`").
|
||||
|
||||
The following example shows how to define a data source in a bean:
|
||||
|
||||
include::code:custom/MyDataSourceConfiguration[]
|
||||
include-code::custom/MyDataSourceConfiguration[]
|
||||
|
||||
The following example shows how to define a data source by setting properties:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configblocks]
|
||||
[configprops%novalidate,yaml]
|
||||
----
|
||||
app:
|
||||
datasource:
|
||||
url: "jdbc:h2:mem:mydb"
|
||||
username: "sa"
|
||||
pool-size: 30
|
||||
app:
|
||||
datasource:
|
||||
url: "jdbc:h2:mem:mydb"
|
||||
username: "sa"
|
||||
pool-size: 30
|
||||
----
|
||||
|
||||
Assuming that `SomeDataSource` has regular JavaBean properties for the URL, the username, and the pool size, these settings are bound automatically before the `DataSource` is made available to other components.
|
||||
@@ -34,7 +36,7 @@ It also auto-detects the driver based on the JDBC URL.
|
||||
|
||||
The following example shows how to create a data source by using a `DataSourceBuilder`:
|
||||
|
||||
include::code:builder/MyDataSourceConfiguration[]
|
||||
include-code::builder/MyDataSourceConfiguration[]
|
||||
|
||||
To run an app with that `DataSource`, all you need is the connection information.
|
||||
Pool-specific settings can also be provided.
|
||||
@@ -42,14 +44,14 @@ Check the implementation that is going to be used at runtime for more details.
|
||||
|
||||
The following example shows how to define a JDBC data source by setting properties:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configblocks]
|
||||
[configprops%novalidate,yaml]
|
||||
----
|
||||
app:
|
||||
datasource:
|
||||
url: "jdbc:mysql://localhost/test"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
pool-size: 30
|
||||
app:
|
||||
datasource:
|
||||
url: "jdbc:mysql://localhost/test"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
pool-size: 30
|
||||
----
|
||||
|
||||
However, there is a catch.
|
||||
@@ -57,14 +59,14 @@ Because the actual type of the connection pool is not exposed, no keys are gener
|
||||
Also, if you happen to have Hikari on the classpath, this basic setup does not work, because Hikari has no `url` property (but does have a `jdbcUrl` property).
|
||||
In that case, you must rewrite your configuration as follows:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configblocks]
|
||||
[configprops%novalidate,yaml]
|
||||
----
|
||||
app:
|
||||
datasource:
|
||||
jdbc-url: "jdbc:mysql://localhost/test"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
pool-size: 30
|
||||
app:
|
||||
datasource:
|
||||
jdbc-url: "jdbc:mysql://localhost/test"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
pool-size: 30
|
||||
----
|
||||
|
||||
You can fix that by forcing the connection pool to use and return a dedicated implementation rather than `DataSource`.
|
||||
@@ -72,27 +74,27 @@ You cannot change the implementation at runtime, but the list of options will be
|
||||
|
||||
The following example shows how create a `HikariDataSource` with `DataSourceBuilder`:
|
||||
|
||||
include::code:simple/MyDataSourceConfiguration[]
|
||||
include-code::simple/MyDataSourceConfiguration[]
|
||||
|
||||
You can even go further by leveraging what `DataSourceProperties` does for you -- that is, by providing a default embedded database with a sensible username and password if no URL is provided.
|
||||
You can easily initialize a `DataSourceBuilder` from the state of any `DataSourceProperties` object, so you could also inject the DataSource that Spring Boot creates automatically.
|
||||
However, that would split your configuration into two namespaces: `url`, `username`, `password`, `type`, and `driver` on `spring.datasource` and the rest on your custom namespace (`app.datasource`).
|
||||
To avoid that, you can redefine a custom `DataSourceProperties` on your custom namespace, as shown in the following example:
|
||||
|
||||
include::code:configurable/MyDataSourceConfiguration[]
|
||||
include-code::configurable/MyDataSourceConfiguration[]
|
||||
|
||||
This setup puts you _in sync_ with what Spring Boot does for you by default, except that a dedicated connection pool is chosen (in code) and its settings are exposed in the `app.datasource.configuration` sub namespace.
|
||||
Because `DataSourceProperties` is taking care of the `url`/`jdbcUrl` translation for you, you can configure it as follows:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configblocks]
|
||||
[configprops%novalidate,yaml]
|
||||
----
|
||||
app:
|
||||
datasource:
|
||||
url: "jdbc:mysql://localhost/test"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
configuration:
|
||||
maximum-pool-size: 30
|
||||
app:
|
||||
datasource:
|
||||
url: "jdbc:mysql://localhost/test"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
configuration:
|
||||
maximum-pool-size: 30
|
||||
----
|
||||
|
||||
TIP: Spring Boot will expose Hikari-specific settings to `spring.datasource.hikari`.
|
||||
@@ -101,46 +103,47 @@ This example uses a more generic `configuration` sub namespace as the example do
|
||||
NOTE: Because your custom configuration chooses to go with Hikari, `app.datasource.type` has no effect.
|
||||
In practice, the builder is initialized with whatever value you might set there and then overridden by the call to `.type()`.
|
||||
|
||||
See "`<<data#data.sql.datasource>>`" in the "`Spring Boot features`" section and the {spring-boot-autoconfigure-module-code}/jdbc/DataSourceAutoConfiguration.java[`DataSourceAutoConfiguration`] class for more details.
|
||||
See "`xref:reference:data/sql.adoc#data.sql.datasource[Configure a DataSource]`" in the "`Spring Boot features`" section and the {code-spring-boot-autoconfigure-src}/jdbc/DataSourceAutoConfiguration.java[`DataSourceAutoConfiguration`] class for more details.
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.configure-two-datasources]]
|
||||
=== Configure Two DataSources
|
||||
== Configure Two DataSources
|
||||
|
||||
If you need to configure multiple data sources, you can apply the same tricks that are described in the previous section.
|
||||
You must, however, mark one of the `DataSource` instances as `@Primary`, because various auto-configurations down the road expect to be able to get one by type.
|
||||
|
||||
If you create your own `DataSource`, the auto-configuration backs off.
|
||||
In the following example, we provide the _exact_ same feature set as the auto-configuration provides on the primary data source:
|
||||
|
||||
include::code:MyDataSourcesConfiguration[]
|
||||
include-code::MyDataSourcesConfiguration[]
|
||||
|
||||
TIP: `firstDataSourceProperties` has to be flagged as `@Primary` so that the database initializer feature uses your copy (if you use the initializer).
|
||||
|
||||
Both data sources are also bound for advanced customizations.
|
||||
For instance, you could configure them as follows:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configblocks]
|
||||
[configprops%novalidate,yaml]
|
||||
----
|
||||
app:
|
||||
datasource:
|
||||
first:
|
||||
url: "jdbc:mysql://localhost/first"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
configuration:
|
||||
maximum-pool-size: 30
|
||||
app:
|
||||
datasource:
|
||||
first:
|
||||
url: "jdbc:mysql://localhost/first"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
configuration:
|
||||
maximum-pool-size: 30
|
||||
|
||||
second:
|
||||
url: "jdbc:mysql://localhost/second"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
max-total: 30
|
||||
second:
|
||||
url: "jdbc:mysql://localhost/second"
|
||||
username: "dbuser"
|
||||
password: "dbpass"
|
||||
max-total: 30
|
||||
----
|
||||
|
||||
You can apply the same concept to the secondary `DataSource` as well, as shown in the following example:
|
||||
|
||||
include::code:MyCompleteDataSourcesConfiguration[]
|
||||
include-code::MyCompleteDataSourcesConfiguration[]
|
||||
|
||||
The preceding example configures two data sources on custom namespaces with the same logic as Spring Boot would use in auto-configuration.
|
||||
Note that each `configuration` sub namespace provides advanced settings based on the chosen implementation.
|
||||
@@ -148,32 +151,35 @@ Note that each `configuration` sub namespace provides advanced settings based on
|
||||
|
||||
|
||||
[[howto.data-access.spring-data-repositories]]
|
||||
=== Use Spring Data Repositories
|
||||
== Use Spring Data Repositories
|
||||
|
||||
Spring Data can create implementations of `@Repository` interfaces of various flavors.
|
||||
Spring Boot handles all of that for you, as long as those `@Repository` annotations are included in one of the <<using#using.auto-configuration.packages,auto-configuration packages>>, typically the package (or a sub-package) of your main application class that is annotated with `@SpringBootApplication` or `@EnableAutoConfiguration`.
|
||||
Spring Boot handles all of that for you, as long as those `@Repository` annotations are included in one of the xref:reference:using/auto-configuration.adoc#using.auto-configuration.packages[auto-configuration packages], typically the package (or a sub-package) of your main application class that is annotated with `@SpringBootApplication` or `@EnableAutoConfiguration`.
|
||||
|
||||
For many applications, all you need is to put the right Spring Data dependencies on your classpath.
|
||||
There is a `spring-boot-starter-data-jpa` for JPA, `spring-boot-starter-data-mongodb` for Mongodb, and various other starters for supported technologies.
|
||||
To get started, create some repository interfaces to handle your `@Entity` objects.
|
||||
|
||||
Spring Boot determines the location of your `@Repository` definitions by scanning the <<using#using.auto-configuration.packages,auto-configuration packages>>.
|
||||
Spring Boot determines the location of your `@Repository` definitions by scanning the xref:reference:using/auto-configuration.adoc#using.auto-configuration.packages[auto-configuration packages].
|
||||
For more control, use the `@Enable…Repositories` annotations from Spring Data.
|
||||
|
||||
For more about Spring Data, see the {spring-data}[Spring Data project page].
|
||||
For more about Spring Data, see the {url-spring-data-site}[Spring Data project page].
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.separate-entity-definitions-from-spring-configuration]]
|
||||
=== Separate @Entity Definitions from Spring Configuration
|
||||
Spring Boot determines the location of your `@Entity` definitions by scanning the <<using#using.auto-configuration.packages,auto-configuration packages>>.
|
||||
== Separate @Entity Definitions from Spring Configuration
|
||||
|
||||
Spring Boot determines the location of your `@Entity` definitions by scanning the xref:reference:using/auto-configuration.adoc#using.auto-configuration.packages[auto-configuration packages].
|
||||
For more control, use the `@EntityScan` annotation, as shown in the following example:
|
||||
|
||||
include::code:MyApplication[]
|
||||
include-code::MyApplication[]
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.jpa-properties]]
|
||||
=== Configure JPA Properties
|
||||
== Configure JPA Properties
|
||||
|
||||
Spring Data JPA already provides some vendor-independent configuration options (such as those for SQL logging), and Spring Boot exposes those options and a few more for Hibernate as external configuration properties.
|
||||
Some of them are automatically detected according to the context so you should not have to set them.
|
||||
|
||||
@@ -186,14 +192,14 @@ If you prefer to set the dialect yourself, set the configprop:spring.jpa.databas
|
||||
|
||||
The most common options to set are shown in the following example:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
jpa:
|
||||
hibernate:
|
||||
naming:
|
||||
physical-strategy: "com.example.MyPhysicalNamingStrategy"
|
||||
show-sql: true
|
||||
spring:
|
||||
jpa:
|
||||
hibernate:
|
||||
naming:
|
||||
physical-strategy: "com.example.MyPhysicalNamingStrategy"
|
||||
show-sql: true
|
||||
----
|
||||
|
||||
In addition, all properties in `+spring.jpa.properties.*+` are passed through as normal JPA properties (with the prefix stripped) when the local `EntityManagerFactory` is created.
|
||||
@@ -213,8 +219,9 @@ This takes precedence to anything that is applied by the auto-configuration.
|
||||
|
||||
|
||||
[[howto.data-access.configure-hibernate-naming-strategy]]
|
||||
=== Configure Hibernate Naming Strategy
|
||||
Hibernate uses {hibernate-docs}#naming[two different naming strategies] to map names from the object model to the corresponding database names.
|
||||
== Configure Hibernate Naming Strategy
|
||||
|
||||
Hibernate uses {url-hibernate-userguide}#naming[two different naming strategies] to map names from the object model to the corresponding database names.
|
||||
The fully qualified class name of the physical and the implicit strategy implementations can be configured by setting the `spring.jpa.hibernate.naming.physical-strategy` and `spring.jpa.hibernate.naming.implicit-strategy` properties, respectively.
|
||||
Alternatively, if `ImplicitNamingStrategy` or `PhysicalNamingStrategy` beans are available in the application context, Hibernate will be automatically configured to use them.
|
||||
|
||||
@@ -224,41 +231,47 @@ Additionally, by default, all table names are generated in lower case.
|
||||
For example, a `TelephoneNumber` entity is mapped to the `telephone_number` table.
|
||||
If your schema requires mixed-case identifiers, define a custom `CamelCaseToUnderscoresNamingStrategy` bean, as shown in the following example:
|
||||
|
||||
include::code:spring/MyHibernateConfiguration[]
|
||||
include-code::spring/MyHibernateConfiguration[]
|
||||
|
||||
If you prefer to use Hibernate's default instead, set the following property:
|
||||
|
||||
[indent=0,properties,subs="verbatim"]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
||||
spring:
|
||||
jpa:
|
||||
hibernate:
|
||||
naming:
|
||||
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
|
||||
----
|
||||
|
||||
Alternatively, you can configure the following bean:
|
||||
|
||||
include::code:standard/MyHibernateConfiguration[]
|
||||
include-code::standard/MyHibernateConfiguration[]
|
||||
|
||||
See {spring-boot-autoconfigure-module-code}/orm/jpa/HibernateJpaAutoConfiguration.java[`HibernateJpaAutoConfiguration`] and {spring-boot-autoconfigure-module-code}/orm/jpa/JpaBaseConfiguration.java[`JpaBaseConfiguration`] for more details.
|
||||
See {code-spring-boot-autoconfigure-src}/orm/jpa/HibernateJpaAutoConfiguration.java[`HibernateJpaAutoConfiguration`] and {code-spring-boot-autoconfigure-src}/orm/jpa/JpaBaseConfiguration.java[`JpaBaseConfiguration`] for more details.
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.configure-hibernate-second-level-caching]]
|
||||
=== Configure Hibernate Second-Level Caching
|
||||
Hibernate {hibernate-docs}#caching[second-level cache] can be configured for a range of cache providers.
|
||||
== Configure Hibernate Second-Level Caching
|
||||
|
||||
Hibernate {url-hibernate-userguide}#caching[second-level cache] can be configured for a range of cache providers.
|
||||
Rather than configuring Hibernate to lookup the cache provider again, it is better to provide the one that is available in the context whenever possible.
|
||||
|
||||
To do this with JCache, first make sure that `org.hibernate.orm:hibernate-jcache` is available on the classpath.
|
||||
Then, add a `HibernatePropertiesCustomizer` bean as shown in the following example:
|
||||
|
||||
include::code:MyHibernateSecondLevelCacheConfiguration[]
|
||||
include-code::MyHibernateSecondLevelCacheConfiguration[]
|
||||
|
||||
This customizer will configure Hibernate to use the same `CacheManager` as the one that the application uses.
|
||||
It is also possible to use separate `CacheManager` instances.
|
||||
For details, see {hibernate-docs}#caching-provider-jcache[the Hibernate user guide].
|
||||
For details, see {url-hibernate-userguide}#caching-provider-jcache[the Hibernate user guide].
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.dependency-injection-in-hibernate-components]]
|
||||
=== Use Dependency Injection in Hibernate Components
|
||||
== Use Dependency Injection in Hibernate Components
|
||||
|
||||
By default, Spring Boot registers a `BeanContainer` implementation that uses the `BeanFactory` so that converters and entity listeners can use regular dependency injection.
|
||||
|
||||
You can disable or tune this behavior by registering a `HibernatePropertiesCustomizer` that removes or changes the `hibernate.resource.beans.container` property.
|
||||
@@ -266,20 +279,21 @@ You can disable or tune this behavior by registering a `HibernatePropertiesCusto
|
||||
|
||||
|
||||
[[howto.data-access.use-custom-entity-manager]]
|
||||
=== Use a Custom EntityManagerFactory
|
||||
== Use a Custom EntityManagerFactory
|
||||
|
||||
To take full control of the configuration of the `EntityManagerFactory`, you need to add a `@Bean` named '`entityManagerFactory`'.
|
||||
Spring Boot auto-configuration switches off its entity manager in the presence of a bean of that type.
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.use-multiple-entity-managers]]
|
||||
[[howto.data-access.use-multiple-entity-managers]]
|
||||
=== Using Multiple EntityManagerFactories
|
||||
== Using Multiple EntityManagerFactories
|
||||
|
||||
If you need to use JPA against multiple data sources, you likely need one `EntityManagerFactory` per data source.
|
||||
The `LocalContainerEntityManagerFactoryBean` from Spring ORM allows you to configure an `EntityManagerFactory` for your needs.
|
||||
You can also reuse `JpaProperties` to bind settings for each `EntityManagerFactory`, as shown in the following example:
|
||||
|
||||
include::code:MyEntityManagerFactoryConfiguration[]
|
||||
include-code::MyEntityManagerFactoryConfiguration[]
|
||||
|
||||
The example above creates an `EntityManagerFactory` using a `DataSource` bean named `firstDataSource`.
|
||||
It scans entities located in the same package as `Order`.
|
||||
@@ -295,23 +309,25 @@ Alternatively, you might be able to use a JTA transaction manager that spans bot
|
||||
|
||||
If you use Spring Data, you need to configure `@EnableJpaRepositories` accordingly, as shown in the following examples:
|
||||
|
||||
include::code:OrderConfiguration[]
|
||||
include-code::OrderConfiguration[]
|
||||
|
||||
include::code:CustomerConfiguration[]
|
||||
include-code::CustomerConfiguration[]
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.use-traditional-persistence-xml]]
|
||||
=== Use a Traditional persistence.xml File
|
||||
== Use a Traditional persistence.xml File
|
||||
|
||||
Spring Boot will not search for or use a `META-INF/persistence.xml` by default.
|
||||
If you prefer to use a traditional `persistence.xml`, you need to define your own `@Bean` of type `LocalEntityManagerFactoryBean` (with an ID of '`entityManagerFactory`') and set the persistence unit name there.
|
||||
|
||||
See {spring-boot-autoconfigure-module-code}/orm/jpa/JpaBaseConfiguration.java[`JpaBaseConfiguration`] for the default settings.
|
||||
See {code-spring-boot-autoconfigure-src}/orm/jpa/JpaBaseConfiguration.java[`JpaBaseConfiguration`] for the default settings.
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.use-spring-data-jpa-and-mongo-repositories]]
|
||||
=== Use Spring Data JPA and Mongo Repositories
|
||||
== Use Spring Data JPA and Mongo Repositories
|
||||
|
||||
Spring Data JPA and Spring Data Mongo can both automatically create `Repository` implementations for you.
|
||||
If they are both present on the classpath, you might have to do some extra configuration to tell Spring Boot which repositories to create.
|
||||
The most explicit way to do that is to use the standard Spring Data `+@EnableJpaRepositories+` and `+@EnableMongoRepositories+` annotations and provide the location of your `Repository` interfaces.
|
||||
@@ -325,7 +341,8 @@ To work with them, change the names of the annotations and flags accordingly.
|
||||
|
||||
|
||||
[[howto.data-access.customize-spring-data-web-support]]
|
||||
=== Customize Spring Data's Web Support
|
||||
== Customize Spring Data's Web Support
|
||||
|
||||
Spring Data provides web support that simplifies the use of Spring Data repositories in a web application.
|
||||
Spring Boot provides properties in the `spring.data.web` namespace for customizing its configuration.
|
||||
Note that if you are using Spring Data REST, you must use the properties in the `spring.data.rest` namespace instead.
|
||||
@@ -333,12 +350,13 @@ Note that if you are using Spring Data REST, you must use the properties in the
|
||||
|
||||
|
||||
[[howto.data-access.exposing-spring-data-repositories-as-rest]]
|
||||
=== Expose Spring Data Repositories as REST Endpoint
|
||||
== Expose Spring Data Repositories as REST Endpoint
|
||||
|
||||
Spring Data REST can expose the `Repository` implementations as REST endpoints for you,
|
||||
provided Spring MVC has been enabled for the application.
|
||||
|
||||
Spring Boot exposes a set of useful properties (from the `spring.data.rest` namespace) that customize the {spring-data-rest-api}/core/config/RepositoryRestConfiguration.html[`RepositoryRestConfiguration`].
|
||||
If you need to provide additional customization, you should use a {spring-data-rest-api}/webmvc/config/RepositoryRestConfigurer.html[`RepositoryRestConfigurer`] bean.
|
||||
Spring Boot exposes a set of useful properties (from the `spring.data.rest` namespace) that customize the {url-spring-data-rest-javadoc}/org/springframework/data/rest/core/config/RepositoryRestConfiguration.html[`RepositoryRestConfiguration`].
|
||||
If you need to provide additional customization, you should use a {url-spring-data-rest-javadoc}/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurer.html[`RepositoryRestConfigurer`] bean.
|
||||
|
||||
NOTE: If you do not specify any order on your custom `RepositoryRestConfigurer`, it runs after the one Spring Boot uses internally.
|
||||
If you need to specify an order, make sure it is higher than 0.
|
||||
@@ -346,7 +364,8 @@ If you need to specify an order, make sure it is higher than 0.
|
||||
|
||||
|
||||
[[howto.data-access.configure-a-component-that-is-used-by-jpa]]
|
||||
=== Configure a Component that is Used by JPA
|
||||
== Configure a Component that is Used by JPA
|
||||
|
||||
If you want to configure a component that JPA uses, then you need to ensure that the component is initialized before JPA.
|
||||
When the component is auto-configured, Spring Boot takes care of this for you.
|
||||
For example, when Flyway is auto-configured, Hibernate is configured to depend upon Flyway so that Flyway has a chance to initialize the database before Hibernate tries to use it.
|
||||
@@ -354,13 +373,14 @@ For example, when Flyway is auto-configured, Hibernate is configured to depend u
|
||||
If you are configuring a component yourself, you can use an `EntityManagerFactoryDependsOnPostProcessor` subclass as a convenient way of setting up the necessary dependencies.
|
||||
For example, if you use Hibernate Search with Elasticsearch as its index manager, any `EntityManagerFactory` beans must be configured to depend on the `elasticsearchClient` bean, as shown in the following example:
|
||||
|
||||
include::code:ElasticsearchEntityManagerFactoryDependsOnPostProcessor[]
|
||||
include-code::ElasticsearchEntityManagerFactoryDependsOnPostProcessor[]
|
||||
|
||||
|
||||
|
||||
[[howto.data-access.configure-jooq-with-multiple-datasources]]
|
||||
=== Configure jOOQ with Two DataSources
|
||||
== Configure jOOQ with Two DataSources
|
||||
|
||||
If you need to use jOOQ with multiple data sources, you should create your own `DSLContext` for each one.
|
||||
See {spring-boot-autoconfigure-module-code}/jooq/JooqAutoConfiguration.java[JooqAutoConfiguration] for more details.
|
||||
See {code-spring-boot-autoconfigure-src}/jooq/JooqAutoConfiguration.java[JooqAutoConfiguration] for more details.
|
||||
|
||||
TIP: In particular, `JooqExceptionTranslator` and `SpringTransactionProvider` can be reused to provide similar features to what the auto-configuration does with a single `DataSource`.
|
||||
@@ -1,5 +1,6 @@
|
||||
[[howto.data-initialization]]
|
||||
== Database Initialization
|
||||
= Database Initialization
|
||||
|
||||
An SQL database can be initialized in different ways depending on what your stack is.
|
||||
Of course, you can also do it manually, provided the database is a separate process.
|
||||
It is recommended to use a single mechanism for schema generation.
|
||||
@@ -7,7 +8,8 @@ It is recommended to use a single mechanism for schema generation.
|
||||
|
||||
|
||||
[[howto.data-initialization.using-jpa]]
|
||||
=== Initialize a Database Using JPA
|
||||
== Initialize a Database Using JPA
|
||||
|
||||
JPA has features for DDL generation, and these can be set up to run on startup against the database.
|
||||
This is controlled through two external properties:
|
||||
|
||||
@@ -18,7 +20,8 @@ This is controlled through two external properties:
|
||||
|
||||
|
||||
[[howto.data-initialization.using-hibernate]]
|
||||
=== Initialize a Database Using Hibernate
|
||||
== Initialize a Database Using Hibernate
|
||||
|
||||
You can set `spring.jpa.hibernate.ddl-auto` explicitly to one of the standard Hibernate property values which are `none`, `validate`, `update`, `create`, and `create-drop`.
|
||||
Spring Boot chooses a default value for you based on whether it thinks your database is embedded.
|
||||
It defaults to `create-drop` if no schema manager has been detected or `none` in all other cases.
|
||||
@@ -28,7 +31,7 @@ Be careful when switching from in-memory to a '`real`' database that you do not
|
||||
You either have to set `ddl-auto` explicitly or use one of the other mechanisms to initialize the database.
|
||||
|
||||
NOTE: You can output the schema creation by enabling the `org.hibernate.SQL` logger.
|
||||
This is done for you automatically if you enable the <<features#features.logging.console-output,debug mode>>.
|
||||
This is done for you automatically if you enable the xref:reference:features/logging.adoc#features.logging.console-output[debug mode].
|
||||
|
||||
In addition, a file named `import.sql` in the root of the classpath is executed on startup if Hibernate creates the schema from scratch (that is, if the `ddl-auto` property is set to `create` or `create-drop`).
|
||||
This can be useful for demos and for testing if you are careful but is probably not something you want to be on the classpath in production.
|
||||
@@ -37,7 +40,8 @@ It is a Hibernate feature (and has nothing to do with Spring).
|
||||
|
||||
|
||||
[[howto.data-initialization.using-basic-sql-scripts]]
|
||||
=== Initialize a Database Using Basic SQL Scripts
|
||||
== Initialize a Database Using Basic SQL Scripts
|
||||
|
||||
Spring Boot can automatically create the schema (DDL scripts) of your JDBC `DataSource` or R2DBC `ConnectionFactory` and initialize its data (DML scripts).
|
||||
|
||||
By default, it loads schema scripts from `optional:classpath*:schema.sql` and data scripts from `optional:classpath*:data.sql`.
|
||||
@@ -65,26 +69,27 @@ This will defer data source initialization until after any `EntityManagerFactory
|
||||
NOTE: The initialization scripts support `--` for single line comments and `/++*++ ++*++/` for block comments.
|
||||
Other comment formats are not supported.
|
||||
|
||||
If you are using a <<howto#howto.data-initialization.migration-tool,Higher-level Database Migration Tool>>, like Flyway or Liquibase, you should use them alone to create and initialize the schema.
|
||||
If you are using a xref:data-initialization.adoc#howto.data-initialization.migration-tool[Higher-level Database Migration Tool], like Flyway or Liquibase, you should use them alone to create and initialize the schema.
|
||||
Using the basic `schema.sql` and `data.sql` scripts alongside Flyway or Liquibase is not recommended and support will be removed in a future release.
|
||||
|
||||
If you need to initialize test data using a higher-level database migration tool, please see the sections about <<howto#howto.data-initialization.migration-tool.flyway-tests, Flyway>> and <<howto#howto.data-initialization.migration-tool.liquibase-tests, Liquibase>>.
|
||||
If you need to initialize test data using a higher-level database migration tool, please see the sections about xref:data-initialization.adoc#howto.data-initialization.migration-tool.flyway-tests[Flyway] and xref:data-initialization.adoc#howto.data-initialization.migration-tool.liquibase-tests[Liquibase].
|
||||
|
||||
|
||||
|
||||
[[howto.data-initialization.batch]]
|
||||
=== Initialize a Spring Batch Database
|
||||
== Initialize a Spring Batch Database
|
||||
|
||||
If you use Spring Batch, it comes pre-packaged with SQL initialization scripts for most popular database platforms.
|
||||
Spring Boot can detect your database type and execute those scripts on startup.
|
||||
If you use an embedded database, this happens by default.
|
||||
You can also enable it for any database type, as shown in the following example:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
batch:
|
||||
jdbc:
|
||||
initialize-schema: "always"
|
||||
spring:
|
||||
batch:
|
||||
jdbc:
|
||||
initialize-schema: "always"
|
||||
----
|
||||
|
||||
You can also switch off the initialization explicitly by setting `spring.batch.jdbc.initialize-schema` to `never`.
|
||||
@@ -92,13 +97,15 @@ You can also switch off the initialization explicitly by setting `spring.batch.j
|
||||
|
||||
|
||||
[[howto.data-initialization.migration-tool]]
|
||||
=== Use a Higher-level Database Migration Tool
|
||||
== Use a Higher-level Database Migration Tool
|
||||
|
||||
Spring Boot supports two higher-level migration tools: https://flywaydb.org/[Flyway] and https://www.liquibase.org/[Liquibase].
|
||||
|
||||
|
||||
|
||||
[[howto.data-initialization.migration-tool.flyway]]
|
||||
==== Execute Flyway Database Migrations on Startup
|
||||
=== Execute Flyway Database Migrations on Startup
|
||||
|
||||
To automatically run Flyway database migrations on startup, add the `org.flywaydb:flyway-core` to your classpath.
|
||||
|
||||
Typically, migrations are scripts in the form `V<VERSION>__<NAME>.sql` (with `<VERSION>` an underscore-separated version, such as '`1`' or '`2_1`').
|
||||
@@ -106,34 +113,34 @@ By default, they are in a directory called `classpath:db/migration`, but you can
|
||||
This is a comma-separated list of one or more `classpath:` or `filesystem:` locations.
|
||||
For example, the following configuration would search for scripts in both the default classpath location and the `/opt/migration` directory:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
flyway:
|
||||
locations: "classpath:db/migration,filesystem:/opt/migration"
|
||||
spring:
|
||||
flyway:
|
||||
locations: "classpath:db/migration,filesystem:/opt/migration"
|
||||
----
|
||||
|
||||
You can also add a special `\{vendor}` placeholder to use vendor-specific scripts.
|
||||
Assume the following:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
flyway:
|
||||
locations: "classpath:db/migration/{vendor}"
|
||||
spring:
|
||||
flyway:
|
||||
locations: "classpath:db/migration/{vendor}"
|
||||
----
|
||||
|
||||
Rather than using `db/migration`, the preceding configuration sets the directory to use according to the type of the database (such as `db/migration/mysql` for MySQL).
|
||||
The list of supported databases is available in {spring-boot-module-code}/jdbc/DatabaseDriver.java[`DatabaseDriver`].
|
||||
The list of supported databases is available in {code-spring-boot-src}/jdbc/DatabaseDriver.java[`DatabaseDriver`].
|
||||
|
||||
Migrations can also be written in Java.
|
||||
Flyway will be auto-configured with any beans that implement `JavaMigration`.
|
||||
|
||||
{spring-boot-autoconfigure-module-code}/flyway/FlywayProperties.java[`FlywayProperties`] provides most of Flyway's settings and a small set of additional properties that can be used to disable the migrations or switch off the location checking.
|
||||
{code-spring-boot-autoconfigure-src}/flyway/FlywayProperties.java[`FlywayProperties`] provides most of Flyway's settings and a small set of additional properties that can be used to disable the migrations or switch off the location checking.
|
||||
If you need more control over the configuration, consider registering a `FlywayConfigurationCustomizer` bean.
|
||||
|
||||
Spring Boot calls `Flyway.migrate()` to perform the database migration.
|
||||
If you would like more control, provide a `@Bean` that implements {spring-boot-autoconfigure-module-code}/flyway/FlywayMigrationStrategy.java[`FlywayMigrationStrategy`].
|
||||
If you would like more control, provide a `@Bean` that implements {code-spring-boot-autoconfigure-src}/flyway/FlywayMigrationStrategy.java[`FlywayMigrationStrategy`].
|
||||
|
||||
Flyway supports SQL and Java https://flywaydb.org/documentation/concepts/callbacks[callbacks].
|
||||
To use SQL-based callbacks, place the callback scripts in the `classpath:db/migration` directory.
|
||||
@@ -154,11 +161,11 @@ For example, you can place test-specific migrations in `src/test/resources` and
|
||||
Also, you can use profile-specific configuration to customize `spring.flyway.locations` so that certain migrations run only when a particular profile is active.
|
||||
For example, in `application-dev.properties`, you might specify the following setting:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
flyway:
|
||||
locations: "classpath:/db/migration,classpath:/dev/db/migration"
|
||||
spring:
|
||||
flyway:
|
||||
locations: "classpath:/db/migration,classpath:/dev/db/migration"
|
||||
----
|
||||
|
||||
With that setup, migrations in `dev/db/migration` run only when the `dev` profile is active.
|
||||
@@ -166,7 +173,8 @@ With that setup, migrations in `dev/db/migration` run only when the `dev` profil
|
||||
|
||||
|
||||
[[howto.data-initialization.migration-tool.liquibase]]
|
||||
==== Execute Liquibase Database Migrations on Startup
|
||||
=== Execute Liquibase Database Migrations on Startup
|
||||
|
||||
To automatically run Liquibase database migrations on startup, add the `org.liquibase:liquibase-core` to your classpath.
|
||||
|
||||
[NOTE]
|
||||
@@ -186,12 +194,13 @@ Alternatively, you can use Liquibase's native `DataSource` by setting `spring.li
|
||||
Setting either `spring.liquibase.url` or `spring.liquibase.user` is sufficient to cause Liquibase to use its own `DataSource`.
|
||||
If any of the three properties has not been set, the value of its equivalent `spring.datasource` property will be used.
|
||||
|
||||
See {spring-boot-autoconfigure-module-code}/liquibase/LiquibaseProperties.java[`LiquibaseProperties`] for details about available settings such as contexts, the default schema, and others.
|
||||
See {code-spring-boot-autoconfigure-src}/liquibase/LiquibaseProperties.java[`LiquibaseProperties`] for details about available settings such as contexts, the default schema, and others.
|
||||
|
||||
|
||||
|
||||
[[howto.data-initialization.migration-tool.flyway-tests]]
|
||||
==== Use Flyway for test-only migrations
|
||||
=== Use Flyway for test-only migrations
|
||||
|
||||
If you want to create Flyway migrations which populate your test database, place them in `src/test/resources/db/migration`.
|
||||
A file named, for example, `src/test/resources/db/migration/V9999__test-data.sql` will be executed after your production migrations and only if you're running the tests.
|
||||
You can use this file to create the needed test data.
|
||||
@@ -200,14 +209,15 @@ 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
|
||||
=== 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.
|
||||
|
||||
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:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
spring:
|
||||
liquibase:
|
||||
@@ -218,7 +228,7 @@ This configures Liquibase to use a different changelog when running in the `test
|
||||
|
||||
Now create the changelog file at `src/test/resources/db/changelog/db.changelog-test.yaml`:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim"]
|
||||
[source,yaml]
|
||||
----
|
||||
databaseChangeLog:
|
||||
- include:
|
||||
@@ -240,7 +250,8 @@ To do this, you can add the `@ActiveProfiles("test")` annotation to your `@Sprin
|
||||
|
||||
|
||||
[[howto.data-initialization.dependencies]]
|
||||
=== Depend Upon an Initialized Database
|
||||
== Depend Upon an Initialized Database
|
||||
|
||||
Database initialization is performed while the application is starting up as part of application context refresh.
|
||||
To allow an initialized database to be accessed during startup, beans that act as database initializers and beans that require that database to have been initialized are detected automatically.
|
||||
Beans whose initialization depends upon the database having been initialized are configured to depend upon those that initialize it.
|
||||
@@ -249,7 +260,8 @@ If, during startup, your application tries to access the database and it has not
|
||||
|
||||
|
||||
[[howto.data-initialization.dependencies.initializer-detection]]
|
||||
==== Detect a Database Initializer
|
||||
=== Detect a Database Initializer
|
||||
|
||||
Spring Boot will automatically detect beans of the following types that initialize an SQL database:
|
||||
|
||||
- `DataSourceScriptDatabaseInitializer`
|
||||
@@ -265,7 +277,8 @@ To have other beans be detected, register an implementation of `DatabaseInitiali
|
||||
|
||||
|
||||
[[howto.data-initialization.dependencies.depends-on-initialization-detection]]
|
||||
==== Detect a Bean That Depends On Database Initialization
|
||||
=== Detect a Bean That Depends On Database Initialization
|
||||
|
||||
Spring Boot will automatically detect beans of the following types that depends upon database initialization:
|
||||
|
||||
- `AbstractEntityManagerFactoryBean` (unless configprop:spring.jpa.defer-datasource-initialization[] is set to `true`)
|
||||
@@ -1,16 +1,18 @@
|
||||
[[howto.docker-compose]]
|
||||
== Docker Compose
|
||||
= Docker Compose
|
||||
|
||||
This section includes topics relating to the Docker Compose support in Spring Boot.
|
||||
|
||||
|
||||
|
||||
[[howto.docker-compose.jdbc-url]]
|
||||
=== Customizing the JDBC URL
|
||||
== Customizing the JDBC URL
|
||||
|
||||
When using `JdbcConnectionDetails` with Docker Compose, the parameters of the JDBC URL
|
||||
can be customized by applying the `org.springframework.boot.jdbc.parameters` label to the
|
||||
service. For example:
|
||||
|
||||
[source,yaml,indent=0]
|
||||
[source,yaml]
|
||||
----
|
||||
services:
|
||||
postgres:
|
||||
@@ -30,7 +32,7 @@ With this Docker Compose file in place, the JDBC URL used is `jdbc:postgresql://
|
||||
|
||||
|
||||
[[howto.docker-compose.sharing-services]]
|
||||
=== Sharing services between multiple applications
|
||||
== Sharing services between multiple applications
|
||||
|
||||
If you want to share services between multiple applications, create the `compose.yaml` file in one of the applications and then use the configuration property configprop:spring.docker.compose.file[] in the other applications to reference the `compose.yaml` file.
|
||||
You should also set configprop:spring.docker.compose.lifecycle-management[] to `start-only`, as it defaults to `start-and-stop` and stopping one application would shut down the shared services for the other still running applications as well.
|
||||
@@ -1,67 +1,75 @@
|
||||
[[howto.hotswapping]]
|
||||
== Hot Swapping
|
||||
= Hot Swapping
|
||||
|
||||
Spring Boot supports hot swapping.
|
||||
This section answers questions about how it works.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.reload-static-content]]
|
||||
=== Reload Static Content
|
||||
== Reload Static Content
|
||||
|
||||
There are several options for hot reloading.
|
||||
The recommended approach is to use <<using#using.devtools,`spring-boot-devtools`>>, as it provides additional development-time features, such as support for fast application restarts and LiveReload as well as sensible development-time configuration (such as template caching).
|
||||
The recommended approach is to use xref:reference:using/devtools.adoc[`spring-boot-devtools`], as it provides additional development-time features, such as support for fast application restarts and LiveReload as well as sensible development-time configuration (such as template caching).
|
||||
Devtools works by monitoring the classpath for changes.
|
||||
This means that static resource changes must be "built" for the change to take effect.
|
||||
By default, this happens automatically in Eclipse when you save your changes.
|
||||
In IntelliJ IDEA, the Make Project command triggers the necessary build.
|
||||
Due to the <<using#using.devtools.restart.excluding-resources, default restart exclusions>>, changes to static resources do not trigger a restart of your application.
|
||||
Due to the xref:reference:using/devtools.adoc#using.devtools.restart.excluding-resources[default restart exclusions], changes to static resources do not trigger a restart of your application.
|
||||
They do, however, trigger a live reload.
|
||||
|
||||
Alternatively, running in an IDE (especially with debugging on) is a good way to do development (all modern IDEs allow reloading of static resources and usually also allow hot-swapping of Java class changes).
|
||||
|
||||
Finally, the <<build-tool-plugins#build-tool-plugins, Maven and Gradle plugins>> can be configured (see the `addResources` property) to support running from the command line with reloading of static files directly from source.
|
||||
Finally, the xref:build-tool-plugin:index.adoc[Maven and Gradle plugins] can be configured (see the `addResources` property) to support running from the command line with reloading of static files directly from source.
|
||||
You can use that with an external css/js compiler process if you are writing that code with higher-level tools.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.reload-templates]]
|
||||
=== Reload Templates without Restarting the Container
|
||||
== Reload Templates without Restarting the Container
|
||||
|
||||
Most of the templating technologies supported by Spring Boot include a configuration option to disable caching (described later in this document).
|
||||
If you use the `spring-boot-devtools` module, these properties are <<using#using.devtools.property-defaults,automatically configured>> for you at development time.
|
||||
If you use the `spring-boot-devtools` module, these properties are xref:reference:using/devtools.adoc#using.devtools.property-defaults[automatically configured] for you at development time.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.reload-templates.thymeleaf]]
|
||||
==== Thymeleaf Templates
|
||||
=== Thymeleaf Templates
|
||||
|
||||
If you use Thymeleaf, set `spring.thymeleaf.cache` to `false`.
|
||||
See {spring-boot-autoconfigure-module-code}/thymeleaf/ThymeleafAutoConfiguration.java[`ThymeleafAutoConfiguration`] for other Thymeleaf customization options.
|
||||
See {code-spring-boot-autoconfigure-src}/thymeleaf/ThymeleafAutoConfiguration.java[`ThymeleafAutoConfiguration`] for other Thymeleaf customization options.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.reload-templates.freemarker]]
|
||||
==== FreeMarker Templates
|
||||
=== FreeMarker Templates
|
||||
|
||||
If you use FreeMarker, set `spring.freemarker.cache` to `false`.
|
||||
See {spring-boot-autoconfigure-module-code}/freemarker/FreeMarkerAutoConfiguration.java[`FreeMarkerAutoConfiguration`] for other FreeMarker customization options.
|
||||
See {code-spring-boot-autoconfigure-src}/freemarker/FreeMarkerAutoConfiguration.java[`FreeMarkerAutoConfiguration`] for other FreeMarker customization options.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.reload-templates.groovy]]
|
||||
==== Groovy Templates
|
||||
=== Groovy Templates
|
||||
|
||||
If you use Groovy templates, set `spring.groovy.template.cache` to `false`.
|
||||
See {spring-boot-autoconfigure-module-code}/groovy/template/GroovyTemplateAutoConfiguration.java[`GroovyTemplateAutoConfiguration`] for other Groovy customization options.
|
||||
See {code-spring-boot-autoconfigure-src}/groovy/template/GroovyTemplateAutoConfiguration.java[`GroovyTemplateAutoConfiguration`] for other Groovy customization options.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.fast-application-restarts]]
|
||||
=== Fast Application Restarts
|
||||
== Fast Application Restarts
|
||||
|
||||
The `spring-boot-devtools` module includes support for automatic application restarts.
|
||||
While not as fast as technologies such as https://www.jrebel.com/products/jrebel[JRebel] it is usually significantly faster than a "`cold start`".
|
||||
You should probably give it a try before investigating some of the more complex reload options discussed later in this document.
|
||||
|
||||
For more details, see the <<using#using.devtools>> section.
|
||||
For more details, see the xref:reference:using/devtools.adoc[Developer Tools] section.
|
||||
|
||||
|
||||
|
||||
[[howto.hotswapping.reload-java-classes-without-restarting]]
|
||||
=== Reload Java Classes without Restarting the Container
|
||||
== Reload Java Classes without Restarting the Container
|
||||
|
||||
Many modern IDEs (Eclipse, IDEA, and others) support hot swapping of bytecode.
|
||||
Consequently, if you make a change that does not affect class or method signatures, it should reload cleanly with no side effects.
|
||||
@@ -1,13 +1,15 @@
|
||||
[[howto.http-clients]]
|
||||
== HTTP Clients
|
||||
= HTTP Clients
|
||||
|
||||
Spring Boot offers a number of starters that work with HTTP clients.
|
||||
This section answers questions related to using them.
|
||||
|
||||
|
||||
|
||||
[[howto.http-clients.rest-template-proxy-configuration]]
|
||||
=== Configure RestTemplate to Use a Proxy
|
||||
As described in <<io#io.rest-client.resttemplate.customization>>, you can use a `RestTemplateCustomizer` with `RestTemplateBuilder` to build a customized `RestTemplate`.
|
||||
== Configure RestTemplate to Use a Proxy
|
||||
|
||||
As described in xref:reference:io/rest-client.adoc#io.rest-client.resttemplate.customization[RestTemplate Customization], you can use a `RestTemplateCustomizer` with `RestTemplateBuilder` to build a customized `RestTemplate`.
|
||||
This is the recommended approach for creating a `RestTemplate` configured to use a proxy.
|
||||
|
||||
The exact details of the proxy configuration depend on the underlying client request factory that is being used.
|
||||
@@ -15,12 +17,13 @@ The exact details of the proxy configuration depend on the underlying client req
|
||||
|
||||
|
||||
[[howto.http-clients.webclient-reactor-netty-customization]]
|
||||
=== Configure the TcpClient used by a Reactor Netty-based WebClient
|
||||
== Configure the TcpClient used by a Reactor Netty-based WebClient
|
||||
|
||||
When Reactor Netty is on the classpath a Reactor Netty-based `WebClient` is auto-configured.
|
||||
To customize the client's handling of network connections, provide a `ClientHttpConnector` bean.
|
||||
The following example configures a 60 second connect timeout and adds a `ReadTimeoutHandler`:
|
||||
|
||||
include::code:MyReactorNettyClientConfiguration[]
|
||||
include-code::MyReactorNettyClientConfiguration[]
|
||||
|
||||
TIP: Note the use of `ReactorResourceFactory` for the connection provider and event loop resources.
|
||||
This ensures efficient sharing of resources for the server receiving requests and the client making requests.
|
||||
@@ -0,0 +1,12 @@
|
||||
[[howto]]
|
||||
= How-to Guides
|
||||
|
||||
This section provides answers to some common '`how do I do that...`' questions that often arise when using Spring Boot.
|
||||
Its coverage is not exhaustive, but it does cover quite a lot.
|
||||
|
||||
If you have a specific problem that we do not cover here, you might want to check https://stackoverflow.com/tags/spring-boot[stackoverflow.com] to see if someone has already provided an answer.
|
||||
This is also a great place to ask new questions (please use the `spring-boot` tag).
|
||||
|
||||
We are also more than happy to extend this section.
|
||||
If you want to add a '`how-to`', send us a {url-github}[pull request].
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
[[howto.jersey]]
|
||||
== Jersey
|
||||
= Jersey
|
||||
|
||||
|
||||
|
||||
[[howto.jersey.spring-security]]
|
||||
=== Secure Jersey endpoints with Spring Security
|
||||
== Secure Jersey endpoints with Spring Security
|
||||
|
||||
Spring Security can be used to secure a Jersey-based web application in much the same way as it can be used to secure a Spring MVC-based web application.
|
||||
However, if you want to use Spring Security's method-level security with Jersey, you must configure Jersey to use `setStatus(int)` rather `sendError(int)`.
|
||||
This prevents Jersey from committing the response before Spring Security has had an opportunity to report an authentication or authorization failure to the client.
|
||||
|
||||
The `jersey.config.server.response.setStatusOverSendError` property must be set to `true` on the application's `ResourceConfig` bean, as shown in the following example:
|
||||
|
||||
[source,java,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::{docs-java}/howto/jersey/springsecurity/JerseySetStatusOverSendErrorConfig.java[]
|
||||
----
|
||||
include-code::JerseySetStatusOverSendErrorConfig[]
|
||||
|
||||
|
||||
|
||||
[[howto.jersey.alongside-another-web-framework]]
|
||||
=== Use Jersey Alongside Another Web Framework
|
||||
== Use Jersey Alongside Another Web Framework
|
||||
|
||||
To use Jersey alongside another web framework, such as Spring MVC, it should be configured so that it will allow the other framework to handle requests that it cannot handle.
|
||||
First, configure Jersey to use a filter rather than a servlet by configuring the configprop:spring.jersey.type[] application property with a value of `filter`.
|
||||
Second, configure your `ResourceConfig` to forward requests that would have resulted in a 404, as shown in the following example.
|
||||
|
||||
[source,java,indent=0,subs="verbatim"]
|
||||
----
|
||||
include::{docs-java}/howto/jersey/alongsideanotherwebframework/JerseyConfig.java[]
|
||||
----
|
||||
includ-code::alongsideanotherwebframework/JerseyConfig[]
|
||||
@@ -1,17 +1,18 @@
|
||||
[[howto.logging]]
|
||||
== Logging
|
||||
= Logging
|
||||
|
||||
Spring Boot has no mandatory logging dependency, except for the Commons Logging API, which is typically provided by Spring Framework's `spring-jcl` module.
|
||||
To use https://logback.qos.ch[Logback], you need to include it and `spring-jcl` on the classpath.
|
||||
The recommended way to do that is through the starters, which all depend on `spring-boot-starter-logging`.
|
||||
For a web application, you only need `spring-boot-starter-web`, since it depends transitively on the logging starter.
|
||||
If you use Maven, the following dependency adds logging for you:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
Spring Boot has a `LoggingSystem` abstraction that attempts to configure logging based on the content of the classpath.
|
||||
@@ -19,12 +20,12 @@ If Logback is available, it is the first choice.
|
||||
|
||||
If the only change you need to make to logging is to set the levels of various loggers, you can do so in `application.properties` by using the "logging.level" prefix, as shown in the following example:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
logging:
|
||||
level:
|
||||
org.springframework.web: "debug"
|
||||
org.hibernate: "error"
|
||||
logging:
|
||||
level:
|
||||
org.springframework.web: "debug"
|
||||
org.hibernate: "error"
|
||||
----
|
||||
|
||||
You can also set the location of a file to which the log will be written (in addition to the console) by using `logging.file.name`.
|
||||
@@ -35,10 +36,11 @@ By default, Spring Boot picks up the native configuration from its default locat
|
||||
|
||||
|
||||
[[howto.logging.logback]]
|
||||
=== Configure Logback for Logging
|
||||
== Configure Logback for Logging
|
||||
|
||||
If you need to apply customizations to logback beyond those that can be achieved with `application.properties`, you will need to add a standard logback configuration file.
|
||||
You can add a `logback.xml` file to the root of your classpath for logback to find.
|
||||
You can also use `logback-spring.xml` if you want to use the <<features#features.logging.logback-extensions,Spring Boot Logback extensions>>.
|
||||
You can also use `logback-spring.xml` if you want to use the xref:reference:features/logging.adoc#features.logging.logback-extensions[Spring Boot Logback extensions].
|
||||
|
||||
TIP: The Logback documentation has a https://logback.qos.ch/manual/configuration.html[dedicated section that covers configuration] in some detail.
|
||||
|
||||
@@ -55,17 +57,17 @@ In addition, a legacy `base.xml` file is provided for compatibility with earlier
|
||||
|
||||
A typical custom `logback.xml` file would look something like this:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</root>
|
||||
<logger name="org.springframework.web" level="DEBUG"/>
|
||||
</configuration>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</root>
|
||||
<logger name="org.springframework.web" level="DEBUG"/>
|
||||
</configuration>
|
||||
----
|
||||
|
||||
Your logback configuration file can also make use of System properties that the `LoggingSystem` takes care of creating for you:
|
||||
@@ -88,35 +90,37 @@ Any `logback-spring.groovy` files will not be detected.
|
||||
|
||||
|
||||
[[howto.logging.logback.file-only-output]]
|
||||
==== Configure Logback for File-only Output
|
||||
=== Configure Logback for File-only Output
|
||||
|
||||
If you want to disable console logging and write output only to a file, you need a custom `logback-spring.xml` that imports `file-appender.xml` but not `console-appender.xml`, as shown in the following example:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
|
||||
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
|
||||
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
|
||||
<root level="INFO">
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
</configuration>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
|
||||
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
|
||||
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
|
||||
<root level="INFO">
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
</configuration>
|
||||
----
|
||||
|
||||
You also need to add `logging.file.name` to your `application.properties` or `application.yaml`, as shown in the following example:
|
||||
|
||||
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
|
||||
[configprops,yaml]
|
||||
----
|
||||
logging:
|
||||
file:
|
||||
name: "myapplication.log"
|
||||
logging:
|
||||
file:
|
||||
name: "myapplication.log"
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[howto.logging.log4j]]
|
||||
=== Configure Log4j for Logging
|
||||
== Configure Log4j for Logging
|
||||
|
||||
Spring Boot supports https://logging.apache.org/log4j/2.x/[Log4j 2] for logging configuration if it is on the classpath.
|
||||
If you use the starters for assembling dependencies, you have to exclude Logback and then include Log4j 2 instead.
|
||||
If you do not use the starters, you need to provide (at least) `spring-jcl` in addition to Log4j 2.
|
||||
@@ -124,42 +128,42 @@ If you do not use the starters, you need to provide (at least) `spring-jcl` in a
|
||||
The recommended path is through the starters, even though it requires some jiggling.
|
||||
The following example shows how to set up the starters in Maven:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
[source,xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
Gradle provides a few different ways to set up the starters.
|
||||
One way is to use a {gradle-docs}/resolution_rules.html#sec:module_replacement[module replacement].
|
||||
One way is to use a {url-gradle-docs}/resolution_rules.html#sec:module_replacement[module replacement].
|
||||
To do so, declare a dependency on the Log4j 2 starter and tell Gradle that any occurrences of the default logging starter should be replaced by the Log4j 2 starter, as shown in the following example:
|
||||
|
||||
[source,gradle,indent=0,subs="verbatim"]
|
||||
[source,gradle]
|
||||
----
|
||||
dependencies {
|
||||
implementation "org.springframework.boot:spring-boot-starter-log4j2"
|
||||
modules {
|
||||
module("org.springframework.boot:spring-boot-starter-logging") {
|
||||
replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
|
||||
}
|
||||
dependencies {
|
||||
implementation "org.springframework.boot:spring-boot-starter-log4j2"
|
||||
modules {
|
||||
module("org.springframework.boot:spring-boot-starter-logging") {
|
||||
replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: The Log4j starters gather together the dependencies for common logging requirements (such as having Tomcat use `java.util.logging` but configuring the output using Log4j 2).
|
||||
@@ -169,7 +173,8 @@ NOTE: To ensure that debug logging performed using `java.util.logging` is routed
|
||||
|
||||
|
||||
[[howto.logging.log4j.yaml-or-json-config]]
|
||||
==== Use YAML or JSON to Configure Log4j 2
|
||||
=== Use YAML or JSON to Configure Log4j 2
|
||||
|
||||
In addition to its default XML configuration format, Log4j 2 also supports YAML and JSON configuration files.
|
||||
To configure Log4j 2 to use an alternative configuration file format, add the appropriate dependencies to the classpath and name your configuration files to match your chosen file format, as shown in the following example:
|
||||
|
||||
@@ -189,7 +194,8 @@ To configure Log4j 2 to use an alternative configuration file format, add the ap
|
||||
|
||||
|
||||
[[howto.logging.log4j.composite-configuration]]
|
||||
==== Use Composite Configuration to Configure Log4j 2
|
||||
=== Use Composite Configuration to Configure Log4j 2
|
||||
|
||||
Log4j 2 has support for combining multiple configuration files into a single composite configuration.
|
||||
To use this support in Spring Boot, configure configprop:logging.log4j2.config.override[] with the locations of one or more secondary configuration files.
|
||||
The secondary configuration files will be merged with the primary configuration, whether the primary's source is Spring Boot's defaults, a standard location such as `log4j.xml`, or the location configured by the configprop:logging.config[] property.
|
||||
@@ -1,16 +1,18 @@
|
||||
[[howto.messaging]]
|
||||
== Messaging
|
||||
= Messaging
|
||||
|
||||
Spring Boot offers a number of starters to support messaging.
|
||||
This section answers questions that arise from using messaging with Spring Boot.
|
||||
|
||||
|
||||
|
||||
[[howto.messaging.disable-transacted-jms-session]]
|
||||
=== Disable Transacted JMS Session
|
||||
== Disable Transacted JMS Session
|
||||
|
||||
If your JMS broker does not support transacted sessions, you have to disable the support of transactions altogether.
|
||||
If you create your own `JmsListenerContainerFactory`, there is nothing to do, since, by default it cannot be transacted.
|
||||
If you want to use the `DefaultJmsListenerContainerFactoryConfigurer` to reuse Spring Boot's default, you can disable transacted sessions, as follows:
|
||||
|
||||
include::code:MyJmsConfiguration[]
|
||||
include-code::MyJmsConfiguration[]
|
||||
|
||||
The preceding example overrides the default factory, and it should be applied to any other factory that your application defines, if any.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user