diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java index c77b39a926..f329d7bf17 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/otlp/OtlpPropertiesConfigAdapter.java @@ -75,18 +75,17 @@ class OtlpPropertiesConfigAdapter extends StepRegistryPropertiesConfigAdapter resourceAttributes() { - Map result; - if (!CollectionUtils.isEmpty(this.openTelemetryProperties.getResourceAttributes())) { - result = new HashMap<>(this.openTelemetryProperties.getResourceAttributes()); - } - else { - result = new HashMap<>(get(OtlpProperties::getResourceAttributes, OtlpConfig.super::resourceAttributes)); - } - result.computeIfAbsent("service.name", - (ignore) -> this.environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME)); + Map resourceAttributes = this.openTelemetryProperties.getResourceAttributes(); + Map result = new HashMap<>((!CollectionUtils.isEmpty(resourceAttributes)) ? resourceAttributes + : get(OtlpProperties::getResourceAttributes, OtlpConfig.super::resourceAttributes)); + result.computeIfAbsent("service.name", (key) -> getApplicationName()); return Collections.unmodifiableMap(result); } + private String getApplicationName() { + return this.environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME); + } + @Override public Map headers() { return get(OtlpProperties::getHeaders, OtlpConfig.super::headers); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryAutoConfiguration.java index be533a8689..b0874f7791 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryAutoConfiguration.java @@ -16,8 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.opentelemetry; -import java.util.Map.Entry; - import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.propagation.ContextPropagators; @@ -80,9 +78,7 @@ public class OpenTelemetryAutoConfiguration { private static Resource toResource(OpenTelemetryProperties properties) { ResourceBuilder builder = Resource.builder(); - for (Entry entry : properties.getResourceAttributes().entrySet()) { - builder.put(entry.getKey(), entry.getValue()); - } + properties.getResourceAttributes().forEach(builder::put); return builder.build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java index ebbf7e3c56..2e5f1cc58a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/DefaultJmsListenerContainerFactoryConfigurer.java @@ -22,6 +22,7 @@ import jakarta.jms.ConnectionFactory; import jakarta.jms.ExceptionListener; import org.springframework.boot.autoconfigure.jms.JmsProperties.Listener.Session; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.destination.DestinationResolver; @@ -103,37 +104,21 @@ public final class DefaultJmsListenerContainerFactoryConfigurer { Assert.notNull(connectionFactory, "ConnectionFactory must not be null"); factory.setConnectionFactory(connectionFactory); factory.setPubSubDomain(this.jmsProperties.isPubSubDomain()); - JmsProperties.Listener listener = this.jmsProperties.getListener(); - Session session = listener.getSession(); - Boolean sessionTransacted = session.getTransacted(); - if (this.transactionManager != null) { - factory.setTransactionManager(this.transactionManager); - } - else if (sessionTransacted == null) { + JmsProperties.Listener listenerProperties = this.jmsProperties.getListener(); + Session sessionProperties = listenerProperties.getSession(); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(this.transactionManager).to(factory::setTransactionManager); + map.from(this.destinationResolver).to(factory::setDestinationResolver); + map.from(this.messageConverter).to(factory::setMessageConverter); + map.from(this.exceptionListener).to(factory::setExceptionListener); + map.from(sessionProperties.getAcknowledgeMode()::getMode).to(factory::setSessionAcknowledgeMode); + if (this.transactionManager == null && sessionProperties.getTransacted() == null) { factory.setSessionTransacted(true); } - if (sessionTransacted != null) { - factory.setSessionTransacted(sessionTransacted); - } - if (this.destinationResolver != null) { - factory.setDestinationResolver(this.destinationResolver); - } - if (this.messageConverter != null) { - factory.setMessageConverter(this.messageConverter); - } - if (this.exceptionListener != null) { - factory.setExceptionListener(this.exceptionListener); - } - factory.setAutoStartup(listener.isAutoStartup()); - factory.setSessionAcknowledgeMode(session.getAcknowledgeMode().getMode()); - String concurrency = listener.formatConcurrency(); - if (concurrency != null) { - factory.setConcurrency(concurrency); - } - Duration receiveTimeout = listener.getReceiveTimeout(); - if (receiveTimeout != null) { - factory.setReceiveTimeout(receiveTimeout.toMillis()); - } + map.from(sessionProperties::getTransacted).to(factory::setSessionTransacted); + map.from(listenerProperties::isAutoStartup).to(factory::setAutoStartup); + map.from(listenerProperties::formatConcurrency).to(factory::setConcurrency); + map.from(listenerProperties::getReceiveTimeout).as(Duration::toMillis).to(factory::setReceiveTimeout); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java index 4add88c74b..389023053e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java @@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; +import org.springframework.boot.autoconfigure.jms.JmsProperties.AcknowledgeMode; import org.springframework.boot.autoconfigure.jms.JmsProperties.DeliveryMode; import org.springframework.boot.autoconfigure.jms.JmsProperties.Template; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -88,23 +89,18 @@ public class JmsAutoConfiguration { } private void mapTemplateProperties(Template properties, JmsTemplate template) { - PropertyMapper map = PropertyMapper.get(); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(properties.getSession()::getAcknowledgeMode) - .to((acknowledgeMode) -> template.setSessionAcknowledgeMode(acknowledgeMode.getMode())); + .asInt(AcknowledgeMode::getMode) + .to(template::setSessionAcknowledgeMode); map.from(properties.getSession()::isTransacted).to(template::setSessionTransacted); map.from(properties::getDefaultDestination).whenNonNull().to(template::setDefaultDestinationName); map.from(properties::getDeliveryDelay).whenNonNull().as(Duration::toMillis).to(template::setDeliveryDelay); map.from(properties::determineQosEnabled).to(template::setExplicitQosEnabled); - map.from(properties::getDeliveryMode) - .whenNonNull() - .as(DeliveryMode::getValue) - .to(template::setDeliveryMode); + map.from(properties::getDeliveryMode).as(DeliveryMode::getValue).to(template::setDeliveryMode); map.from(properties::getPriority).whenNonNull().to(template::setPriority); map.from(properties::getTimeToLive).whenNonNull().as(Duration::toMillis).to(template::setTimeToLive); - map.from(properties::getReceiveTimeout) - .whenNonNull() - .as(Duration::toMillis) - .to(template::setReceiveTimeout); + map.from(properties::getReceiveTimeout).as(Duration::toMillis).to(template::setReceiveTimeout); } } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 14d9c035ac..2b0a5dd180 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -739,6 +739,7 @@ Auto-configuration enables the instrumentation of all available `ThreadPoolTaskE Metrics are tagged by the name of the executor, which is derived from the bean name. + [[actuator.metrics.supported.jms]] ==== JMS Metrics Auto-configuration enables the instrumentation of all available `JmsTemplate` beans. diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc index f2ced63368..0294fab362 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/messaging/pulsar.adoc @@ -52,6 +52,8 @@ For example, if you want to configure the issuer url for the `AuthenticationOAut If you use other forms, such as `issuerurl` or `issuer-url`, the setting will not be applied to the plugin. ==== + + [[messaging.pulsar.connecting.ssl]] ==== SSL By default, Pulsar clients communicate with Pulsar services in plain text. diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/otlp/OpenTelemetryMetricsConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/otlp/OpenTelemetryMetricsConnectionDetailsFactoryIntegrationTests.java index d2c85b3014..c1a88d38df 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/otlp/OpenTelemetryMetricsConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/otlp/OpenTelemetryMetricsConnectionDetailsFactoryIntegrationTests.java @@ -79,7 +79,6 @@ class OpenTelemetryMetricsConnectionDetailsFactoryIntegrationTests { Gauge.builder("test.gauge", () -> 12).register(this.meterRegistry); Timer.builder("test.timer").register(this.meterRegistry).record(Duration.ofMillis(123)); DistributionSummary.builder("test.distributionsummary").register(this.meterRegistry).record(24); - Awaitility.await() .atMost(Duration.ofSeconds(5)) .pollDelay(Duration.ofMillis(100)) @@ -88,19 +87,14 @@ class OpenTelemetryMetricsConnectionDetailsFactoryIntegrationTests { .statusCode(200) .contentType(OPENMETRICS_001) .body(endsWith("# EOF\n"))); - whenPrometheusScraped().then() .body(containsString( "{job=\"test\",service_name=\"test\",telemetry_sdk_language=\"java\",telemetry_sdk_name=\"io.micrometer\""), - matchesPattern("(?s)^.*test_counter\\{.+} 42\\.0\\n.*$"), matchesPattern("(?s)^.*test_gauge\\{.+} 12\\.0\\n.*$"), - matchesPattern("(?s)^.*test_timer_count\\{.+} 1\\n.*$"), - matchesPattern("(?s)^.*test_timer_sum\\{.+} 123\\.0\\n.*$"), matchesPattern("(?s)^.*test_timer_bucket\\{.+,le=\"\\+Inf\"} 1\\n.*$"), - matchesPattern("(?s)^.*test_distributionsummary_count\\{.+} 1\\n.*$"), matchesPattern("(?s)^.*test_distributionsummary_sum\\{.+} 24\\.0\\n.*$"), matchesPattern("(?s)^.*test_distributionsummary_bucket\\{.+,le=\"\\+Inf\"} 1\\n.*$")); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java index 7ae4d8419a..476f0a8917 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/BuildRequest.java @@ -349,6 +349,7 @@ public class BuildRequest { * Return a new {@link BuildRequest} with an updated build workspace. * @param buildWorkspace the build workspace * @return an updated build request + * @since 3.2.0 */ public BuildRequest withBuildWorkspace(Cache buildWorkspace) { Assert.notNull(buildWorkspace, "BuildWorkspace must not be null"); @@ -426,6 +427,7 @@ public class BuildRequest { * Return a new {@link BuildRequest} with an updated security options. * @param securityOptions the security options * @return an updated build request + * @since 3.2.0 */ public BuildRequest withSecurityOptions(List securityOptions) { Assert.notNull(securityOptions, "SecurityOption must not be null"); @@ -552,6 +554,11 @@ public class BuildRequest { return this.tags; } + /** + * Return the build workspace that should be used by the lifecycle. + * @return the build workspace or {@code null} + * @since 3.2.0 + */ public Cache getBuildWorkspace() { return this.buildWorkspace; } @@ -590,7 +597,8 @@ public class BuildRequest { /** * Return the security options that should be used by the lifecycle. - * @return the security options + * @return the security options or {@code null} + * @since 3.2.0 */ public List getSecurityOptions() { return this.securityOptions; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java index 143f54d62b..2ba12dae88 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.java @@ -228,6 +228,7 @@ public abstract class BootBuildImage extends DefaultTask { /** * Returns the build temporary workspace that will be used when building the image. * @return the cache + * @since 3.2.0 */ @Nested @Optional @@ -239,6 +240,7 @@ public abstract class BootBuildImage extends DefaultTask { * Customizes the {@link CacheSpec} for the build temporary workspace using the given * {@code action}. * @param action the action + * @since 3.2.0 */ public void buildWorkspace(Action action) { action.execute(this.buildWorkspace);