diff --git a/api-catalog-services/build.gradle b/api-catalog-services/build.gradle index 07a1781f1a..c7dcb732dd 100644 --- a/api-catalog-services/build.gradle +++ b/api-catalog-services/build.gradle @@ -65,7 +65,7 @@ dependencies { api project(':apiml-tomcat-common') api project(':security-service-client-spring') - implementation libs.spring.boot.starter.aop + implementation libs.spring.boot.starter.aspectj implementation libs.spring.boot.starter.actuator implementation libs.spring.boot.starter.security implementation libs.spring.boot.starter.web diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/ApiCatalogApplication.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/ApiCatalogApplication.java index c67022bb94..03ef8f628c 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/ApiCatalogApplication.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/ApiCatalogApplication.java @@ -11,8 +11,6 @@ package org.zowe.apiml.apicatalog; import org.springframework.boot.SpringApplication; -import org.springframework.boot.actuate.autoconfigure.logging.OpenTelemetryLoggingAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.ComponentScan; @@ -27,8 +25,6 @@ @SpringBootApplication( exclude = { - OpenTelemetryAutoConfiguration.class, - OpenTelemetryLoggingAutoConfiguration.class } ) @EnableDiscoveryClient diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/handlers/CustomErrorStatusHandlingBean.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/handlers/CustomErrorStatusHandlingBean.java index e88d02cdda..e130aba6c4 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/handlers/CustomErrorStatusHandlingBean.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/handlers/CustomErrorStatusHandlingBean.java @@ -11,9 +11,9 @@ package org.zowe.apiml.apicatalog.controllers.handlers; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.web.server.ErrorPage; +import org.springframework.boot.web.error.ErrorPage; import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; diff --git a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicator.java b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicator.java index 78d799306b..43786b0ba0 100644 --- a/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicator.java +++ b/api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicator.java @@ -11,9 +11,9 @@ package org.zowe.apiml.apicatalog.health; import lombok.RequiredArgsConstructor; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Component; diff --git a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicatorTest.java b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicatorTest.java index 9a912316ba..e79cb29561 100644 --- a/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicatorTest.java +++ b/api-catalog-services/src/test/java/org/zowe/apiml/apicatalog/health/ApiCatalogHealthIndicatorTest.java @@ -12,8 +12,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.zowe.apiml.product.constants.CoreService; diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/ApimlDiscoveryCompositeHealthContributor.java b/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/ApimlDiscoveryCompositeHealthContributor.java deleted file mode 100644 index f1d17047e6..0000000000 --- a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/ApimlDiscoveryCompositeHealthContributor.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This program and the accompanying materials are made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Copyright Contributors to the Zowe Project. - */ - -package org.zowe.apiml.product.compatibility; - -import org.springframework.boot.actuate.health.CompositeHealthContributor; -import org.springframework.boot.actuate.health.HealthContributor; -import org.springframework.boot.actuate.health.HealthIndicator; -import org.springframework.boot.actuate.health.NamedContributor; -import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * This class is a replacement for DiscoveryCompositeHealthContributor in spring-cloud-cloud-commons:2.2.9.RELEASE in order - * to work with ApimlHealthCheckHandler more effectively. - *

- * This code is copied from the 3.1.x version of spring-cloud-commons. - * https://github.com/spring-cloud/spring-cloud-commons/blob/3.1.x/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryCompositeHealthContributor.java - *

- * NOTE: This should be removed when the APIML upgrades to Spring Cloud 3.x. - */ -@Component -public class ApimlDiscoveryCompositeHealthContributor implements CompositeHealthContributor { - private final Map indicators; - - public ApimlDiscoveryCompositeHealthContributor(Collection indicators) { - Assert.notNull(indicators, "'indicators' must not be null"); - this.indicators = indicators.stream() - .collect(Collectors.toMap(DiscoveryHealthIndicator::getName, Function.identity())); - } - - @Override - public HealthContributor getContributor(String name) { - return asHealthIndicator(this.indicators.get(name)); - } - - @Override - public Iterator> iterator() { - return this.indicators.values().stream().map(this::asNamedContributor).iterator(); - } - - private NamedContributor asNamedContributor(DiscoveryHealthIndicator indicator) { - return new NamedContributor() { - - @Override - public String getName() { - return indicator.getName(); - } - - @Override - public HealthIndicator getContributor() { - return asHealthIndicator(indicator); - } - - }; - } - - private HealthIndicator asHealthIndicator(DiscoveryHealthIndicator indicator) { - return (indicator != null) ? indicator::health : null; - } - - public Map getIndicators() { - return Collections.unmodifiableMap(indicators); - } -} diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/ApimlHealthCheckHandler.java b/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/ApimlHealthCheckHandler.java deleted file mode 100644 index fad6541859..0000000000 --- a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/ApimlHealthCheckHandler.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This program and the accompanying materials are made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Copyright Contributors to the Zowe Project. - */ - -package org.zowe.apiml.product.compatibility; - -import com.netflix.appinfo.HealthCheckHandler; -import com.netflix.appinfo.InstanceInfo; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.actuate.health.*; -import org.springframework.cloud.netflix.eureka.EurekaHealthIndicator; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.Lifecycle; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * This class is a replacement for EurekaHealthCheckHandler in spring-cloud-netflix-eureka-client:2.2.10.RELEASE, which is incompatible with Spring Boot 2.5. - * EurekaHealthCheckHandler in 2.2.10.RELEASE relies on a few classes that are removed in Spring Boot 2.5. - *

- * This code is almost entirely copied from the 3.1.x version of spring-cloud-netflix-eureka-client. - * https://github.com/spring-cloud/spring-cloud-netflix/blob/3.1.x/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaHealthCheckHandler.java - *

- * There are minor formatting changes (e.g. making a variable final), the only other change is using ApimlDiscoveryCompositeHealthContributor - * to bridge the difference between spring-cloud-commons:2.2.9.RELEASE and spring-cloud-commons:3.1.x. - *

- * NOTE: This should be removed when the APIML upgrades to Spring Cloud 3.x. - */ -@Component -public class ApimlHealthCheckHandler implements HealthCheckHandler, ApplicationContextAware, InitializingBean, Ordered, Lifecycle { - private static final Map STATUS_MAPPING = new HashMap<>(); - - static { - STATUS_MAPPING.put(Status.UNKNOWN, InstanceInfo.InstanceStatus.UNKNOWN); - STATUS_MAPPING.put(Status.OUT_OF_SERVICE, InstanceInfo.InstanceStatus.OUT_OF_SERVICE); - STATUS_MAPPING.put(Status.DOWN, InstanceInfo.InstanceStatus.DOWN); - STATUS_MAPPING.put(Status.UP, InstanceInfo.InstanceStatus.UP); - } - - private final StatusAggregator statusAggregator; - private final Map healthContributors = new HashMap<>(); - private final Map reactiveHealthContributors = new HashMap<>(); - - /** - * {@code true} until the context is stopped. - */ - private boolean running = true; - private ApplicationContext applicationContext; - - public ApimlHealthCheckHandler(StatusAggregator statusAggregator) { - this.statusAggregator = statusAggregator; - Assert.notNull(statusAggregator, "StatusAggregator must not be null"); - - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @Override - public void afterPropertiesSet() { - populateHealthContributors(applicationContext.getBeansOfType(HealthContributor.class)); - reactiveHealthContributors.putAll(applicationContext.getBeansOfType(ReactiveHealthContributor.class)); - } - - void populateHealthContributors(Map healthContributors) { - for (Map.Entry entry : healthContributors.entrySet()) { - // ignore EurekaHealthIndicator and flatten the rest of the composite - // otherwise there is a never ending cycle of down. See gh-643 - if (entry.getValue() instanceof ApimlDiscoveryCompositeHealthContributor) { - ApimlDiscoveryCompositeHealthContributor indicator = (ApimlDiscoveryCompositeHealthContributor) entry.getValue(); - indicator.getIndicators().forEach((name, discoveryHealthIndicator) -> { - if (!(discoveryHealthIndicator instanceof EurekaHealthIndicator)) { - this.healthContributors.put(name, (HealthIndicator) discoveryHealthIndicator::health); - } - }); - } else { - this.healthContributors.put(entry.getKey(), entry.getValue()); - } - } - } - - @Override - public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus instanceStatus) { - if (running) { - return getHealthStatus(); - } else { - // Return nothing if the context is not running, so the status held by the - // InstanceInfo remains unchanged. - // See gh-1571 - return null; - } - } - - protected InstanceInfo.InstanceStatus getHealthStatus() { - Status status = getStatus(statusAggregator); - return mapToInstanceStatus(status); - } - - protected Status getStatus(StatusAggregator statusAggregator) { - Set statusSet = new HashSet<>(); - for (HealthContributor contributor : healthContributors.values()) { - processContributor(statusSet, contributor); - } - for (ReactiveHealthContributor contributor : reactiveHealthContributors.values()) { - processContributor(statusSet, contributor); - } - return statusAggregator.getAggregateStatus(statusSet); - } - - private void processContributor(Set statusSet, HealthContributor contributor) { - if (contributor instanceof CompositeHealthContributor) { - for (NamedContributor contrib : (CompositeHealthContributor) contributor) { - processContributor(statusSet, contrib.getContributor()); - } - } else if (contributor instanceof HealthIndicator) { - statusSet.add(((HealthIndicator) contributor).health().getStatus()); - } - } - - private void processContributor(Set statusSet, ReactiveHealthContributor contributor) { - if (contributor instanceof CompositeReactiveHealthContributor) { - for (NamedContributor contrib : (CompositeReactiveHealthContributor) contributor) { - processContributor(statusSet, contrib.getContributor()); - } - } else if (contributor instanceof ReactiveHealthIndicator) { - Health health = ((ReactiveHealthIndicator) contributor).health().block(); - if (health != null) { - statusSet.add(health.getStatus()); - } - } - } - - protected InstanceInfo.InstanceStatus mapToInstanceStatus(Status status) { - if (!STATUS_MAPPING.containsKey(status)) { - return InstanceInfo.InstanceStatus.UNKNOWN; - } - return STATUS_MAPPING.get(status); - } - - @Override - public int getOrder() { - // registered with a high order priority so the close() method is invoked early - // and *BEFORE* EurekaAutoServiceRegistration - // (must be in effect when the registration is closed and the eureka replication - // triggered -> health check handler is - // consulted at that moment) - return Ordered.HIGHEST_PRECEDENCE; - } - - @Override - public void start() { - running = true; - } - - @Override - public void stop() { - running = false; - } - - @Override - public boolean isRunning() { - return true; - } -} diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicator.java b/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicator.java index 1a1d5bd2b5..8892b83b43 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicator.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicator.java @@ -10,8 +10,8 @@ package org.zowe.apiml.product.compatibility; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.application.DiskSpaceHealthIndicator; import org.springframework.util.unit.DataSize; import java.io.File; diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/DiskHealthConfiguration.java b/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/DiskHealthConfiguration.java index dd13feb663..e4d176a5cb 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/DiskHealthConfiguration.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/compatibility/DiskHealthConfiguration.java @@ -10,9 +10,9 @@ package org.zowe.apiml.product.compatibility; -import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties; -import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; +import org.springframework.boot.health.autoconfigure.application.DiskSpaceHealthContributorAutoConfiguration; +import org.springframework.boot.health.autoconfigure.application.DiskSpaceHealthIndicatorProperties; +import org.springframework.boot.health.application.DiskSpaceHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/config/ServerAddressPropertiesUpdater.java b/apiml-common/src/main/java/org/zowe/apiml/product/config/ServerAddressPropertiesUpdater.java index 9dcf7f0380..5edc0d11f3 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/config/ServerAddressPropertiesUpdater.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/config/ServerAddressPropertiesUpdater.java @@ -19,9 +19,9 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.reactive.TomcatReactiveWebServerFactory; +import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory; import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; @@ -226,7 +226,7 @@ public AdditionalConnectorReactive(List connectorCust @Override protected void initFactory(TomcatReactiveWebServerFactory factory) { - factory.addAdditionalTomcatConnectors(connector); + factory.addAdditionalConnectors(connector); factory.addConnectorCustomizers(connectorCustomizers.toArray(new TomcatConnectorCustomizer[0])); } @@ -243,7 +243,7 @@ public AdditionalConnectorServlet(List connectorCusto @Override protected void initFactory(TomcatServletWebServerFactory factory) { - factory.addAdditionalTomcatConnectors(connector); + factory.addAdditionalConnectors(connector); factory.addConnectorCustomizers(connectorCustomizers.toArray(new TomcatConnectorCustomizer[0])); } diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlNonZosOpenTelemetryResourceProvider.java b/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlNonZosOpenTelemetryResourceProvider.java index a67632d802..03b8c09697 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlNonZosOpenTelemetryResourceProvider.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlNonZosOpenTelemetryResourceProvider.java @@ -15,7 +15,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.stereotype.Component; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @ConditionalOnMissingBean(ApimlZosOpenTelemetryResourceProvider.class) @Component diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlOpenTelemetryResourceProvider.java b/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlOpenTelemetryResourceProvider.java index f8d987e513..a659278f5e 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlOpenTelemetryResourceProvider.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlOpenTelemetryResourceProvider.java @@ -18,7 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @Slf4j public abstract class ApimlOpenTelemetryResourceProvider implements ResourceProvider { diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlZosOpenTelemetryResourceProvider.java b/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlZosOpenTelemetryResourceProvider.java index 5fdc67ec07..1ebb591eec 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlZosOpenTelemetryResourceProvider.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/opentelemetry/ApimlZosOpenTelemetryResourceProvider.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Component; import org.zowe.apiml.product.zos.ZosSystemInformation; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import java.util.Optional; diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/security/WebServerSecurityConfig.java b/apiml-common/src/main/java/org/zowe/apiml/product/security/WebServerSecurityConfig.java index a31a19a7f1..58ecc350aa 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/security/WebServerSecurityConfig.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/security/WebServerSecurityConfig.java @@ -13,7 +13,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.coyote.http11.AbstractHttp11Protocol; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/apiml-common/src/main/java/org/zowe/apiml/product/web/HttpConfig.java b/apiml-common/src/main/java/org/zowe/apiml/product/web/HttpConfig.java index 6de3507887..09daaea945 100644 --- a/apiml-common/src/main/java/org/zowe/apiml/product/web/HttpConfig.java +++ b/apiml-common/src/main/java/org/zowe/apiml/product/web/HttpConfig.java @@ -23,7 +23,7 @@ import org.apache.hc.core5.util.Timeout; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -246,12 +246,16 @@ public HttpsFactory httpsFactory() { * * @return RestTemplate, which uses certificate from keystore to authenticate */ + /** + * Note: Connection timeouts are configured at the HttpClient/ConnectionManager level + * (see HttpsFactory.buildHttpClient() for RequestConfig.setConnectionRequestTimeout and + * getConnectionManager() for ConnectionConfig.setConnectTimeout/setSocketTimeout), + * not on HttpComponentsClientHttpRequestFactory. This is the correct HC5 approach. + */ @Bean @Primary RestTemplate restTemplateWithKeystore() { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(secureHttpClient); - factory.setConnectionRequestTimeout(requestConnectionTimeout); - factory.setConnectTimeout(requestConnectionTimeout); return new RestTemplate(factory); } @@ -265,8 +269,6 @@ RestTemplate restTemplateWithKeystore() { @Bean RestTemplate restTemplateWithoutKeystore() { HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(secureHttpClientWithoutKeystore); - factory.setConnectionRequestTimeout(requestConnectionTimeout); - factory.setConnectTimeout(requestConnectionTimeout); return new RestTemplate(factory); } diff --git a/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicatorTest.java b/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicatorTest.java index 9574d7ab57..e386e8a9a3 100644 --- a/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicatorTest.java +++ b/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/CustomDiskSpaceHealthIndicatorTest.java @@ -13,8 +13,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.util.unit.DataSize; import java.io.File; diff --git a/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/DiskHealthConfigurationTest.java b/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/DiskHealthConfigurationTest.java index 02ffc3aa35..6a5cbc1fff 100644 --- a/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/DiskHealthConfigurationTest.java +++ b/apiml-common/src/test/java/org/zowe/apiml/product/compatibility/DiskHealthConfigurationTest.java @@ -12,8 +12,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties; -import org.springframework.boot.actuate.system.DiskSpaceHealthIndicator; +import org.springframework.boot.health.autoconfigure.application.DiskSpaceHealthIndicatorProperties; +import org.springframework.boot.health.application.DiskSpaceHealthIndicator; import org.springframework.util.unit.DataSize; import java.io.File; diff --git a/apiml-common/src/test/java/org/zowe/apiml/product/web/HttpConfigTest.java b/apiml-common/src/test/java/org/zowe/apiml/product/web/HttpConfigTest.java index b413e6412b..b353086289 100644 --- a/apiml-common/src/test/java/org/zowe/apiml/product/web/HttpConfigTest.java +++ b/apiml-common/src/test/java/org/zowe/apiml/product/web/HttpConfigTest.java @@ -17,7 +17,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.boot.web.server.Ssl; import org.springframework.context.ApplicationContext; import org.springframework.test.util.ReflectionTestUtils; diff --git a/apiml-security-common/build.gradle b/apiml-security-common/build.gradle index 882fb7b61d..d1717a9dc2 100644 --- a/apiml-security-common/build.gradle +++ b/apiml-security-common/build.gradle @@ -15,6 +15,7 @@ dependencies { implementation libs.apache.commons.lang3 implementation libs.http.client5 + implementation libs.jackson.databind implementation libs.nimbus.jose.jwt // Parsing @@ -27,7 +28,6 @@ dependencies { testCompileOnly libs.lombok testImplementation libs.netty.reactor.http - testImplementation libs.reactor.test testAnnotationProcessor libs.lombok testFixturesImplementation libs.nimbus.jose.jwt diff --git a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/config/WebClientConfig.java b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/config/WebClientConfig.java index cf818e8280..384116adb1 100644 --- a/apiml-security-common/src/main/java/org/zowe/apiml/security/common/config/WebClientConfig.java +++ b/apiml-security-common/src/main/java/org/zowe/apiml/security/common/config/WebClientConfig.java @@ -15,7 +15,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.cloud.gateway.config.HttpClientCustomizer; import org.springframework.cloud.gateway.config.HttpClientFactory; import org.springframework.cloud.gateway.config.HttpClientProperties; diff --git a/apiml-tomcat-common/build.gradle b/apiml-tomcat-common/build.gradle index 644865b562..60de3b0e03 100644 --- a/apiml-tomcat-common/build.gradle +++ b/apiml-tomcat-common/build.gradle @@ -5,6 +5,9 @@ dependencies { api libs.zowe.zos.utils implementation libs.netty.reactor.http implementation libs.apache.commons.lang3 + implementation libs.jackson.annotations + implementation libs.jackson.core + implementation libs.jackson.databind testImplementation libs.spring.boot.starter.test diff --git a/apiml-tomcat-common/src/main/java/org/zowe/apiml/gzip/GZipResponseUtils.java b/apiml-tomcat-common/src/main/java/org/zowe/apiml/gzip/GZipResponseUtils.java index 8645784cb9..2251aee0c1 100644 --- a/apiml-tomcat-common/src/main/java/org/zowe/apiml/gzip/GZipResponseUtils.java +++ b/apiml-tomcat-common/src/main/java/org/zowe/apiml/gzip/GZipResponseUtils.java @@ -46,9 +46,9 @@ public static boolean shouldGzippedBodyBeZero(byte[] compressedBytes) { /** * Performs a number of checks to ensure response saneness according to the rules of RFC2616: *

    - *
  1. If the response code is {@link javax.servlet.http.HttpServletResponse#SC_NO_CONTENT} then it is forbidden for the body + *
  2. If the response code is {@link jakarta.servlet.http.HttpServletResponse#SC_NO_CONTENT} then it is forbidden for the body * to contain anything. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5 - *
  3. If the response code is {@link javax.servlet.http.HttpServletResponse#SC_NOT_MODIFIED} then it is forbidden for the body + *
  4. If the response code is {@link jakarta.servlet.http.HttpServletResponse#SC_NOT_MODIFIED} then it is forbidden for the body * to contain anything. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 *
* @@ -68,7 +68,7 @@ public static boolean shouldBodyBeZero(int responseStatus) { * * @param response the response which will have a header added to it. I.e this method changes its parameter * @throws RuntimeException Either the response is committed or we were called using the include method - * from a {@link javax.servlet.RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} + * from a {@link jakarta.servlet.RequestDispatcher#include(jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse)} * method and the set header is ignored. */ public static void addGzipHeader(final HttpServletResponse response) throws GZipResponseException { diff --git a/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/ApimlTomcatCustomizer.java b/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/ApimlTomcatCustomizer.java index 13f32517ae..6cb67f16f2 100644 --- a/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/ApimlTomcatCustomizer.java +++ b/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/ApimlTomcatCustomizer.java @@ -18,7 +18,7 @@ import org.apache.tomcat.util.net.*; import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; import org.springframework.stereotype.Component; import org.zowe.apiml.exception.AttlsHandlerException; import org.zowe.commons.attls.ContextIsNotInitializedException; diff --git a/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatAcceptFixConfig.java b/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatAcceptFixConfig.java index 3bd7a1c8c8..ee1df1f156 100644 --- a/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatAcceptFixConfig.java +++ b/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatAcceptFixConfig.java @@ -19,7 +19,7 @@ import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.NioEndpoint; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatDefaultCertificate.java b/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatDefaultCertificate.java index aa0798583b..225031f28d 100644 --- a/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatDefaultCertificate.java +++ b/apiml-tomcat-common/src/main/java/org/zowe/apiml/product/web/TomcatDefaultCertificate.java @@ -13,7 +13,7 @@ import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.net.SSLHostConfig; import org.apache.tomcat.util.net.SSLHostConfigCertificate; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; import org.springframework.stereotype.Component; import java.lang.reflect.Field; diff --git a/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatAcceptFixConfigTest.java b/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatAcceptFixConfigTest.java index ab44dbad99..88dacdfb38 100644 --- a/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatAcceptFixConfigTest.java +++ b/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatAcceptFixConfigTest.java @@ -23,7 +23,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; import java.io.IOException; import java.lang.reflect.Field; diff --git a/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatKeyringFixTest.java b/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatKeyringFixTest.java index c799f5ca9f..79bb4ed4a3 100644 --- a/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatKeyringFixTest.java +++ b/apiml-tomcat-common/src/test/java/org/zowe/apiml/product/web/TomcatKeyringFixTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory; import org.springframework.boot.web.server.Ssl; import org.springframework.test.util.ReflectionTestUtils; diff --git a/apiml/build.gradle b/apiml/build.gradle index 6982e5566e..59ac592c89 100644 --- a/apiml/build.gradle +++ b/apiml/build.gradle @@ -61,6 +61,23 @@ dependencies { api project(":caching-service") api project(":api-catalog-services") + // Force Jersey/HK2 versions compatible with Java 17 + configurations.all { + resolutionStrategy { + force 'org.glassfish.jersey.core:jersey-common:3.1.9' + force 'org.glassfish.jersey.core:jersey-client:3.1.9' + force 'org.glassfish.jersey.core:jersey-server:3.1.9' + force 'org.glassfish.jersey.inject:jersey-hk2:3.1.9' + force 'org.glassfish.jersey.media:jersey-media-jaxb:3.1.9' + force 'org.glassfish.jersey.containers:jersey-container-servlet:3.1.9' + force 'org.glassfish.hk2:hk2-locator:3.1.1' + force 'org.glassfish.hk2:hk2-api:3.1.1' + force 'org.glassfish.hk2:hk2-utils:3.1.1' + force 'org.glassfish.hk2:spring-bridge:3.1.1' + force 'org.glassfish.hk2.external:aopalliance-repackaged:3.1.1' + } + } + implementation libs.bundles.modulith implementation libs.spring.boot.starter.web implementation libs.swagger2.parser diff --git a/apiml/src/main/java/org/zowe/apiml/ApimlApplication.java b/apiml/src/main/java/org/zowe/apiml/ApimlApplication.java index 095f4b2b3d..87c4f7ab8d 100644 --- a/apiml/src/main/java/org/zowe/apiml/ApimlApplication.java +++ b/apiml/src/main/java/org/zowe/apiml/ApimlApplication.java @@ -11,11 +11,7 @@ package org.zowe.apiml; import org.springframework.boot.SpringApplication; -import org.springframework.boot.actuate.autoconfigure.logging.OpenTelemetryLoggingAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration; import org.springframework.cloud.netflix.eureka.server.EurekaController; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; @@ -24,13 +20,7 @@ import org.zowe.apiml.enable.register.RegisterToApiLayer; import org.zowe.apiml.gateway.config.GatewayHealthIndicator; -@SpringBootApplication(exclude = { - ReactiveOAuth2ClientAutoConfiguration.class, - OpenTelemetryAutoConfiguration.class, - OpenTelemetryLoggingAutoConfiguration.class, - io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration.class, - CacheMetricsAutoConfiguration.class -}) +@SpringBootApplication @ComponentScan( excludeFilters = { @ComponentScan.Filter( diff --git a/apiml/src/main/java/org/zowe/apiml/EurekaConfiguration.java b/apiml/src/main/java/org/zowe/apiml/EurekaConfiguration.java index 1b0b65bf43..8a97fed58e 100644 --- a/apiml/src/main/java/org/zowe/apiml/EurekaConfiguration.java +++ b/apiml/src/main/java/org/zowe/apiml/EurekaConfiguration.java @@ -51,8 +51,8 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Application; import jakarta.ws.rs.ext.Provider; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.spi.Container; @@ -67,7 +67,7 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; @@ -104,7 +104,7 @@ @PropertySource("classpath:/eureka/server.properties") public class EurekaConfiguration implements WebMvcConfigurer { - private static final Log log = LogFactory.getLog(EurekaConfiguration.class); + private static final Logger log = LoggerFactory.getLogger(EurekaConfiguration.class); /** * List of packages containing Jersey resources required by the Eureka server. diff --git a/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java b/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java index bfa806dbf8..2e83f6e0f3 100644 --- a/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java +++ b/apiml/src/main/java/org/zowe/apiml/EurekaHealthIndicatorApiml.java @@ -10,8 +10,8 @@ package org.zowe.apiml; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.netflix.eureka.EurekaHealthIndicator; import org.springframework.context.annotation.Primary; diff --git a/apiml/src/main/java/org/zowe/apiml/EurekaRestController.java b/apiml/src/main/java/org/zowe/apiml/EurekaRestController.java index dc8ffd2e5c..65b3ab4b0e 100644 --- a/apiml/src/main/java/org/zowe/apiml/EurekaRestController.java +++ b/apiml/src/main/java/org/zowe/apiml/EurekaRestController.java @@ -391,6 +391,11 @@ public List getMatchedResources() { return List.of(); } + @Override + public String getMatchedResourceTemplate() { + return null; + } + @Override public URI resolve(URI uri) { return uri; diff --git a/apiml/src/main/java/org/zowe/apiml/GatewayHealthIndicator.java b/apiml/src/main/java/org/zowe/apiml/GatewayHealthIndicator.java index f4d37f5425..8e48a36551 100644 --- a/apiml/src/main/java/org/zowe/apiml/GatewayHealthIndicator.java +++ b/apiml/src/main/java/org/zowe/apiml/GatewayHealthIndicator.java @@ -15,9 +15,9 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health.Builder; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health.Builder; +import org.springframework.boot.health.contributor.Status; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; import org.springframework.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent; @@ -26,7 +26,6 @@ import org.springframework.stereotype.Component; import org.zowe.apiml.apicatalog.ApiCatalogServiceAvailableEvent; import org.zowe.apiml.message.log.ApimlLogger; -import org.zowe.apiml.product.compatibility.ApimlHealthCheckHandler; import org.zowe.apiml.product.constants.CoreService; import org.zowe.apiml.product.logging.annotations.InjectApimlLogger; import org.zowe.apiml.product.service.ServiceStartupEventHandler; @@ -34,12 +33,12 @@ import java.util.concurrent.atomic.AtomicBoolean; -import static org.springframework.boot.actuate.health.Status.DOWN; -import static org.springframework.boot.actuate.health.Status.UP; +import static org.springframework.boot.health.contributor.Status.DOWN; +import static org.springframework.boot.health.contributor.Status.UP; /** * This class contributes the apiml component health indication to the main /application/health - * controlled by class {@link ApimlHealthCheckHandler} in the common package. + * controlled by class {@link org.springframework.cloud.netflix.eureka.EurekaHealthCheckHandler}. * * Note: Name is kept as GatewayHealthIndicator for backwards compatibility */ diff --git a/apiml/src/main/java/org/zowe/apiml/ModulithConfig.java b/apiml/src/main/java/org/zowe/apiml/ModulithConfig.java index 6fcafcba26..b099878571 100644 --- a/apiml/src/main/java/org/zowe/apiml/ModulithConfig.java +++ b/apiml/src/main/java/org/zowe/apiml/ModulithConfig.java @@ -35,10 +35,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatContextCustomizer; +import org.springframework.boot.tomcat.TomcatProtocolHandlerCustomizer; +import org.springframework.boot.tomcat.reactive.TomcatReactiveWebServerFactory; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; @@ -373,9 +373,9 @@ protected void configureContext(Context context) { super.configureContext(context); } }; - factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().toList()); - factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().toList()); - factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().toList()); + factory.addConnectorCustomizers(connectorCustomizers.orderedStream().toArray(TomcatConnectorCustomizer[]::new)); + factory.addContextCustomizers(contextCustomizers.orderedStream().toArray(TomcatContextCustomizer[]::new)); + factory.addProtocolHandlerCustomizers(protocolHandlerCustomizers.orderedStream().toArray(TomcatProtocolHandlerCustomizer[]::new)); return factory; } diff --git a/apiml/src/main/java/org/zowe/apiml/RouteRefreshListener.java b/apiml/src/main/java/org/zowe/apiml/RouteRefreshListener.java index c01ed5a6aa..4ac356123e 100644 --- a/apiml/src/main/java/org/zowe/apiml/RouteRefreshListener.java +++ b/apiml/src/main/java/org/zowe/apiml/RouteRefreshListener.java @@ -27,7 +27,7 @@ package org.zowe.apiml; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.server.context.WebServerApplicationContext; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; diff --git a/apiml/src/test/java/org/zowe/apiml/GatewayHealthIndicatorTest.java b/apiml/src/test/java/org/zowe/apiml/GatewayHealthIndicatorTest.java index 2ccb3bbc16..39f1866310 100644 --- a/apiml/src/test/java/org/zowe/apiml/GatewayHealthIndicatorTest.java +++ b/apiml/src/test/java/org/zowe/apiml/GatewayHealthIndicatorTest.java @@ -19,8 +19,8 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent; diff --git a/apiml/src/test/java/org/zowe/apiml/acceptance/OpenTelemetryTestConfig.java b/apiml/src/test/java/org/zowe/apiml/acceptance/OpenTelemetryTestConfig.java index 9c3765ebe2..67c020a316 100644 --- a/apiml/src/test/java/org/zowe/apiml/acceptance/OpenTelemetryTestConfig.java +++ b/apiml/src/test/java/org/zowe/apiml/acceptance/OpenTelemetryTestConfig.java @@ -29,7 +29,7 @@ import org.zowe.apiml.zaas.security.service.saf.SafIdtProvider; import org.zowe.apiml.zaas.security.service.saf.SafRestAuthenticationService; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; @TestConfiguration @Profile("OpenTelemetryTest") diff --git a/build.gradle b/build.gradle index ac1c23f360..062b5cb0b6 100644 --- a/build.gradle +++ b/build.gradle @@ -102,6 +102,14 @@ allprojects { } configurations.all { + resolutionStrategy { + // REST Assured 5.5.7 is incompatible with Groovy 5.x — force Groovy 4.0.x + // (NullPointerException in Class.isAssignableFrom via ClosureMetaClass) + force 'org.apache.groovy:groovy:4.0.28' + force 'org.apache.groovy:groovy-bom:4.0.28' + force 'org.apache.groovy:groovy-json:4.0.28' + force 'org.apache.groovy:groovy-xml:4.0.28' + } resolutionStrategy.dependencySubstitution { substitute(module('javax.servlet:servlet-api')).using(module('javax.servlet:javax.servlet-api:4.0.1')) @@ -123,8 +131,6 @@ configure(subprojects.findAll { it.name in [ ]}) { configurations.all { - // it has been replaced by spring-jcl - exclude group: "commons-logging", module: "commons-logging" // exclude netty platform specific native libraries from distribution exclude group: "io.netty", module: "netty-codec-native-quic" } diff --git a/caching-service/build.gradle b/caching-service/build.gradle index 087e85d49e..6e3159af49 100644 --- a/caching-service/build.gradle +++ b/caching-service/build.gradle @@ -60,10 +60,11 @@ dependencies { api project(':onboarding-enabler-spring') api project(':apiml-security-common') - implementation libs.spring.boot.starter.aop + implementation libs.spring.boot.starter.aspectj implementation libs.spring.boot.starter.webflux implementation libs.spring.boot.starter.security implementation libs.spring.boot.starter.actuator + implementation libs.spring.boot.starter.cache implementation libs.spring.doc.webflux.ui implementation libs.spring.retry implementation libs.eureka.jersey.client diff --git a/caching-service/src/main/java/org/zowe/apiml/caching/CachingServiceApplication.java b/caching-service/src/main/java/org/zowe/apiml/caching/CachingServiceApplication.java index cfc21bf426..415adfefc3 100644 --- a/caching-service/src/main/java/org/zowe/apiml/caching/CachingServiceApplication.java +++ b/caching-service/src/main/java/org/zowe/apiml/caching/CachingServiceApplication.java @@ -11,8 +11,6 @@ package org.zowe.apiml.caching; import org.springframework.boot.SpringApplication; -import org.springframework.boot.actuate.autoconfigure.logging.OpenTelemetryLoggingAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.retry.annotation.EnableRetry; import org.zowe.apiml.enable.EnableApiDiscovery; @@ -20,8 +18,6 @@ @SpringBootApplication( exclude = { - OpenTelemetryAutoConfiguration.class, - OpenTelemetryLoggingAutoConfiguration.class } ) @EnableApiDiscovery diff --git a/caching-service/src/main/java/org/zowe/apiml/caching/config/GeneralConfig.java b/caching-service/src/main/java/org/zowe/apiml/caching/config/GeneralConfig.java index 729afcf1d0..b8bfcd2135 100644 --- a/caching-service/src/main/java/org/zowe/apiml/caching/config/GeneralConfig.java +++ b/caching-service/src/main/java/org/zowe/apiml/caching/config/GeneralConfig.java @@ -17,7 +17,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.zowe.apiml.filter.AttlsHttpHandler; import org.zowe.apiml.product.config.NonModulithApplicationInfoConfig; @@ -39,11 +38,6 @@ public class GeneralConfig implements WebMvcConfigurer { @Value("${caching.storage.size:100}") private int maxDataSize; - @Override - public void configurePathMatch(PathMatchConfigurer configurer) { - configurer.setUseTrailingSlashMatch(true); - } - @Bean @ConditionalOnMissingBean(name = "modulithConfig") ServiceStartupEventHandler serviceStartupEventHandler() { diff --git a/caching-service/src/main/java/org/zowe/apiml/caching/health/ApimlCachesEndpoint.java b/caching-service/src/main/java/org/zowe/apiml/caching/health/ApimlCachesEndpoint.java index fca8676047..a91cf5065d 100644 --- a/caching-service/src/main/java/org/zowe/apiml/caching/health/ApimlCachesEndpoint.java +++ b/caching-service/src/main/java/org/zowe/apiml/caching/health/ApimlCachesEndpoint.java @@ -11,7 +11,7 @@ package org.zowe.apiml.caching.health; import lombok.experimental.Delegate; -import org.springframework.boot.actuate.cache.CachesEndpoint; +import org.springframework.boot.cache.actuate.endpoint.CachesEndpoint; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cache.CacheManager; diff --git a/caching-service/src/main/java/org/zowe/apiml/caching/health/CachingHealthIndicator.java b/caching-service/src/main/java/org/zowe/apiml/caching/health/CachingHealthIndicator.java index abd59f4630..eb21a48292 100644 --- a/caching-service/src/main/java/org/zowe/apiml/caching/health/CachingHealthIndicator.java +++ b/caching-service/src/main/java/org/zowe/apiml/caching/health/CachingHealthIndicator.java @@ -13,9 +13,9 @@ import com.netflix.discovery.shared.Application; import jakarta.annotation.Nonnull; import lombok.RequiredArgsConstructor; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; diff --git a/caching-service/src/main/java/org/zowe/apiml/caching/health/InfinispanHealthIndicator.java b/caching-service/src/main/java/org/zowe/apiml/caching/health/InfinispanHealthIndicator.java index d8fd889b88..393c207903 100644 --- a/caching-service/src/main/java/org/zowe/apiml/caching/health/InfinispanHealthIndicator.java +++ b/caching-service/src/main/java/org/zowe/apiml/caching/health/InfinispanHealthIndicator.java @@ -14,9 +14,9 @@ import org.infinispan.remoting.transport.Address; import org.infinispan.spring.embedded.provider.SpringEmbeddedCacheManager; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cache.CacheManager; diff --git a/caching-service/src/test/java/org/zowe/apiml/caching/health/CachingHealthIndicatorTest.java b/caching-service/src/test/java/org/zowe/apiml/caching/health/CachingHealthIndicatorTest.java index 918addfea3..313b406549 100644 --- a/caching-service/src/test/java/org/zowe/apiml/caching/health/CachingHealthIndicatorTest.java +++ b/caching-service/src/test/java/org/zowe/apiml/caching/health/CachingHealthIndicatorTest.java @@ -18,8 +18,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.zowe.apiml.eurekaservice.client.ApiMediationClient; import org.zowe.apiml.product.constants.CoreService; diff --git a/caching-service/src/test/java/org/zowe/apiml/caching/health/InfinispanHealthIndicatorTest.java b/caching-service/src/test/java/org/zowe/apiml/caching/health/InfinispanHealthIndicatorTest.java index a19bab5ee2..ac63b3711d 100644 --- a/caching-service/src/test/java/org/zowe/apiml/caching/health/InfinispanHealthIndicatorTest.java +++ b/caching-service/src/test/java/org/zowe/apiml/caching/health/InfinispanHealthIndicatorTest.java @@ -24,8 +24,8 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.cache.CacheManager; import org.springframework.test.util.ReflectionTestUtils; diff --git a/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/SpringComponentsConfiguration.java b/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/SpringComponentsConfiguration.java index 594e0cef75..cfa9c2f6d4 100644 --- a/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/SpringComponentsConfiguration.java +++ b/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/SpringComponentsConfiguration.java @@ -12,8 +12,8 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.zowe.apiml.product.service.ServiceStartupEventHandler; /** @@ -24,8 +24,8 @@ public class SpringComponentsConfiguration { @Bean - Jackson2ObjectMapperBuilderCustomizer failOnUnknownProperties() { - return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder + Jackson2ObjectMapperBuilder failOnUnknownProperties() { + return new Jackson2ObjectMapperBuilder() .featuresToEnable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); } diff --git a/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/TomcatConfiguration.java b/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/TomcatConfiguration.java index 84c8db8d6e..0300414aff 100644 --- a/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/TomcatConfiguration.java +++ b/discoverable-client/src/main/java/org/zowe/apiml/client/configuration/TomcatConfiguration.java @@ -12,9 +12,9 @@ import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.buf.EncodedSolidusHandling; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/discovery-service/build.gradle b/discovery-service/build.gradle index 065c3c2b43..af300aa88a 100644 --- a/discovery-service/build.gradle +++ b/discovery-service/build.gradle @@ -30,6 +30,17 @@ def componentName = "discovery-service" setJib(componentName, javaAgentPort, debugPort, applicationPort) jib.container.args.add('--spring.profiles.active=https') +configurations.all { + resolutionStrategy { + force 'org.glassfish.jersey.core:jersey-common:3.1.9' + force 'org.glassfish.jersey.core:jersey-client:3.1.9' + force 'org.glassfish.jersey.core:jersey-server:3.1.9' + force 'org.glassfish.jersey.inject:jersey-hk2:3.1.9' + force 'org.glassfish.jersey.media:jersey-media-jaxb:3.1.9' + force 'org.glassfish.jersey.containers:jersey-container-servlet:3.1.9' + } +} + springBoot { // This statement tells the Gradle Spring Boot plugin to generate a file @@ -72,6 +83,8 @@ dependencies { testImplementation libs.rest.assured testImplementation libs.netflix.servo + testImplementation libs.apache.commons.logging + compileOnly libs.lombok annotationProcessor libs.lombok diff --git a/discovery-service/gradle/lite.gradle b/discovery-service/gradle/lite.gradle index 5f9f17f21a..b3e06cc316 100644 --- a/discovery-service/gradle/lite.gradle +++ b/discovery-service/gradle/lite.gradle @@ -27,7 +27,7 @@ apply from: "$rootDir/gradle/lite-project.gradle" task liteJar(type: BootJar) { //Do not allow duplicates by ignoring subsequent items to be created at the same path. duplicatesStrategy = DuplicatesStrategy.EXCLUDE - targetJavaVersion = JavaVersion.VERSION_17 + targetJavaVersion = JavaVersion.VERSION_21 manifest { attributes 'Main-Class': 'org.springframework.boot.loader.launch.PropertiesLauncher' } diff --git a/discovery-service/src/main/java/org/zowe/apiml/discovery/ApimlInstanceRegistry.java b/discovery-service/src/main/java/org/zowe/apiml/discovery/ApimlInstanceRegistry.java index f9e07ac3d8..ed3bc0f359 100644 --- a/discovery-service/src/main/java/org/zowe/apiml/discovery/ApimlInstanceRegistry.java +++ b/discovery-service/src/main/java/org/zowe/apiml/discovery/ApimlInstanceRegistry.java @@ -56,7 +56,6 @@ public class ApimlInstanceRegistry extends InstanceRegistry { private final ApplicationContext appCntx; private final EurekaConfig.Tuple tuple; - private final MetadataFilterService metadataFilterService; private ConcurrentHashMap>> registry; diff --git a/discovery-service/src/main/java/org/zowe/apiml/discovery/DiscoveryServiceApplication.java b/discovery-service/src/main/java/org/zowe/apiml/discovery/DiscoveryServiceApplication.java index c4eb61b5b2..d507df5137 100644 --- a/discovery-service/src/main/java/org/zowe/apiml/discovery/DiscoveryServiceApplication.java +++ b/discovery-service/src/main/java/org/zowe/apiml/discovery/DiscoveryServiceApplication.java @@ -13,8 +13,6 @@ import jakarta.annotation.Nonnull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; -import org.springframework.boot.actuate.autoconfigure.logging.OpenTelemetryLoggingAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -31,8 +29,6 @@ @EnableEurekaServer @SpringBootApplication( exclude = { - OpenTelemetryAutoConfiguration.class, - OpenTelemetryLoggingAutoConfiguration.class } ) @ComponentScan({ diff --git a/discovery-service/src/main/java/org/zowe/apiml/discovery/config/DiscoveryErrorController.java b/discovery-service/src/main/java/org/zowe/apiml/discovery/config/DiscoveryErrorController.java index db1dd93639..b42f497624 100644 --- a/discovery-service/src/main/java/org/zowe/apiml/discovery/config/DiscoveryErrorController.java +++ b/discovery-service/src/main/java/org/zowe/apiml/discovery/config/DiscoveryErrorController.java @@ -13,10 +13,10 @@ import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; -import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver; -import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.boot.autoconfigure.web.WebProperties; +import org.springframework.boot.webmvc.autoconfigure.error.BasicErrorController; +import org.springframework.boot.webmvc.autoconfigure.error.ErrorViewResolver; +import org.springframework.boot.webmvc.error.ErrorAttributes; import org.springframework.context.annotation.Primary; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -32,8 +32,8 @@ @ConditionalOnMissingBean(name = "modulithConfig") public class DiscoveryErrorController extends BasicErrorController { - public DiscoveryErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, List errorViewResolvers) { - super(errorAttributes, serverProperties.getError(), errorViewResolvers); + public DiscoveryErrorController(ErrorAttributes errorAttributes, WebProperties webProperties, List errorViewResolvers) { + super(errorAttributes, webProperties.getError(), errorViewResolvers); } @Override diff --git a/discovery-service/src/main/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicator.java b/discovery-service/src/main/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicator.java index c1a4d70ac6..ae4ace98dd 100644 --- a/discovery-service/src/main/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicator.java +++ b/discovery-service/src/main/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicator.java @@ -11,9 +11,9 @@ package org.zowe.apiml.discovery.health; import lombok.RequiredArgsConstructor; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Component; import org.zowe.apiml.product.constants.CoreService; diff --git a/discovery-service/src/main/java/org/zowe/apiml/discovery/metadata/MetadataDefaultsService.java b/discovery-service/src/main/java/org/zowe/apiml/discovery/metadata/MetadataDefaultsService.java index 383611c1e7..f0c75b84a0 100644 --- a/discovery-service/src/main/java/org/zowe/apiml/discovery/metadata/MetadataDefaultsService.java +++ b/discovery-service/src/main/java/org/zowe/apiml/discovery/metadata/MetadataDefaultsService.java @@ -10,8 +10,8 @@ package org.zowe.apiml.discovery.metadata; -import org.springframework.stereotype.Service; import org.zowe.apiml.product.discovery.ServiceOverrideData; +import org.springframework.stereotype.Service; import java.util.Collections; import java.util.Map; diff --git a/discovery-service/src/test/java/org/zowe/apiml/discovery/ApimlInstanceRegistryTest.java b/discovery-service/src/test/java/org/zowe/apiml/discovery/ApimlInstanceRegistryTest.java index 58fbf7e1f6..0e9d64ac67 100644 --- a/discovery-service/src/test/java/org/zowe/apiml/discovery/ApimlInstanceRegistryTest.java +++ b/discovery-service/src/test/java/org/zowe/apiml/discovery/ApimlInstanceRegistryTest.java @@ -57,9 +57,9 @@ class ApimlInstanceRegistryTest { @Mock private EurekaServerHttpClientFactory eurekaServerHttpClientFactory; @Mock private InstanceRegistryProperties instanceRegistryProperties; @Mock private ApplicationContext appCntx; + @Mock private MetadataFilterService metadataFilterService; @Mock private EurekaInstanceConfig eurekaInstanceConfig; @Mock private PeerEurekaNodes peerEurekaNodes; - @Mock private MetadataFilterService metadataFilterService; private InstanceInfo standardInstance; private EurekaServerConfig serverConfig; @@ -78,8 +78,7 @@ void setUp() throws Exception { eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, - new EurekaConfig.Tuple("service*,hello"), - metadataFilterService))); + new EurekaConfig.Tuple("service*,hello"), metadataFilterService))); doReturn("zowe").when(eurekaInstanceConfig).getNamespace(); doReturn("discovery").when(eurekaInstanceConfig).getAppname(); @@ -128,8 +127,7 @@ void thenOnboard(String instanceId, String appName) throws Exception { eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, - new EurekaConfig.Tuple(""), - metadataFilterService))); + new EurekaConfig.Tuple(""), metadataFilterService))); assertDoesNotThrow( () -> apimlInstanceRegistry.register(wrongInstance, 1, false) ); @@ -151,8 +149,7 @@ void thenShouldRegister() throws Exception { eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, - new EurekaConfig.Tuple(null), - metadataFilterService))); + new EurekaConfig.Tuple(null), metadataFilterService))); assertDoesNotThrow(() -> apimlInstanceRegistry.register(standardInstance, false)); } @@ -206,8 +203,7 @@ void thenShouldRegister(String tuple, String expectedServiceIdInResult) throws E eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, - new EurekaConfig.Tuple(tuple), - metadataFilterService))); + new EurekaConfig.Tuple(tuple), metadataFilterService))); apimlInstanceRegistry.register(standardInstance, false); assertEquals(expectedServiceIdInResult, standardInstance.getInstanceId()); } @@ -223,8 +219,7 @@ void thenShouldRegisterWithSecondMethod(String tuple, String expectedServiceIdIn eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, - new EurekaConfig.Tuple(tuple), - metadataFilterService))); + new EurekaConfig.Tuple(tuple), metadataFilterService))); apimlInstanceRegistry.register(standardInstance, 1, false); assertEquals(expectedServiceIdInResult, standardInstance.getInstanceId()); } @@ -344,8 +339,7 @@ class UpdateRenewsPerMinThreshold { void setUp() { registry = new ApimlInstanceRegistry( serverConfig, clientConfig, serverCodecs, eurekaClient, - eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, new EurekaConfig.Tuple(""), - metadataFilterService + eurekaServerHttpClientFactory, instanceRegistryProperties, appCntx, new EurekaConfig.Tuple(""), metadataFilterService ); renewCorrection = (ThreadLocal) ReflectionTestUtils.getField(registry, "RENEW_CORRECTION"); } diff --git a/discovery-service/src/test/java/org/zowe/apiml/discovery/eureka/RefreshablePeerEurekaNodesTest.java b/discovery-service/src/test/java/org/zowe/apiml/discovery/eureka/RefreshablePeerEurekaNodesTest.java index f5dfcb5ddd..098cd68d2c 100644 --- a/discovery-service/src/test/java/org/zowe/apiml/discovery/eureka/RefreshablePeerEurekaNodesTest.java +++ b/discovery-service/src/test/java/org/zowe/apiml/discovery/eureka/RefreshablePeerEurekaNodesTest.java @@ -12,6 +12,7 @@ import com.netflix.appinfo.ApplicationInfoManager; import com.netflix.discovery.EurekaClientConfig; +import com.netflix.discovery.converters.wrappers.CodecWrapper; import com.netflix.eureka.EurekaServerConfig; import com.netflix.eureka.cluster.PeerEurekaNode; import com.netflix.eureka.registry.PeerAwareInstanceRegistry; @@ -31,37 +32,21 @@ import org.zowe.apiml.product.eureka.client.ApimlPeerEurekaNode; import javax.net.ssl.SSLContext; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.Executors; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @TestInstance(Lifecycle.PER_CLASS) @ExtendWith(MockitoExtension.class) class RefreshablePeerEurekaNodesTest { private static final int DEFAULT_MAX_RETRIES = 10; - private static final VarHandle MODIFIERS; - - static { - try { - var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()); - MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class); - } catch (IllegalAccessException | NoSuchFieldException ex) { - throw new RuntimeException(ex); - } - } PeerAwareInstanceRegistry registry; @Mock @@ -91,14 +76,10 @@ void setUp() { } @Test - void givenEurekaNodeUrl_thenCreateNode() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + void givenEurekaNodeUrl_thenCreateNode() { when(serverConfig.getPeerNodeTotalConnections()).thenReturn(100); when(serverConfig.getPeerNodeTotalConnectionsPerHost()).thenReturn(10); - - Field defaultExecutor = StatsMonitor.class.getDeclaredField("DEFAULT_EXECUTOR"); - MODIFIERS.set(defaultExecutor, defaultExecutor.getModifiers() & ~Modifier.FINAL); - defaultExecutor.setAccessible(true); - defaultExecutor.set(null, Executors.newSingleThreadScheduledExecutor()); + when(serverCodecs.getFullJsonCodec()).thenReturn(mock(CodecWrapper.class)); PeerEurekaNode node = eurekaNodes.createPeerEurekaNode("https://localhost:10013/"); assertInstanceOf(ApimlPeerEurekaNode.class, node); diff --git a/discovery-service/src/test/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicatorTest.java b/discovery-service/src/test/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicatorTest.java index 3dbe5768ad..22d23fe86c 100644 --- a/discovery-service/src/test/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicatorTest.java +++ b/discovery-service/src/test/java/org/zowe/apiml/discovery/health/DiscoveryServiceHealthIndicatorTest.java @@ -13,8 +13,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.zowe.apiml.product.constants.CoreService; diff --git a/discovery-service/src/test/java/org/zowe/apiml/discovery/health/ProtectedHealthEndpointTest.java b/discovery-service/src/test/java/org/zowe/apiml/discovery/health/ProtectedHealthEndpointTest.java index f9019d33d8..ffd6e10155 100644 --- a/discovery-service/src/test/java/org/zowe/apiml/discovery/health/ProtectedHealthEndpointTest.java +++ b/discovery-service/src/test/java/org/zowe/apiml/discovery/health/ProtectedHealthEndpointTest.java @@ -15,10 +15,13 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.zowe.apiml.discovery.DiscoveryServiceApplication; import org.zowe.apiml.discovery.config.EurekaConfig; import org.zowe.apiml.discovery.functional.DiscoveryFunctionalTest; +import io.restassured.RestAssured; import static io.restassured.RestAssured.given; import static org.hamcrest.core.Is.is; @@ -30,6 +33,18 @@ classes = {DiscoveryServiceApplication.class, EurekaConfig.class} ) public class ProtectedHealthEndpointTest extends DiscoveryFunctionalTest { + + @Autowired + private Environment environment; + + @Override + protected String getProtocol() { + if (environment != null && java.util.Arrays.asList(environment.getActiveProfiles()).contains("https")) { + return "https"; + } + return "http"; + } + @Nested @ActiveProfiles("http") class GivenProtectedHealthEndpointWithHttp { @@ -48,6 +63,7 @@ void applicationHealthEndpointsWhenProtected() { class GivenProtectedHealthEndpointWithHttps { @Test void applicationHealthEndpointsWhenProtected() { + RestAssured.useRelaxedHTTPSValidation(); given() .when() .get(getDiscoveryUriWithPath("/application/health")) diff --git a/discovery-service/src/test/java/org/zowe/apiml/discovery/staticdef/StaticApiRestControllerTest.java b/discovery-service/src/test/java/org/zowe/apiml/discovery/staticdef/StaticApiRestControllerTest.java index 1f96e18673..08ebeccaba 100644 --- a/discovery-service/src/test/java/org/zowe/apiml/discovery/staticdef/StaticApiRestControllerTest.java +++ b/discovery-service/src/test/java/org/zowe/apiml/discovery/staticdef/StaticApiRestControllerTest.java @@ -13,6 +13,8 @@ import com.netflix.appinfo.InstanceInfo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.web.servlet.MockMvc; import org.zowe.apiml.product.discovery.StaticRegistrationResult; @@ -28,6 +30,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; +@ExtendWith(MockitoExtension.class) class StaticApiRestControllerTest { private static final String CREDENTIALS = "eureka:password"; diff --git a/discovery-service/src/test/resources/application.yml b/discovery-service/src/test/resources/application.yml index d836c66cd9..6f6e5ee7dc 100644 --- a/discovery-service/src/test/resources/application.yml +++ b/discovery-service/src/test/resources/application.yml @@ -1,4 +1,6 @@ apiml: + security: + allowedDomains: localhost,localhost2,www.zowe.org,zowe.github.io,www.ibm.com discovery: allPeersUrls: http://${apiml.service.hostname}:${apiml.service.port}/eureka/ service: @@ -7,8 +9,6 @@ apiml: port: 20011 ipAddress: 127.0.0.1 preferIpAddress: false - security: - allowedDomains: localhost,localhost2,www.zowe.org,zowe.github.io,www.ibm.com spring: config: diff --git a/docs/sb4-migration-status.md b/docs/sb4-migration-status.md new file mode 100644 index 0000000000..74f458529e --- /dev/null +++ b/docs/sb4-migration-status.md @@ -0,0 +1,307 @@ +# Spring Boot 4 Migration Status + +**Branch:** `feat/sb4-health-tomcat-migration` +**Last updated:** 2026-06-05 +**Key versions:** Spring Boot 4.0.2 · Spring Cloud 2025.1.1 · Spring Framework 7.0.7 · Spring Security 7.0.2 · Java 17 + +--- + +## Build Status + +``` +./gradlew compileJava +``` + +**4 modules fail to compile:** + +| Module | Error count | +|--------|-------------| +| `discovery-service` | ~25 errors | +| `caching-service` | 3 errors | +| `zaas-service` | 2 errors | +| `api-catalog-services` | 1 error | + +All other modules (`apiml-common`, `apiml-tomcat-common`, `apiml-security-common`, `gateway-service`, `zaas-client`, etc.) compile successfully. + +--- + +## Active Compilation Failures + +### 1. Java Version / Jersey 4.0.1 Incompatibility (discovery-service) — BLOCKER + +**Root cause:** Jersey 4.0.1 (a transitive dependency pulled in by `spring-cloud-netflix-eureka-server:5.0.1` via `eureka-client-jersey3:2.0.6`) compiles to class file version **65.0 (Java 21)**, but the project targets **Java 17 (class file version 61.0)**. The JVM refuses to load this class. + +**Error:** +``` +discovery-service/.../RefreshablePeerEurekaNodes.java:232: error: cannot access ExtendedConfig + class CustomClientConfig extends ClientConfig { + bad class file: jersey-common-4.0.1.jar(org/glassfish/jersey/ExtendedConfig.class) + class file has wrong version 65.0, should be 61.0 +``` + +**Dependency chain:** +``` +spring-cloud-netflix-eureka-server:5.0.1 + → eureka-client-jersey3:2.0.6 + → jersey-client:3.0.5 → 4.0.1 (version conflict resolution) + → jersey-common:3.0.5 → 4.0.1 +``` + +**Resolution options:** +- **(a) Upgrade project to Java 21** — aligns with Spring Boot 4's recommended baseline. +- **(b) Force Jersey to 3.x** — add a dependency resolution rule in `discovery-service/build.gradle`: + ```groovy + configurations.all { + resolutionStrategy.force 'org.glassfish.jersey.core:jersey-common:3.1.9' + resolutionStrategy.force 'org.glassfish.jersey.core:jersey-client:3.1.9' + resolutionStrategy.force 'org.glassfish.jersey.core:jersey-server:3.1.9' + resolutionStrategy.force 'org.glassfish.jersey.inject:jersey-hk2:3.1.9' + } + ``` + +--- + +### 2. `InstanceRegistry.log` Privatized (discovery-service) + +**Root cause:** `spring-cloud-netflix-eureka-server:5.0.1` changed the `log` field visibility in `InstanceRegistry` from accessible (protected/package) to `private`. `ApimlInstanceRegistry extends InstanceRegistry` and references `log` directly. + +**Affected file:** `discovery-service/src/main/java/org/zowe/apiml/discovery/ApimlInstanceRegistry.java` + +**Errors:** +``` +ApimlInstanceRegistry.java:119: error: log has private access in InstanceRegistry +ApimlInstanceRegistry.java:119: error: cannot access Log +ApimlInstanceRegistry.java:203: error: log has private access in InstanceRegistry +ApimlInstanceRegistry.java:210: error: log has private access in InstanceRegistry +ApimlInstanceRegistry.java:214: error: log has private access in InstanceRegistry +ApimlInstanceRegistry.java:296: error: log has private access in InstanceRegistry +``` + +**Fix:** The class already has `@Slf4j`, but is using the inherited `log` field instead of its own. Since `@Slf4j` generates a field named `log`, the parent's private `log` shadows the Lombok one. Rename the Lombok logger via `@Slf4j(topic = "ApimlInstanceRegistry")` and use a local field name, or explicitly declare `private static final Logger log = LoggerFactory.getLogger(ApimlInstanceRegistry.class);` and remove references to the parent's field. + +--- + +### 3. Lombok `@Slf4j` in Lambda / Inner-Class Scopes (discovery-service) + +**Root cause:** Several classes use `log.debug/info/warn/error` inside lambdas or anonymous inner classes. Lombok's `@Slf4j` generates a `static` field, but `log` is not in scope inside a local class or a `BeanDefinitionRegistryPostProcessor` lambda. + +**Affected files:** +``` +discovery-service/.../config/EurekaConfig.java:67,69,137 +discovery-service/.../staticdef/StaticServicesRegistrationService.java:75,77,80,97 +discovery-service/.../staticdef/ServiceDefinitionProcessor.java:73,84,106,116,136,169,172,179,180,207,266,354,356,357 +discovery-service/.../eureka/RefreshablePeerEurekaNodes.java:161 +discovery-service/.../config/HttpWebSecurityConfig.java:132 (inner static class) +``` + +**Errors:** `error: cannot find symbol — variable log` + +**Fix:** For lambda bodies (e.g. in `deleteEurekaPeerAwareInstanceRegistry`), capture the logger in a local variable before the lambda: +```java +Logger localLog = log; +return registry -> { localLog.debug("..."); }; +``` +For the inner static class `EurekaBasicAuthenticationProvider`, add a `private static final Logger log = LoggerFactory.getLogger(EurekaBasicAuthenticationProvider.class);` field to the inner class (or use `@Slf4j` on it). + +--- + +### 4. `EurekaBasicAuthenticationProvider` Constructor Mismatch (discovery-service) + +**Root cause:** `EurekaBasicAuthenticationProvider` is annotated `@RequiredArgsConstructor` and has two `final` fields (`String eurekaUserid`, `char[] eurekaPassword`), so Lombok should generate a two-arg constructor. However, the compiler reports `required: no arguments`, meaning Lombok is not processing the inner `static` class correctly in this context. + +**Error:** +``` +HttpWebSecurityConfig.java:70: error: constructor EurekaBasicAuthenticationProvider cannot be applied + auth.authenticationProvider(new EurekaBasicAuthenticationProvider(eurekaUserid, eurekaPassword)); + required: no arguments + found: String,char[] +``` + +**Fix:** Explicitly write the constructor instead of relying on Lombok for this inner static class: +```java +EurekaBasicAuthenticationProvider(String eurekaUserid, char[] eurekaPassword) { + this.eurekaUserid = eurekaUserid; + this.eurekaPassword = eurekaPassword; +} +``` + +--- + +### 5. `serverProperties.getError()` Removed (discovery-service) + +**Root cause:** In Spring Boot 4, `ServerProperties` no longer has a `getError()` method. `ErrorProperties` has been separated out and `BasicErrorController` now takes it differently. + +**Affected file:** `discovery-service/src/main/java/org/zowe/apiml/discovery/config/DiscoveryErrorController.java:36` + +**Error:** +``` +super(errorAttributes, serverProperties.getError(), errorViewResolvers); +error: cannot find symbol — method getError() +``` + +**Fix:** Inject `ErrorProperties` directly and pass it to the super constructor: +```java +public DiscoveryErrorController(ErrorAttributes errorAttributes, + ErrorProperties errorProperties, + List errorViewResolvers) { + super(errorAttributes, errorProperties, errorViewResolvers); +} +``` +Wire it in configuration or rely on auto-injection using `@Autowired` + an `ErrorProperties` bean. + +--- + +### 6. `EurekaConfig` Symbol Conflicts (discovery-service) + +**Root cause:** Several `cannot find symbol` errors in `EurekaConfig.java` (lines 67, 69, 137) are the same `log`-in-lambda issue as item 3. Additionally, `RefreshablePeerEurekaNodes.java:161` has the same `log` issue in a local anonymous class. + +No additional fix beyond item 3 above. + +--- + +### 7. `ErrorPage` Package Moved (zaas-service, api-catalog-services) + +**Root cause:** In Spring Boot 4, `ErrorPage` moved from `org.springframework.boot.web.server.ErrorPage` to **`org.springframework.boot.web.error.ErrorPage`**. + +**Affected files:** +- `zaas-service/src/main/java/org/zowe/apiml/zaas/error/custom/CustomErrorStatusHandlingBean.java:14` +- `api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/controllers/handlers/CustomErrorStatusHandlingBean.java:14` + +**Error:** `error: cannot find symbol — class ErrorPage in package org.springframework.boot.web.server` + +**Fix:** Update import in both files: +```java +// Before +import org.springframework.boot.web.server.ErrorPage; +// After +import org.springframework.boot.web.error.ErrorPage; +``` + +--- + +### 8. `AntPathRequestMatcher` Removed in Spring Security 7.0.2 (zaas-service) + +**Root cause:** Spring Security 7.0.2 (bundled with Spring Boot 4) removed `AntPathRequestMatcher`. The replacement is `PathPatternRequestMatcher` (for pattern-based matching) or `OrRequestMatcher` for combining matchers. + +**Affected file:** `zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java:41,151` + +**Error:** `error: cannot find symbol — class AntPathRequestMatcher` + +**Usage:** +```java +.logoutRequestMatcher(new AntPathRequestMatcher(...)) +``` + +**Fix:** Replace with `PathPatternRequestMatcher.withDefaults()` or the factory method: +```java +import org.springframework.security.web.util.matcher.PathPatternRequestMatcher; +// ... +.logoutRequestMatcher(PathPatternRequestMatcher.withDefaults().matcher(...)) +``` +Or use the static factory: +```java +import static org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher.*; +.logoutRequestMatcher(pathPattern("/auth/logout")) +``` + +--- + +### 9. `CachesEndpoint` Missing Dependency (caching-service) + +**Root cause:** In Spring Boot 4, `CachesEndpoint` was extracted from `spring-boot-actuator` into the separate `spring-boot-cache` module. The class is at the same package path (`org.springframework.boot.cache.actuate.endpoint.CachesEndpoint`) but requires the `spring-boot-starter-cache` dependency. + +**Affected file:** `caching-service/src/main/java/org/zowe/apiml/caching/health/ApimlCachesEndpoint.java:14` + +**Error:** +``` +error: package org.springframework.boot.cache.actuate.endpoint does not exist +``` + +**Fix:** Add dependency to `caching-service/build.gradle`: +```groovy +implementation libs.spring_boot_starter_cache +``` +The library alias already exists in `gradle/versions.gradle`. + +--- + +## Minor / Non-Blocking Issues + +### `javax.servlet` String Literals (zaas-service tests) + +Three test assertions use the string constant `"javax.servlet.request.X509Certificate"`. In Jakarta EE this attribute key is `"jakarta.servlet.request.X509Certificate"`. + +**File:** `zaas-service/src/test/java/org/zowe/apiml/zaas/security/service/schema/source/X509AuthSourceServiceTest.java` (lines 102, 157, 206) + +**Fix:** Update string literals if the production code has been migrated; leave if the attribute name is intentionally backwards-compatible. + +### `javax.servlet` JavaDoc references (apiml-tomcat-common) + +**File:** `apiml-tomcat-common/src/main/java/org/zowe/apiml/gzip/GZipResponseUtils.java` (lines 49, 51, 71) + +These are JavaDoc `{@link javax.servlet...}` references. They break `javadoc -Xdoclint` but do not affect compilation. + +**Fix:** Update to `jakarta.servlet` references. + +### `spring.factories` for `EnvironmentPostProcessor` + +All services register `ServerAddressPropertiesUpdater` as an `EnvironmentPostProcessor` via `META-INF/spring.factories`. In Spring Boot 3+, the preferred approach is a dedicated file: + +``` +META-INF/spring/org.springframework.boot.env.EnvironmentPostProcessor.imports +``` + +`spring.factories` still works in Spring Boot 4 for this use case, but it is the legacy mechanism. This is not a compilation error. + +### Shadow Plugin Deprecation Warning + +``` +The legacy Shadow plugin (id 'com.github.johnrengelman.shadow') is deprecated. +Please use the Gradle Shadow plugin instead (id = 'com.gradleup.shadow') +``` + +Affects `onboarding-enabler-micronaut-sample-app`. Not a blocker. + +### Gradle Wrapper Version + +The `gradle-wrapper.properties` specifies **8.14.5**, while recent commits claim a move to Gradle 9.0. Update: +``` +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0-bin.zip +``` + +--- + +## Summary Table + +| # | Module | File | Issue | Severity | +|---|--------|------|-------|----------| +| 1 | `discovery-service` | transitive deps | Jersey 4.0.1 requires Java 21; project targets Java 17 | **BLOCKER** | +| 2 | `discovery-service` | `ApimlInstanceRegistry.java` | `InstanceRegistry.log` now private in Spring Cloud Netflix 5.0.1 | High | +| 3 | `discovery-service` | `EurekaConfig.java`, `StaticServicesRegistrationService.java`, `ServiceDefinitionProcessor.java`, `RefreshablePeerEurekaNodes.java` | Lombok `@Slf4j` `log` not accessible inside lambda/inner class scopes | High | +| 4 | `discovery-service` | `HttpWebSecurityConfig.java` | `@RequiredArgsConstructor` not generating constructor for inner static class | High | +| 5 | `discovery-service` | `DiscoveryErrorController.java` | `ServerProperties.getError()` removed in SB4 | High | +| 6 | `zaas-service` | `CustomErrorStatusHandlingBean.java` | `ErrorPage` moved to `org.springframework.boot.web.error` | Medium | +| 7 | `api-catalog-services` | `CustomErrorStatusHandlingBean.java` | Same as #6 | Medium | +| 8 | `zaas-service` | `NewSecurityConfiguration.java` | `AntPathRequestMatcher` removed in Spring Security 7.0.2 | Medium | +| 9 | `caching-service` | `ApimlCachesEndpoint.java` | `CachesEndpoint` moved to `spring-boot-cache` module; missing `spring-boot-starter-cache` dep | Medium | +| 10 | `zaas-service` tests | `X509AuthSourceServiceTest.java` | `javax.servlet.request.X509Certificate` string literal (should be jakarta) | Low | +| 11 | `apiml-tomcat-common` | `GZipResponseUtils.java` | JavaDoc references `javax.servlet` | Low | +| 12 | All services | `spring.factories` | Legacy mechanism for `EnvironmentPostProcessor` | Low | +| 13 | Micronaut sample | `build.gradle` | Deprecated Shadow plugin ID | Low | +| 14 | Root | `gradle-wrapper.properties` | Wrapper still at 8.14.5, not 9.0 | Low | + +--- + +## What Is Already Working + +The following migration work is complete and compiles successfully: + +- **Health indicators** — All services migrated from `org.springframework.boot.actuate.health.*` to `org.springframework.boot.health.contributor.*` (`AbstractHealthIndicator`, `Health`, `Status`) +- **Tomcat embedding** — Updated to `org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory` across all services +- **`javax` → `jakarta`** — Jakarta EE annotation imports updated (only standard Java `javax.net.ssl`, `javax.naming`, `javax.management` remain, correctly) +- **Spring Security** — All services use `SecurityFilterChain` bean pattern; no `WebSecurityConfigurerAdapter` remaining +- **WebSocket proxy** — Updated to Spring Framework 7 API (`execute()`, `containsHeader()`) +- **`HttpHeaders` API** — Fixed throughout: no longer inherits from `Map`; `forEach()` replaces `entrySet().stream()` patterns +- **Jackson** — `spring-boot-jackson2` dependency added to `apiml-tomcat-common` +- **Spring Framework version** — Pinned to `7.0.7` (the `7.0` BOM does not exist on Maven Central) +- **Modules compiling clean:** `apiml-common`, `apiml-tomcat-common`, `apiml-security-common`, `gateway-service`, `zaas-client`, `common-service-core`, `onboarding-enabler-spring`, `onboarding-enabler-java`, `apiml-extension-loader`, `security-service-client-spring`, `discoverable-client`, and all sample apps diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/GatewayServiceApplication.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/GatewayServiceApplication.java index 880d98207f..1c7f3142f7 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/GatewayServiceApplication.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/GatewayServiceApplication.java @@ -12,7 +12,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration; +import org.springframework.boot.security.oauth2.client.autoconfigure.reactive.ReactiveOAuth2ClientAutoConfiguration; @SpringBootApplication( scanBasePackages = { diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/caching/CachingServiceClientRest.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/caching/CachingServiceClientRest.java index 4b6a0fb554..61456cb627 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/caching/CachingServiceClientRest.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/caching/CachingServiceClientRest.java @@ -18,8 +18,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.client.WebClient; import org.zowe.apiml.message.log.ApimlLogger; import org.zowe.apiml.product.gateway.GatewayClient; @@ -56,7 +54,7 @@ public class CachingServiceClientRest implements CachingServiceClient, Initializ private volatile String cachingBalancerUrl; private final GatewayClient gatewayClient; - private static final MultiValueMap defaultHeaders = new LinkedMultiValueMap<>(); + private static final HttpHeaders defaultHeaders = new HttpHeaders(); static { defaultHeaders.add("Content-Type", "application/json"); diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/GatewayHealthIndicator.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/GatewayHealthIndicator.java index 5512d1b912..993e506203 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/GatewayHealthIndicator.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/GatewayHealthIndicator.java @@ -12,27 +12,26 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import org.zowe.apiml.message.log.ApimlLogger; -import org.zowe.apiml.product.compatibility.ApimlHealthCheckHandler; import org.zowe.apiml.product.constants.CoreService; import org.zowe.apiml.product.logging.annotations.InjectApimlLogger; import java.util.concurrent.atomic.AtomicBoolean; -import static org.springframework.boot.actuate.health.Status.DOWN; -import static org.springframework.boot.actuate.health.Status.UP; +import static org.springframework.boot.health.contributor.Status.DOWN; +import static org.springframework.boot.health.contributor.Status.UP; /** * Gateway health information (/application/health) - * This class contributes Gateway's information to {@link ApimlHealthCheckHandler} + * This class contributes Gateway's information to {@link org.springframework.cloud.netflix.eureka.EurekaHealthCheckHandler} * */ @Component diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/SslUpdater.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/SslUpdater.java index 0ebd8cb7a4..dba8ff60b5 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/SslUpdater.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/SslUpdater.java @@ -12,7 +12,7 @@ import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.boot.web.server.Ssl; import org.springframework.stereotype.Component; import org.zowe.apiml.security.SecurityUtils; diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/UrlTomcatCustomizer.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/UrlTomcatCustomizer.java index 17f43ef14a..e72868ce6e 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/config/UrlTomcatCustomizer.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/config/UrlTomcatCustomizer.java @@ -13,7 +13,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.buf.EncodedSolidusHandling; -import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.tomcat.TomcatConnectorCustomizer; import org.springframework.stereotype.Component; @Slf4j diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/AbstractAuthSchemeFactory.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/AbstractAuthSchemeFactory.java index 37f59b45ed..8143eb4250 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/AbstractAuthSchemeFactory.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/AbstractAuthSchemeFactory.java @@ -179,9 +179,11 @@ protected RequestCredentials.RequestCredentialsBuilder createRequestCredentials( List cookies = CookieUtil.readCookies(headers).toList(); // set in the request to ZAAS all cookies and headers that contain credentials - headers.entrySet().stream() - .filter(e -> CREDENTIALS_HEADER_INPUT.test(e.getKey())) - .forEach(e -> zaasRequestBuilder.addHeader(e.getKey(), e.getValue().toArray(new String[0]))); + headers.forEach((key, values) -> { + if (CREDENTIALS_HEADER_INPUT.test(key)) { + zaasRequestBuilder.addHeader(key, values.toArray(new String[0])); + } + }); cookies.stream() .filter(CREDENTIALS_COOKIE_INPUT) .forEach(c -> zaasRequestBuilder.addCookie(c.getName(), c.getValue())); @@ -242,14 +244,17 @@ protected ServerHttpRequest cleanHeadersOnAuthSuccess(ServerWebExchange exchange List cookies = CookieUtil.readCookies(headers).toList(); // update original request - to remove all potential headers and cookies with credentials - Stream> nonCredentialHeaders = headers.entrySet().stream() - .filter(entry -> !CREDENTIALS_HEADER.test(entry.getKey())) - .flatMap(entry -> entry.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(entry.getKey(), v))); + java.util.List> nonCredentialHeaders = new java.util.ArrayList<>(); + headers.forEach((key, values) -> { + if (!CREDENTIALS_HEADER.test(key)) { + values.forEach(v -> nonCredentialHeaders.add(new AbstractMap.SimpleEntry<>(key, v))); + } + }); Stream> nonCredentialCookies = cookies.stream() .filter(c -> !CREDENTIALS_COOKIE.test(c)) .map(c -> new AbstractMap.SimpleEntry<>(HttpHeaders.COOKIE, c.toString())); List> newHeaders = Stream.concat( - nonCredentialHeaders, + nonCredentialHeaders.stream(), nonCredentialCookies ).toList(); diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/HeaderRouteStepFilterFactory.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/HeaderRouteStepFilterFactory.java index 3ec81d04a6..f1be225e8f 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/HeaderRouteStepFilterFactory.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/HeaderRouteStepFilterFactory.java @@ -36,7 +36,7 @@ public HeaderRouteStepFilterFactory() { public GatewayFilter apply(Config config) { String header = config.getHeader(); return (exchange, chain) -> { - if (exchange.getRequest().getHeaders().containsKey(header)) { + if (exchange.getRequest().getHeaders().get(header) != null) { exchange = exchange.mutate().request(request -> request.headers(headers -> { String headerValue = headers.getFirst(header); int index = headerValue.indexOf("/"); diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/MissingHeaderRoutePredicateFactory.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/MissingHeaderRoutePredicateFactory.java index 809a8953ce..e27619f4ea 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/MissingHeaderRoutePredicateFactory.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/MissingHeaderRoutePredicateFactory.java @@ -38,7 +38,7 @@ public Predicate apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange exchange) { - return !exchange.getRequest().getHeaders().containsKey(config.header); + return exchange.getRequest().getHeaders().get(config.header) == null; } @Override diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/proxyheaders/X509AndGwAwareXForwardedHeadersFilter.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/proxyheaders/X509AndGwAwareXForwardedHeadersFilter.java index b6cd7dff72..eb7ac92832 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/proxyheaders/X509AndGwAwareXForwardedHeadersFilter.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/filters/proxyheaders/X509AndGwAwareXForwardedHeadersFilter.java @@ -155,7 +155,7 @@ private boolean isXForwardedHeader(String header) { } private boolean hasXForwardedHeader(HttpHeaders headers) { - return headers.keySet().stream() + return headers.toSingleValueMap().keySet().stream() .anyMatch(this::isXForwardedHeader); } } diff --git a/gateway-service/src/main/java/org/zowe/apiml/gateway/websocket/ApimlWebSocketSession.java b/gateway-service/src/main/java/org/zowe/apiml/gateway/websocket/ApimlWebSocketSession.java index 6261d660ea..544726ba62 100644 --- a/gateway-service/src/main/java/org/zowe/apiml/gateway/websocket/ApimlWebSocketSession.java +++ b/gateway-service/src/main/java/org/zowe/apiml/gateway/websocket/ApimlWebSocketSession.java @@ -19,8 +19,11 @@ import org.springframework.web.reactive.socket.HandshakeInfo; import org.springframework.web.reactive.socket.adapter.TomcatWebSocketSession; import reactor.core.publisher.Sinks; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ApimlWebSocketSession extends TomcatWebSocketSession { + private static final Logger LOG = LoggerFactory.getLogger(ApimlWebSocketSession.class); private Sinks.Empty completionSink; @@ -39,10 +42,10 @@ public void onError(Throwable ex) { // Ignore result: can't overflow, ok if not first or no one listens this.completionSink.tryEmitError(ex); } - if (logger.isDebugEnabled()) { - logger.debug("WebSocket session completed with error", ex); - } else if (logger.isInfoEnabled()) { - logger.info("WebSocket session completed with error: " + ex.getMessage()); + if (LOG.isDebugEnabled()) { + LOG.debug("WebSocket session completed with error", ex); + } else if (LOG.isInfoEnabled()) { + LOG.info("WebSocket session completed with error: " + ex.getMessage()); } // Jakarta implementation if (ex.getCause() instanceof AuthenticationException) { diff --git a/gateway-service/src/main/resources/application.yml b/gateway-service/src/main/resources/application.yml index adcea536e4..5e123a26e8 100644 --- a/gateway-service/src/main/resources/application.yml +++ b/gateway-service/src/main/resources/application.yml @@ -58,6 +58,7 @@ spring: gateway: server: webflux: + trusted-proxies: "192.168.0.0/16,10.0.0.0/8" x-forwarded: prefix-append: false prefix-enabled: true @@ -102,7 +103,7 @@ apiml: corsAllowedEndpoints: /gateway/** allowEncodedSlashes: true discoveryServiceUrls: https://localhost:10011/eureka/ - forwardClientCertEnabled: true + forwardClientCertEnabled: false hostname: localhost id: ${spring.application.name} ignoredHeadersWhenCorsEnabled: Access-Control-Request-Method,Access-Control-Request-Headers,Access-Control-Allow-Origin,Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Credentials,Origin diff --git a/gateway-service/src/test/java/org/zowe/apiml/gateway/config/GatewayHealthIndicatorTest.java b/gateway-service/src/test/java/org/zowe/apiml/gateway/config/GatewayHealthIndicatorTest.java index 3afddfd092..b44de27aff 100644 --- a/gateway-service/src/test/java/org/zowe/apiml/gateway/config/GatewayHealthIndicatorTest.java +++ b/gateway-service/src/test/java/org/zowe/apiml/gateway/config/GatewayHealthIndicatorTest.java @@ -12,8 +12,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; diff --git a/gateway-service/src/test/java/org/zowe/apiml/gateway/config/SslUpdaterTest.java b/gateway-service/src/test/java/org/zowe/apiml/gateway/config/SslUpdaterTest.java index 82cb289498..25b2bfe1ba 100644 --- a/gateway-service/src/test/java/org/zowe/apiml/gateway/config/SslUpdaterTest.java +++ b/gateway-service/src/test/java/org/zowe/apiml/gateway/config/SslUpdaterTest.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.boot.web.server.Ssl; import static org.junit.jupiter.api.Assertions.*; diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 513e328eaa..0efef7085d 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -5,13 +5,13 @@ dependencyResolutionManagement { version('projectNode', '24.10.0') version('projectNpm', '10.9.0') - version('springBoot', '3.5.15') - version('springBootGraphQl', '3.5.15') - version('springCloudNetflix', '4.3.3') - version('springCloudCommons', '4.3.3') - version('springCloudCB', '3.3.3') - version('springCloudGateway', '4.3.4') - version('springFramework', '6.2.19') + version('springBoot', '4.0.2') + version('springBootGraphQl', '4.0.2') + version('springCloudNetflix', '5.0.1') + version('springCloudCommons', '5.0.1') + version('springCloudCB', '5.0.1') + version('springCloudGateway', '5.0.1') + version('springFramework', '7.0.7') version('springRetry', '2.0.13') version('modulith', '1.4.12') @@ -88,6 +88,9 @@ dependencyResolutionManagement { version('reactor', '3.8.6') version('restAssured', '5.5.7') + // Force Groovy 4.0.x — REST Assured 5.5.7 is incompatible with Groovy 5.x + // (NullPointerException in Class.isAssignableFrom via ClosureMetaClass) + version('groovy', '4.0.28') version('rhino', '1.9.1') version('springDoc', '2.8.17') version('swaggerCore', '2.2.51') @@ -137,7 +140,7 @@ dependencyResolutionManagement { library('spring_boot_starter_web', 'org.springframework.boot', 'spring-boot-starter-web').versionRef('springBoot') library('spring_boot_starter_websocket', 'org.springframework.boot', 'spring-boot-starter-websocket').versionRef('springBoot') library('spring_boot_starter_test', 'org.springframework.boot', 'spring-boot-starter-test').versionRef('springBoot') - library('spring_boot_starter_aop', 'org.springframework.boot', 'spring-boot-starter-aop').versionRef('springBoot') + library('spring_boot_starter_aspectj', 'org.springframework.boot', 'spring-boot-starter-aspectj').versionRef('springBoot') library('spring_boot_starter_thymeleaf', 'org.springframework.boot', 'spring-boot-starter-thymeleaf').versionRef('springBoot') library('spring_boot_starter_cache', 'org.springframework.boot', 'spring-boot-starter-cache').versionRef('springBoot') library('spring_boot_starter_webflux', 'org.springframework.boot', 'spring-boot-starter-webflux').versionRef('springBoot') @@ -145,7 +148,7 @@ dependencyResolutionManagement { library('spring_cloud_starter_eureka_client', 'org.springframework.cloud', 'spring-cloud-starter-netflix-eureka-client').versionRef('springCloudNetflix') library('spring_cloud_starter_eureka_server', 'org.springframework.cloud', 'spring-cloud-starter-netflix-eureka-server').versionRef('springCloudNetflix') library('spring_cloud_starter_gateway', 'org.springframework.cloud', 'spring-cloud-starter-gateway-server-webflux').versionRef('springCloudGateway') - library('spring_cloud_gateway_server', 'org.springframework.cloud', 'spring-cloud-gateway-server').versionRef('springCloudGateway') + library('spring_cloud_gateway_server', 'org.springframework.cloud', 'spring-cloud-gateway-server-webflux').versionRef('springCloudGateway') library('spring_cloud_commons', 'org.springframework.cloud', 'spring-cloud-commons').versionRef('springCloudCommons') library('spring_cloud_circuit_breaker', 'org.springframework.cloud', 'spring-cloud-starter-circuitbreaker-reactor-resilience4j').versionRef('springCloudCB') diff --git a/integration-tests/src/test/java/org/zowe/apiml/integration/ha/WebSocketChaoticTest.java b/integration-tests/src/test/java/org/zowe/apiml/integration/ha/WebSocketChaoticTest.java index 015b0d9b66..726ff9ba7e 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/integration/ha/WebSocketChaoticTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/integration/ha/WebSocketChaoticTest.java @@ -80,7 +80,7 @@ private WebSocketSession appendingWebSocketSession(URI uri, WebSocketHttpHeaders throws Exception { StandardWebSocketClient client = new StandardWebSocketClient(); client.setSslContext(HttpClientUtils.ignoreSslContext()); - return client.doHandshake(appendResponseHandler(response, countToNotify), headers, uri).get(30000, TimeUnit.MILLISECONDS); + return client.execute(appendResponseHandler(response, countToNotify), headers, uri).get(30000, TimeUnit.MILLISECONDS); } @Nested diff --git a/integration-tests/src/test/java/org/zowe/apiml/integration/proxy/WebSocketProxyTest.java b/integration-tests/src/test/java/org/zowe/apiml/integration/proxy/WebSocketProxyTest.java index cb4d36195a..11844fad54 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/integration/proxy/WebSocketProxyTest.java +++ b/integration-tests/src/test/java/org/zowe/apiml/integration/proxy/WebSocketProxyTest.java @@ -155,7 +155,7 @@ void message() throws Exception { @Test void headers() throws Exception { final StringBuilder response = new StringBuilder(); - if (!VALID_AUTH_HEADERS.containsKey("X-Test")) { + if (!VALID_AUTH_HEADERS.containsHeader("X-Test")) { VALID_AUTH_HEADERS.add("X-Test", "value"); } VALID_AUTH_HEADERS.add("Cookie", validToken); @@ -210,7 +210,7 @@ void whenUrlFormatIsNotCorrect() throws Exception { @Test void whenHandshakeRequestIsTooLarge() throws Exception { final StringBuilder response = new StringBuilder(); - if (!VALID_AUTH_HEADERS.containsKey("X-Test")) { + if (!VALID_AUTH_HEADERS.containsHeader("X-Test")) { VALID_AUTH_HEADERS.add("X-Test", "value"); } VALID_AUTH_HEADERS.add("Cookie", validToken); diff --git a/integration-tests/src/test/java/org/zowe/apiml/util/service/VirtualService.java b/integration-tests/src/test/java/org/zowe/apiml/util/service/VirtualService.java index 270f351807..c9807df607 100644 --- a/integration-tests/src/test/java/org/zowe/apiml/util/service/VirtualService.java +++ b/integration-tests/src/test/java/org/zowe/apiml/util/service/VirtualService.java @@ -29,7 +29,7 @@ import org.apache.http.HttpStatus; import org.json.JSONException; import org.json.JSONObject; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Status; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.zowe.apiml.auth.Authentication; diff --git a/onboarding-enabler-spring-sample-app/build.gradle b/onboarding-enabler-spring-sample-app/build.gradle index 69eab93467..31a0f0983f 100644 --- a/onboarding-enabler-spring-sample-app/build.gradle +++ b/onboarding-enabler-spring-sample-app/build.gradle @@ -18,7 +18,7 @@ apply plugin: 'org.springframework.boot' bootJar { archiveBaseName.set("enabler-springboot-${libs.versions.springBoot.get()}-sample") - launchScript() + // launchScript() // TODO: SB4 migration — launchScript() removed in Spring Boot 4.x, tracked in #4719 } jar { diff --git a/zaas-service/build.gradle b/zaas-service/build.gradle index 9ea505c415..f1bf841a55 100644 --- a/zaas-service/build.gradle +++ b/zaas-service/build.gradle @@ -64,7 +64,7 @@ dependencies { implementation libs.spring.boot.starter.actuator implementation libs.spring.boot.starter.web implementation libs.spring.boot.starter.cache - implementation libs.spring.boot.starter.aop + implementation libs.spring.boot.starter.aspectj implementation libs.spring.boot.starter.security implementation libs.spring.cloud.starter.eureka.client implementation libs.spring.retry diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/ZaasApplication.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/ZaasApplication.java index 2063563af5..38ebebe571 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/ZaasApplication.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/ZaasApplication.java @@ -11,8 +11,6 @@ package org.zowe.apiml.zaas; import org.springframework.boot.SpringApplication; -import org.springframework.boot.actuate.autoconfigure.logging.OpenTelemetryLoggingAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @@ -30,8 +28,6 @@ @EnableWebSecurity @SpringBootApplication( exclude = { - OpenTelemetryAutoConfiguration.class, - OpenTelemetryLoggingAutoConfiguration.class } ) @EnableDiscoveryClient diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/error/controllers/ZaasErrorController.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/error/controllers/ZaasErrorController.java index fa9221d415..a494e46f5d 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/error/controllers/ZaasErrorController.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/error/controllers/ZaasErrorController.java @@ -14,7 +14,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.boot.webmvc.error.ErrorController; import org.springframework.context.annotation.Primary; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/error/custom/CustomErrorStatusHandlingBean.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/error/custom/CustomErrorStatusHandlingBean.java index ccf1f0af90..edad327686 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/error/custom/CustomErrorStatusHandlingBean.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/error/custom/CustomErrorStatusHandlingBean.java @@ -11,9 +11,9 @@ package org.zowe.apiml.zaas.error.custom; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.web.server.ErrorPage; +import org.springframework.boot.web.error.ErrorPage; import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/health/ZaasHealthIndicator.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/health/ZaasHealthIndicator.java index 9feb54694b..624f988979 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/health/ZaasHealthIndicator.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/health/ZaasHealthIndicator.java @@ -11,16 +11,16 @@ package org.zowe.apiml.zaas.health; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.actuate.health.AbstractHealthIndicator; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.AbstractHealthIndicator; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.stereotype.Component; import org.zowe.apiml.product.constants.CoreService; import org.zowe.apiml.zaas.security.login.Providers; -import static org.springframework.boot.actuate.health.Status.DOWN; -import static org.springframework.boot.actuate.health.Status.UP; +import static org.springframework.boot.health.contributor.Status.DOWN; +import static org.springframework.boot.health.contributor.Status.UP; /** * ZAAS health information (/application/health) diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java index 448d79fc3c..7556c7ba54 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/config/NewSecurityConfiguration.java @@ -38,7 +38,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutHandler; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.zowe.apiml.filter.AttlsFilter; import org.zowe.apiml.filter.SecureConnectionFilter; import org.zowe.apiml.security.common.config.AuthConfigurationProperties; @@ -148,8 +148,8 @@ SecurityFilterChain authenticationFunctionalityFilterChain(HttpSecurity http) th .anyRequest().permitAll()) .logout(logout -> logout - .logoutRequestMatcher(new AntPathRequestMatcher( - authConfigurationProperties.getZaasLogoutEndpoint(), HttpMethod.POST.name() + .logoutRequestMatcher(PathPatternRequestMatcher.pathPattern( + HttpMethod.POST, authConfigurationProperties.getZaasLogoutEndpoint() )) .addLogoutHandler(logoutHandler()) .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.NO_CONTENT))) diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/login/dummy/DummyAuthenticationProvider.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/login/dummy/DummyAuthenticationProvider.java index 3c59924cab..25e0091ad8 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/login/dummy/DummyAuthenticationProvider.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/login/dummy/DummyAuthenticationProvider.java @@ -47,9 +47,8 @@ public DummyAuthenticationProvider(BCryptPasswordEncoder encoder, @Qualifier("dummyService") UserDetailsService userDetailsService, AuthenticationService authenticationService, ApplicationEventPublisher publisher) { - super(); + super(userDetailsService); this.setPasswordEncoder(encoder); - this.setUserDetailsService(userDetailsService); this.authenticationService = authenticationService; this.publisher = publisher; } diff --git a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/service/zosmf/AbstractZosmfService.java b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/service/zosmf/AbstractZosmfService.java index 75d0efe98b..9976fdebc3 100644 --- a/zaas-service/src/main/java/org/zowe/apiml/zaas/security/service/zosmf/AbstractZosmfService.java +++ b/zaas-service/src/main/java/org/zowe/apiml/zaas/security/service/zosmf/AbstractZosmfService.java @@ -173,9 +173,9 @@ protected RuntimeException handleExceptionOnCall(String url, RuntimeException re if (re instanceof RestClientResponseException) { RestClientResponseException responseException = (RestClientResponseException) re; if (log.isTraceEnabled()) { - log.trace("z/OSMF request {} failed with status code {}, server response: {}", url, responseException.getRawStatusCode(), responseException.getResponseBodyAsString()); + log.trace("z/OSMF request {} failed with status code {}, server response: {}", url, responseException.getStatusCode().value(), responseException.getResponseBodyAsString()); } else { - log.debug("z/OSMF request {} failed with status code {}", url, responseException.getRawStatusCode()); + log.debug("z/OSMF request {} failed with status code {}", url, responseException.getStatusCode().value()); } } diff --git a/zaas-service/src/test/java/org/zowe/apiml/zaas/health/ZaasHealthIndicatorTest.java b/zaas-service/src/test/java/org/zowe/apiml/zaas/health/ZaasHealthIndicatorTest.java index 35bea62563..3d281d0bc1 100644 --- a/zaas-service/src/test/java/org/zowe/apiml/zaas/health/ZaasHealthIndicatorTest.java +++ b/zaas-service/src/test/java/org/zowe/apiml/zaas/health/ZaasHealthIndicatorTest.java @@ -13,8 +13,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.boot.actuate.health.Health; -import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.health.contributor.Health; +import org.springframework.boot.health.contributor.Status; import org.zowe.apiml.zaas.security.login.Providers; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/zaas-service/src/test/java/org/zowe/apiml/zaas/security/service/schema/source/X509AuthSourceServiceTest.java b/zaas-service/src/test/java/org/zowe/apiml/zaas/security/service/schema/source/X509AuthSourceServiceTest.java index b59e359654..35b60de541 100644 --- a/zaas-service/src/test/java/org/zowe/apiml/zaas/security/service/schema/source/X509AuthSourceServiceTest.java +++ b/zaas-service/src/test/java/org/zowe/apiml/zaas/security/service/schema/source/X509AuthSourceServiceTest.java @@ -99,7 +99,7 @@ void whenNoClientCertInRequest_thenThrows() { request = mock(HttpServletRequest.class); assertFalse(serviceUnderTest.getAuthSourceFromRequest(request).isPresent()); verify(request, times(1)).getAttribute("client.auth.X509Certificate"); - verify(request, times(0)).getAttribute("javax.servlet.request.X509Certificate"); + verify(request, times(0)).getAttribute("jakarta.servlet.request.X509Certificate"); } @Test @@ -154,7 +154,7 @@ void whenClientCertInRequest_thenAuthSourceIsPresent() { Optional authSource = serviceUnderTest.getAuthSourceFromRequest(request); verify(request, times(1)).getAttribute("client.auth.X509Certificate"); - verify(request, times(0)).getAttribute("javax.servlet.request.X509Certificate"); + verify(request, times(0)).getAttribute("jakarta.servlet.request.X509Certificate"); Assertions.assertTrue(authSource.isPresent()); Assertions.assertTrue(authSource.get() instanceof X509AuthSource); @@ -203,7 +203,7 @@ void whenInternalApimlCertInRequestInStandardAttribute_thenThrows() { assertFalse(serviceUnderTest.getAuthSourceFromRequest(request).isPresent()); verify(request, times(1)).getAttribute("client.auth.X509Certificate"); - verify(request, times(0)).getAttribute("javax.servlet.request.X509Certificate"); + verify(request, times(0)).getAttribute("jakarta.servlet.request.X509Certificate"); } @Test