From 7954caad63249c17ab3b77e5932b9427df92c598 Mon Sep 17 00:00:00 2001 From: shroffk Date: Tue, 4 Aug 2026 09:30:44 -0400 Subject: [PATCH 01/12] Phased upgrade of springboot --- services/alarm-config-logger/pom.xml | 6 ++++-- services/alarm-logger/pom.xml | 6 ++++-- .../org/phoebus/alarm/logging/purge/ElasticIndexPurger.java | 2 +- .../org/phoebus/alarm/logging/rest/SearchController.java | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/services/alarm-config-logger/pom.xml b/services/alarm-config-logger/pom.xml index 53bbfc6b59..a59189f5d3 100644 --- a/services/alarm-config-logger/pom.xml +++ b/services/alarm-config-logger/pom.xml @@ -7,6 +7,8 @@ 21 + + 3.5.16 service-alarm-config-logger ${project.groupId}:${project.artifactId} @@ -91,8 +93,8 @@ jackson-annotations ${jackson.annotations.version} - - + + org.slf4j slf4j-jdk14 1.7.28 diff --git a/services/alarm-logger/pom.xml b/services/alarm-logger/pom.xml index ea56a8b29d..3f6737afaa 100644 --- a/services/alarm-logger/pom.xml +++ b/services/alarm-logger/pom.xml @@ -7,6 +7,8 @@ 21 + + 3.5.16 service-alarm-logger ${project.groupId}:${project.artifactId} @@ -141,8 +143,8 @@ org.springdoc - springdoc-openapi-ui - 1.7.0 + springdoc-openapi-starter-webmvc-ui + 2.8.17 diff --git a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/purge/ElasticIndexPurger.java b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/purge/ElasticIndexPurger.java index f5a22e3e3b..33aee84ade 100644 --- a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/purge/ElasticIndexPurger.java +++ b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/purge/ElasticIndexPurger.java @@ -38,7 +38,7 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.io.IOException; import java.time.Instant; import java.time.temporal.ChronoUnit; diff --git a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java index fa0b6d5937..33141d0048 100644 --- a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java +++ b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java @@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.LinkedHashMap; From 5723ffc8053ec539acb8f31668eddaf08db4f02b Mon Sep 17 00:00:00 2001 From: shroffk Date: Tue, 4 Aug 2026 09:45:50 -0400 Subject: [PATCH 02/12] update save and restore - spring 3, jakarta --- app/save-and-restore/model/pom.xml | 6 +-- services/save-and-restore/pom.xml | 18 ++++---- .../web/config/AcceptHeaderResolver.java | 2 +- .../web/config/WebConfiguration.java | 2 +- .../web/config/WebSecurityConfig.java | 43 +++++++++---------- .../web/controllers/BaseController.java | 4 +- .../web/controllers/HelpResource.java | 2 +- .../web/config/ControllersTestConfig.java | 10 ++--- .../web/controllers/SearchControllerTest.java | 6 +-- 9 files changed, 45 insertions(+), 48 deletions(-) diff --git a/app/save-and-restore/model/pom.xml b/app/save-and-restore/model/pom.xml index a8c3a05d54..ea17f1a944 100644 --- a/app/save-and-restore/model/pom.xml +++ b/app/save-and-restore/model/pom.xml @@ -72,11 +72,11 @@ ${tools.jackson.version} - + org.glassfish - javax.json - 1.1.4 + jakarta.json + 2.0.1 diff --git a/services/save-and-restore/pom.xml b/services/save-and-restore/pom.xml index b672def0ce..44d36b15b3 100644 --- a/services/save-and-restore/pom.xml +++ b/services/save-and-restore/pom.xml @@ -14,6 +14,7 @@ 4.4 + 3.5.16 @@ -52,8 +53,8 @@ org.springdoc - springdoc-openapi-ui - 1.7.0 + springdoc-openapi-starter-webmvc-ui + 2.8.17 @@ -160,6 +161,12 @@ 2.0.1 + + + org.glassfish + jakarta.json + 2.0.1 + org.springframework.boot spring-boot-starter-logging @@ -171,13 +178,6 @@ - - - org.glassfish - javax.json - 1.1.4 - - org.springframework diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/AcceptHeaderResolver.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/AcceptHeaderResolver.java index 17c9a8c9f0..1389682451 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/AcceptHeaderResolver.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/AcceptHeaderResolver.java @@ -20,7 +20,7 @@ import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.List; import java.util.Locale; diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebConfiguration.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebConfiguration.java index 63fe8a2dc1..1530c661f3 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebConfiguration.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebConfiguration.java @@ -27,7 +27,7 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.Scope; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletContext; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java index 2f8544104d..fb97d28aad 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java @@ -13,8 +13,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; @@ -30,13 +29,15 @@ import org.springframework.security.web.SecurityFilterChain; import tools.jackson.databind.json.JsonMapper; +import static org.springframework.security.config.Customizer.withDefaults; + /** * {@link Configuration} class setting up authentication/authorization depending on the * auth.impl application property. */ @Configuration @EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) +@EnableMethodSecurity(prePostEnabled = true) @SuppressWarnings("unused") public class WebSecurityConfig { @@ -189,8 +190,8 @@ public String authenticationImplementation(){ public WebSecurityCustomizer ignoringCustomizer() { return web -> { // The below lists exceptions for authentication. - web.ignoring().antMatchers(HttpMethod.GET, "/**"); - web.ignoring().antMatchers(HttpMethod.POST, "/**/login*"); + web.ignoring().requestMatchers(HttpMethod.GET, "/**"); + web.ignoring().requestMatchers(HttpMethod.POST, "/**/login*"); }; } @@ -202,9 +203,9 @@ public WebSecurityCustomizer ignoringCustomizer() { */ @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf().disable(); - http.authorizeRequests().anyRequest().authenticated(); - http.httpBasic(); + http.csrf(csrf -> csrf.disable()); + http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated()); + http.httpBasic(withDefaults()); return http.build(); } @@ -255,17 +256,17 @@ public LdapAuthoritiesPopulator authorities(BaseLdapPathContextSource contextSou myAuthPopulator.setGroupSearchFilter(ldap_groups_search_pattern); myAuthPopulator.setSearchSubtree(true); myAuthPopulator.setIgnorePartialResultException(true); - LdapAuthenticationProviderConfigurer configurer = new LdapAuthenticationProviderConfigurer(); - if (ldap_user_dn_pattern != null && !ldap_user_dn_pattern.isEmpty()) { - configurer.userDnPatterns(ldap_user_dn_pattern); - } - if (ldap_user_search_filter != null && !ldap_user_search_filter.isEmpty()) { - configurer.userSearchFilter(ldap_user_search_filter); - } - if (ldap_user_search_base != null && !ldap_user_search_base.isEmpty()) { - configurer.userSearchBase(ldap_user_search_base); - } - configurer.contextSource(contextSource); +// LdapAuthenticationProviderConfigurer configurer = new LdapAuthenticationProviderConfigurer(); +// if (ldap_user_dn_pattern != null && !ldap_user_dn_pattern.isEmpty()) { +// configurer.userDnPatterns(ldap_user_dn_pattern); +// } +// if (ldap_user_search_filter != null && !ldap_user_search_filter.isEmpty()) { +// configurer.userSearchFilter(ldap_user_search_filter); +// } +// if (ldap_user_search_base != null && !ldap_user_search_base.isEmpty()) { +// configurer.userSearchBase(ldap_user_search_base); +// } +// configurer.contextSource(contextSource); return myAuthPopulator; } @@ -347,9 +348,7 @@ public ObjectMapper objectMapper() { */ @Bean public RoleHierarchy roleHierarchy() { - RoleHierarchyImpl hierarchy = new RoleHierarchyImpl(); - hierarchy.setHierarchy("ROLE_" + roleAdmin.toUpperCase() + " > ROLE_" + roleUser.toUpperCase()); - return hierarchy; + return RoleHierarchyImpl.fromHierarchy("ROLE_" + roleAdmin.toUpperCase() + " > ROLE_" + roleUser.toUpperCase()); } /** diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/BaseController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/BaseController.java index d031cb6e1b..b732ed5c6c 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/BaseController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/BaseController.java @@ -25,8 +25,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java index 5b8d8b8697..64359e43db 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java @@ -28,7 +28,7 @@ import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java index a6e5bc57af..ff61d72dbc 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java @@ -36,10 +36,10 @@ import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.user.SimpUserRegistry; import org.springframework.mock.web.MockServletContext; -import org.springframework.util.Base64Utils; +import java.util.Base64; import org.springframework.web.socket.WebSocketSession; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletContext; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -111,17 +111,17 @@ public SearchUtil searchUtil() { @Bean("userAuthorization") public String userAuthorization() { - return "Basic " + Base64Utils.encodeToString((demoUser + ":" + demoUserPassword).getBytes()); + return "Basic " + Base64.getEncoder().encodeToString((demoUser + ":" + demoUserPassword).getBytes()); } @Bean("adminAuthorization") public String adminAuthorization() { - return "Basic " + Base64Utils.encodeToString((demoAdmin + ":" + demoAdminPassword).getBytes()); + return "Basic " + Base64.getEncoder().encodeToString((demoAdmin + ":" + demoAdminPassword).getBytes()); } @Bean("readOnlyAuthorization") public String readOnlyAuthorization() { - return "Basic " + Base64Utils.encodeToString((demoReadOnly + ":" + demoReadOnlyPassword).getBytes()); + return "Basic " + Base64.getEncoder().encodeToString((demoReadOnly + ":" + demoReadOnlyPassword).getBytes()); } @Bean diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java index ad6b7fe40d..fe14f94b36 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java @@ -42,9 +42,7 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.util.LinkedMultiValueMap; - -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; +import org.springframework.util.MultiValueMap; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -96,7 +94,7 @@ public void testSearch() throws Exception { @Test public void testSearchForPVs() { - MultivaluedMap> searchParams = new MultivaluedHashMap<>(); + MultiValueMap> searchParams = new LinkedMultiValueMap<>(); searchParams.put("type", List.of(List.of(NodeType.CONFIGURATION.toString()))); searchParams.put("pvs", List.of(List.of("abc"))); From 6188eab45141dfa803c031bd4e2d6fc9caa85f7b Mon Sep 17 00:00:00 2001 From: shroffk Date: Tue, 4 Aug 2026 10:41:02 -0400 Subject: [PATCH 03/12] spring 4.1 --- services/alarm-config-logger/pom.xml | 4 ++-- services/alarm-logger/pom.xml | 4 ++-- .../logging/rest/SearchControllerTest.java | 23 +++++++++++-------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/services/alarm-config-logger/pom.xml b/services/alarm-config-logger/pom.xml index a59189f5d3..825f0cc74f 100644 --- a/services/alarm-config-logger/pom.xml +++ b/services/alarm-config-logger/pom.xml @@ -7,8 +7,8 @@ 21 - - 3.5.16 + + 4.1.0 service-alarm-config-logger ${project.groupId}:${project.artifactId} diff --git a/services/alarm-logger/pom.xml b/services/alarm-logger/pom.xml index 3f6737afaa..8f85792902 100644 --- a/services/alarm-logger/pom.xml +++ b/services/alarm-logger/pom.xml @@ -7,8 +7,8 @@ 21 - - 3.5.16 + + 4.1.0 service-alarm-logger ${project.groupId}:${project.artifactId} diff --git a/services/alarm-logger/src/test/java/org/phoebus/alarm/logging/rest/SearchControllerTest.java b/services/alarm-logger/src/test/java/org/phoebus/alarm/logging/rest/SearchControllerTest.java index 83400e8b9c..4b919ea3c8 100644 --- a/services/alarm-logger/src/test/java/org/phoebus/alarm/logging/rest/SearchControllerTest.java +++ b/services/alarm-logger/src/test/java/org/phoebus/alarm/logging/rest/SearchControllerTest.java @@ -4,28 +4,31 @@ package org.phoebus.alarm.logging.rest; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.junit.jupiter.api.Assertions.*; -@ExtendWith(SpringExtension.class) -@ContextConfiguration(classes = ControllersTestConfig.class) -@WebMvcTest(SearchController.class) +/** + * Unit test for {@link SearchController} using standalone MockMvc setup. + * Migrated from @WebMvcTest (removed in Spring Boot 4.x) to + * MockMvcBuilders.standaloneSetup() which requires no Spring context. + */ public class SearchControllerTest { - @Autowired private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.standaloneSetup(new SearchController()).build(); + } + @Test public void testRedirectSwagger() throws Exception { MockHttpServletRequestBuilder request = get("/swagger-ui"); From ad7a6416efab8771e93d1d20e252db3b380f73ec Mon Sep 17 00:00:00 2001 From: shroffk Date: Tue, 4 Aug 2026 15:18:54 -0400 Subject: [PATCH 04/12] now try to make save and restore to spring4.1 --- app/save-and-restore/model/pom.xml | 11 ++++++++++- services/save-and-restore/pom.xml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/save-and-restore/model/pom.xml b/app/save-and-restore/model/pom.xml index ea17f1a944..39eb262cd3 100644 --- a/app/save-and-restore/model/pom.xml +++ b/app/save-and-restore/model/pom.xml @@ -72,7 +72,16 @@ ${tools.jackson.version} - + + + org.glassfish + javax.json + 1.1.4 + + org.glassfish jakarta.json diff --git a/services/save-and-restore/pom.xml b/services/save-and-restore/pom.xml index 44d36b15b3..0928cd2d8e 100644 --- a/services/save-and-restore/pom.xml +++ b/services/save-and-restore/pom.xml @@ -14,7 +14,7 @@ 4.4 - 3.5.16 + 4.1.0 From b03359b7e90a9e470ada6f07fe8c869e6e5d4929 Mon Sep 17 00:00:00 2001 From: shroffk Date: Tue, 4 Aug 2026 15:56:56 -0400 Subject: [PATCH 05/12] start migration to new spring security API --- .../web/config/WebSecurityConfig.java | 37 ++++++++----------- .../controllers/AuthenticationController.java | 4 +- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java index fb97d28aad..5191b96815 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/config/WebSecurityConfig.java @@ -11,9 +11,11 @@ import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.ObjectPostProcessor; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; @@ -277,7 +279,7 @@ public LdapAuthoritiesPopulator authorities(BaseLdapPathContextSource contextSou */ @Bean @ConditionalOnProperty(name = "auth.impl", havingValue = "ad") - public AuthenticationManager authenticationProvider() throws Exception { + public AuthenticationManager authenticationProvider() { ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider(ad_domain, ad_url); adProvider.setConvertSubErrorCodesToExceptions(true); @@ -286,33 +288,24 @@ public AuthenticationManager authenticationProvider() throws Exception { SimpleAuthorityMapper simpleAuthorityMapper = new SimpleAuthorityMapper(); simpleAuthorityMapper.setConvertToUpperCase(true); adProvider.setAuthoritiesMapper(simpleAuthorityMapper); - return new AuthenticationManagerBuilder(new ObjectPostProcessor<>() { - @Override - public O postProcess(O object) { - return object; - } - }).authenticationProvider(adProvider).build(); + return new ProviderManager(adProvider); } /** * Created only if application property auth.impl = demo. - * @param auth Injected by Spring * @return A {@link AuthenticationManager} object - * @throws Exception on error */ @Bean @ConditionalOnProperty(name = "auth.impl", havingValue = "demo") - public AuthenticationManager demoAuthenticationManager(AuthenticationManagerBuilder auth) throws Exception { - return new AuthenticationManagerBuilder(new ObjectPostProcessor<>() { - @Override - public O postProcess(O object) { - return object; - } - }).inMemoryAuthentication() - .passwordEncoder(encoder()) - .withUser(demoAdmin).password(encoder().encode(demoAdminPassword)).roles(roleAdmin()).and() - .withUser(demoUser).password(encoder().encode(demoUserPassword)).roles(roleUser()).and() - .withUser(demoReadOnly).password(encoder().encode(demoReadOnlyPassword)).roles().and().and().build(); + public AuthenticationManager demoAuthenticationManager() { + InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager( + User.withUsername(demoAdmin).password(encoder().encode(demoAdminPassword)).roles(roleAdmin()).build(), + User.withUsername(demoUser).password(encoder().encode(demoUserPassword)).roles(roleUser()).build(), + User.withUsername(demoReadOnly).password(encoder().encode(demoReadOnlyPassword)).roles().build() + ); + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService); + provider.setPasswordEncoder(encoder()); + return new ProviderManager(provider); } /** diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/AuthenticationController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/AuthenticationController.java index 7a87af6a8e..917162bfbf 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/AuthenticationController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/AuthenticationController.java @@ -62,9 +62,7 @@ public ResponseEntity login(@RequestBody LoginCredentials loginCredent authentication = authenticationManager.authenticate(authentication); } catch (AuthenticationException e) { Logger.getLogger(AuthenticationController.class.getName()).log(Level.WARNING, "Unable to authenticate user " + loginCredentials.username(), e); - return new ResponseEntity<>( - null, - HttpStatus.UNAUTHORIZED); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } List roles = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority).collect(Collectors.toList()); From e0d2e1f1d3582debe73b7f21405223bee3621898 Mon Sep 17 00:00:00 2001 From: shroffk Date: Tue, 4 Aug 2026 16:53:42 -0400 Subject: [PATCH 06/12] updating save and restore tests for springboot 4.1 --- .../AbstractElasticsearchIT.java | 4 +-- .../impl/elasticsearch/ElasticTestConfig.java | 25 ++++++++++++++--- .../elasticsearch/ElasticsearchDAOTest.java | 10 +------ .../web/config/ControllersTestConfig.java | 7 ++++- .../AppMetaDataControllerTest.java | 21 +++++++++------ .../controllers/ComparisonControllerTest.java | 23 +++++++++------- ...positeSnapshotControllerPermitAllTest.java | 22 +++++++++------ .../CompositeSnapshotControllerTest.java | 21 +++++++++------ .../ConfigurationControllerPermitAllTest.java | 21 +++++++++------ .../ConfigurationControllerTest.java | 21 +++++++++------ .../FilterControllerPermitAllTest.java | 21 +++++++++------ .../web/controllers/FilterControllerTest.java | 21 +++++++++------ .../web/controllers/HelpResourceTest.java | 12 +-------- .../NodeControllerPermitAllTest.java | 25 ++++++++++------- .../web/controllers/NodeControllerTest.java | 25 ++++++++++------- .../web/controllers/SearchControllerTest.java | 21 +++++++++------ .../SnapshotControllerPermitAllTest.java | 23 +++++++++------- .../controllers/SnapshotControllerTest.java | 23 +++++++++------- .../SnapshotRestorerControllerTest.java | 26 ++++++++++-------- .../StructureControllerPermitAllTest.java | 23 +++++++++------- .../controllers/StructureControllerTest.java | 27 +++++++++++-------- .../TagControllerPermitAllTest.java | 21 +++++++++------ .../web/controllers/TagControllerTest.java | 21 +++++++++------ .../TakeSnapshotControllerTest.java | 23 +++++++++------- 24 files changed, 294 insertions(+), 193 deletions(-) diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/AbstractElasticsearchIT.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/AbstractElasticsearchIT.java index 1a9bd0f46f..cb10afc70e 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/AbstractElasticsearchIT.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/AbstractElasticsearchIT.java @@ -11,9 +11,9 @@ import org.phoebus.service.saveandrestore.persistence.config.ElasticConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; @@ -39,7 +39,7 @@ @SpringBootTest @ContextConfiguration(classes = ElasticConfig.class) @TestPropertySource(locations = "classpath:test_application.properties") -@Profile("IT") +@ActiveProfiles("IT") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) public abstract class AbstractElasticsearchIT { diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticTestConfig.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticTestConfig.java index 90399fb6b3..62e7c7c0f7 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticTestConfig.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticTestConfig.java @@ -2,17 +2,21 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import org.mockito.Mockito; +import org.phoebus.service.saveandrestore.search.SearchUtil; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @Configuration -@ComponentScan(basePackages = {"org.phoebus.service.saveandrestore"}) -@SuppressWarnings("unused") @Profile("!IT") +@SuppressWarnings("unused") public class ElasticTestConfig { + @Bean + public ElasticsearchDAO elasticsearchDAO() { + return new ElasticsearchDAO(); + } + @Bean({"client"}) public ElasticsearchClient getClient() { @@ -29,6 +33,21 @@ public ConfigurationDataRepository configurationDataRepository(){ return Mockito.mock(ConfigurationDataRepository.class); } + @Bean + public FilterRepository filterRepository() { + return Mockito.mock(FilterRepository.class); + } + + @Bean + public CompositeSnapshotDataRepository compositeSnapshotDataRepository() { + return Mockito.mock(CompositeSnapshotDataRepository.class); + } + + @Bean + public SearchUtil searchUtil() { + return Mockito.mock(SearchUtil.class); + } + @SuppressWarnings("unused") @Bean public SnapshotDataRepository snapshotDataRepository(){ diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticsearchDAOTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticsearchDAOTest.java index 606c9d4884..f9f44ff6b6 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticsearchDAOTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/persistence/dao/impl/elasticsearch/ElasticsearchDAOTest.java @@ -26,14 +26,9 @@ import org.phoebus.service.saveandrestore.model.ESTreeNode; import org.phoebus.service.saveandrestore.persistence.dao.impl.elasticsearch.ElasticsearchDAO.NodeNameComparator; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Profile; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; -import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import java.util.Arrays; import java.util.List; @@ -45,11 +40,8 @@ import static org.mockito.Mockito.when; @ExtendWith(SpringExtension.class) -@EnableConfigurationProperties -@ContextHierarchy({@ContextConfiguration(classes = {ElasticTestConfig.class})}) -@TestExecutionListeners({DependencyInjectionTestExecutionListener.class}) +@ContextConfiguration(classes = {ElasticTestConfig.class}) @TestPropertySource(locations = "classpath:test_application.properties") -@Profile("IT") public class ElasticsearchDAOTest { @Autowired diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java index ff61d72dbc..fe097f5eb9 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ControllersTestConfig.java @@ -43,7 +43,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + @TestConfiguration +@EnableWebMvc @ComponentScan(basePackages = "org.phoebus.service.saveandrestore.web.controllers") @SuppressWarnings("unused") @Profile("!IT") @@ -131,7 +134,9 @@ public ExecutorService executorService() { @Bean public SnapshotUtil snapshotUtil() { - return new SnapshotUtil(); + // Return a mock so tests can stub it with when(...); previously @MockBean was used + // but @MockBean was removed in Spring Boot 4.x. + return Mockito.mock(SnapshotUtil.class); } @Bean diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/AppMetaDataControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/AppMetaDataControllerTest.java index 142d9e90da..8349835d20 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/AppMetaDataControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/AppMetaDataControllerTest.java @@ -17,18 +17,18 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -41,17 +41,22 @@ * @author georgweiss * Created 16 May 2019 */ -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(AppMetaDataControllerTest.class) -@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") @SuppressWarnings("unused") public class AppMetaDataControllerTest { @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Value("${app.name}") private String appName; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java index 2069903d05..3e8e534a45 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java @@ -3,6 +3,10 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; @@ -11,7 +15,6 @@ import org.epics.vtype.Time; import org.epics.vtype.VDouble; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.applications.saveandrestore.model.ComparisonResult; import org.phoebus.applications.saveandrestore.model.CompositeSnapshotData; import org.phoebus.applications.saveandrestore.model.ConfigPv; @@ -24,11 +27,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -44,18 +44,23 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") -@WebMvcTest(ComparisonController.class) public class ComparisonControllerTest { @Autowired private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + private final ObjectMapper objectMapper = new ObjectMapper(); @Test @@ -189,4 +194,4 @@ public void testCompositeSnapshot() throws Exception{ reset(nodeDAO); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerPermitAllTest.java index bd9774840b..f1caf56b77 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerPermitAllTest.java @@ -18,11 +18,15 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.CompositeSnapshot; import org.phoebus.applications.saveandrestore.model.CompositeSnapshotData; @@ -32,12 +36,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -52,9 +52,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(CompositeSnapshotController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, + webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") public class CompositeSnapshotControllerPermitAllTest { @@ -68,8 +67,15 @@ public class CompositeSnapshotControllerPermitAllTest { private String demoUser; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + private final ObjectMapper objectMapper = new ObjectMapper(); private static CompositeSnapshot compositeSnapshot; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerTest.java index 198d9d67dd..7d3611856e 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotControllerTest.java @@ -18,13 +18,17 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.CompositeSnapshot; import org.phoebus.applications.saveandrestore.model.CompositeSnapshotData; @@ -37,12 +41,8 @@ import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.phoebus.service.saveandrestore.websocket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -60,9 +60,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(CompositeSnapshotController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") public class CompositeSnapshotControllerTest { @@ -82,8 +80,15 @@ public class CompositeSnapshotControllerTest { private String demoUser; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private WebSocketService webSocketService; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerPermitAllTest.java index 41c419497b..51221a9868 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerPermitAllTest.java @@ -18,11 +18,15 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.Configuration; import org.phoebus.applications.saveandrestore.model.ConfigurationData; @@ -32,12 +36,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -50,9 +50,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(ConfigurationController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") public class ConfigurationControllerPermitAllTest { @@ -60,8 +58,15 @@ public class ConfigurationControllerPermitAllTest { private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private ObjectMapper objectMapper; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerTest.java index 4a8e7acaed..0d546eae80 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationControllerTest.java @@ -18,11 +18,15 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.Comparison; import org.phoebus.applications.saveandrestore.model.ComparisonMode; @@ -37,12 +41,8 @@ import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.phoebus.service.saveandrestore.websocket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -58,9 +58,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(ConfigurationController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") public class ConfigurationControllerTest { @@ -68,8 +66,15 @@ public class ConfigurationControllerTest { private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private ObjectMapper objectMapper; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerPermitAllTest.java index 7e5961721a..36dd4a93f9 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerPermitAllTest.java @@ -18,22 +18,22 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.search.Filter; import org.phoebus.service.saveandrestore.persistence.dao.NodeDAO; import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -48,9 +48,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(FilterController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") public class FilterControllerPermitAllTest { @@ -58,8 +56,15 @@ public class FilterControllerPermitAllTest { private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private ObjectMapper objectMapper; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerTest.java index 9d1cc79b22..db3409dbc0 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/FilterControllerTest.java @@ -18,11 +18,15 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.search.Filter; import org.phoebus.core.websocket.common.WebSocketMessage; @@ -31,12 +35,8 @@ import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.phoebus.service.saveandrestore.websocket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -55,9 +55,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(FilterController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") public class FilterControllerTest { @@ -65,8 +63,15 @@ public class FilterControllerTest { private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private ObjectMapper objectMapper; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java index 995e84570a..a47e4e2bb5 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java @@ -20,24 +20,14 @@ import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; -import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -@ExtendWith(SpringExtension.class) -@WebMvcTest(HelpResource.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) @TestPropertySource(locations = "classpath:test_application.properties") public class HelpResourceTest{ @@ -68,4 +58,4 @@ public void testGetCheatSheetUnsupportedHelpType() throws Exception{ MockHttpServletRequestBuilder request = get("/help/unsupported"); mockMvc.perform(request).andExpect(status().isNotFound()); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerPermitAllTest.java index 9a2712ab4a..63c843df29 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerPermitAllTest.java @@ -17,23 +17,23 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.service.saveandrestore.persistence.dao.NodeDAO; import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -47,10 +47,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") -@WebMvcTest(NodeController.class) /** * Main purpose of the tests in this class is to verify that REST end points are * maintained, i.e. that URLs are not changed and that they return the correct @@ -65,8 +63,15 @@ public class NodeControllerPermitAllTest { private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + private static Node folderFromClient; private final ObjectMapper objectMapper = new ObjectMapper(); @@ -81,7 +86,7 @@ public class NodeControllerPermitAllTest { private String readOnlyAuthorization; @BeforeAll - public static void setUp() { + public static void initData() { folderFromClient = Node.builder().name("SomeFolder").userName("myusername").uniqueId("11").build(); } @@ -205,4 +210,4 @@ public void testUpdateNode() throws Exception { .content(objectMapper.writeValueAsString(node)); mockMvc.perform(request).andExpect(status().isUnauthorized()); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerTest.java index 78d22be804..e4a20111f2 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/NodeControllerTest.java @@ -17,13 +17,17 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.mockito.stubbing.Answer; import org.phoebus.applications.saveandrestore.model.Comparison; @@ -42,12 +46,8 @@ import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.phoebus.service.saveandrestore.websocket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -76,18 +76,23 @@ * * @author Georg Weiss, European Spallation Source */ -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") -@WebMvcTest(NodeController.class) public class NodeControllerTest { @Autowired private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private WebSocketService webSocketService; @@ -113,7 +118,7 @@ public class NodeControllerTest { private String readOnlyAuthorization; @BeforeAll - public static void setUp() { + public static void initData() { config1 = Node.builder().nodeType(NodeType.CONFIGURATION).uniqueId("a") .userName("myusername").build(); @@ -829,4 +834,4 @@ public void testRootNodeChildNodes() throws Exception { }); assertEquals(1, nodes.size()); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java index fe14f94b36..70262fa414 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SearchControllerTest.java @@ -18,11 +18,15 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import co.elastic.clients.elasticsearch.core.SearchRequest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.applications.saveandrestore.model.NodeType; @@ -33,11 +37,7 @@ import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -52,9 +52,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(SearchController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") public class SearchControllerTest { @@ -62,8 +60,15 @@ public class SearchControllerTest { private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private ObjectMapper objectMapper; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerPermitAllTest.java index c4ae3d0d46..869a97b253 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerPermitAllTest.java @@ -18,10 +18,14 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.mockito.stubbing.Answer; import org.phoebus.applications.saveandrestore.model.Node; @@ -31,12 +35,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -50,10 +50,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") -@WebMvcTest(SnapshotController.class) public class SnapshotControllerPermitAllTest { @Autowired @@ -68,8 +66,15 @@ public class SnapshotControllerPermitAllTest { private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private String demoUser; @@ -170,4 +175,4 @@ public void testUpdateSnapshot() throws Exception { .content(snapshotString); mockMvc.perform(request).andExpect(status().isOk()); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerTest.java index a0109e2265..9e1c4f2705 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotControllerTest.java @@ -18,11 +18,15 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.mockito.stubbing.Answer; import org.phoebus.applications.saveandrestore.model.Node; @@ -34,12 +38,8 @@ import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.phoebus.service.saveandrestore.websocket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -57,10 +57,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") -@WebMvcTest(SnapshotController.class) public class SnapshotControllerTest { @Autowired @@ -78,8 +76,15 @@ public class SnapshotControllerTest { private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private String demoUser; @@ -344,4 +349,4 @@ public void testDeleteSnapshot4() throws Exception { verify(webSocketService, times(0)).sendMessageToClients(Mockito.any(WebSocketMessage.class)); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java index ec38a0c968..1033e9be46 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java @@ -1,4 +1,9 @@ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; @@ -7,7 +12,6 @@ import org.epics.vtype.Time; import org.epics.vtype.VFloat; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.applications.saveandrestore.model.ConfigPv; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.applications.saveandrestore.model.NodeType; @@ -19,13 +23,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -40,10 +39,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") -@WebMvcTest(SnapshotRestoreController.class) public class SnapshotRestorerControllerTest { @Autowired @@ -52,14 +49,21 @@ public class SnapshotRestorerControllerTest { @Autowired private String userAuthorization; - @MockBean + @Autowired private SnapshotUtil snapshotUtil; private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Test public void testRestoreFromSnapshotNode() throws Exception { @@ -155,4 +159,4 @@ public void testRestoreFromSnapshotItems() throws Exception { new TypeReference>() { }); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerPermitAllTest.java index f12a840d8a..8329c683e9 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerPermitAllTest.java @@ -18,21 +18,21 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.service.saveandrestore.persistence.dao.NodeDAO; import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -45,18 +45,23 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") -@WebMvcTest(StructureController.class) public class StructureControllerPermitAllTest { @Autowired private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired @@ -154,4 +159,4 @@ public void testCopyNodes() throws Exception { .param("to", "target"); mockMvc.perform(request).andExpect(status().isUnauthorized()); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerTest.java index 69facdcdaa..3aae7b6772 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/StructureControllerTest.java @@ -18,25 +18,25 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; +import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.core.websocket.common.WebSocketMessage; import org.phoebus.service.saveandrestore.persistence.dao.NodeDAO; -import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; -import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.phoebus.service.saveandrestore.websocket.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -53,18 +53,23 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") -@WebMvcTest(StructureController.class) public class StructureControllerTest { @Autowired private NodeDAO nodeDAO; @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired @@ -245,4 +250,4 @@ public void testCopyNodesBadRequest3() throws Exception { verify(webSocketService, times(0)).sendMessageToClients(Mockito.any(WebSocketMessage.class)); } -} +} \ No newline at end of file diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerPermitAllTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerPermitAllTest.java index 170f0e7edc..cb5873319a 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerPermitAllTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerPermitAllTest.java @@ -18,10 +18,14 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.applications.saveandrestore.model.Tag; import org.phoebus.applications.saveandrestore.model.TagData; @@ -29,12 +33,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -48,15 +48,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(TagController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") public class TagControllerPermitAllTest { @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private NodeDAO nodeDAO; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerTest.java index 0007f740d9..3e0697a536 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TagControllerTest.java @@ -18,10 +18,14 @@ */ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.applications.saveandrestore.model.Node; import org.phoebus.applications.saveandrestore.model.Tag; import org.phoebus.applications.saveandrestore.model.TagData; @@ -29,12 +33,8 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.HttpHeaders; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -47,15 +47,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) -@WebMvcTest(TagController.class) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") public class TagControllerTest { @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Autowired private NodeDAO nodeDAO; diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotControllerTest.java index 557853734d..8ae71943a9 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotControllerTest.java @@ -1,9 +1,13 @@ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.boot.test.context.SpringBootTest; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.phoebus.applications.saveandrestore.model.ConfigPv; import org.phoebus.applications.saveandrestore.model.ConfigurationData; @@ -15,11 +19,7 @@ import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -33,10 +33,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {ControllersTestConfig.class, WebSecurityConfig.class})}) +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application_permit_all.properties") -@WebMvcTest(TakeSnapshotController.class) public class TakeSnapshotControllerTest { @Autowired @@ -47,8 +45,15 @@ public class TakeSnapshotControllerTest { private final ObjectMapper objectMapper = new ObjectMapper(); @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } + @Test public void testTakeSnapshot() throws Exception { @@ -82,4 +87,4 @@ public void testTakeSnapshotBadConfigId() throws Exception { mockMvc.perform(request).andExpect(status().isNotFound()); } -} +} \ No newline at end of file From d98fd575d4b82c1f271834025f1727c0610c9309 Mon Sep 17 00:00:00 2001 From: shroffk Date: Wed, 5 Aug 2026 10:39:37 -0400 Subject: [PATCH 07/12] use named path variables as required by springboot4 --- .../web/controllers/ComparisonController.java | 2 +- .../CompositeSnapshotController.java | 6 +++--- .../controllers/ConfigurationController.java | 2 +- .../web/controllers/HelpResource.java | 2 +- .../web/controllers/NodeController.java | 4 ++-- .../web/controllers/SnapshotController.java | 2 +- .../web/controllers/StructureController.java | 2 +- .../controllers/TakeSnapshotController.java | 4 ++-- .../web/config/WebConfigTest.java | 12 +++++------ .../web/controllers/HelpResourceTest.java | 20 +++++++++++++++++-- 10 files changed, 35 insertions(+), 21 deletions(-) diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonController.java index 24edbbba3a..4f3933caeb 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonController.java @@ -61,7 +61,7 @@ public class ComparisonController extends BaseController { * comparison evaluates to "equal" for a PV. */ @GetMapping(value = "/{nodeId}", produces = JSON) - public List compare(@PathVariable String nodeId, + public List compare(@PathVariable("nodeId") String nodeId, @RequestParam(value = "tolerance", required = false, defaultValue = "0") double tolerance, @RequestParam(value = "compareMode", required = false, defaultValue = "ABSOLUTE") ComparisonMode compareMode, @RequestParam(value = "skipReadback", required = false, defaultValue = "false") boolean skipReadback) { diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotController.java index e88e3b39ca..e7202eaaaa 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/CompositeSnapshotController.java @@ -103,7 +103,7 @@ public CompositeSnapshot updateCompositeSnapshot(@RequestBody CompositeSnapshot * @return The {@link CompositeSnapshotData} associated with the {@link CompositeSnapshot} {@link Node}. */ @GetMapping(value = "/composite-snapshot/{uniqueId}", produces = JSON) - public CompositeSnapshotData getCompositeSnapshotData(@PathVariable String uniqueId) { + public CompositeSnapshotData getCompositeSnapshotData(@PathVariable("uniqueId") String uniqueId) { return nodeDAO.getCompositeSnapshotData(uniqueId); } @@ -114,7 +114,7 @@ public CompositeSnapshotData getCompositeSnapshotData(@PathVariable String uniqu * {@link NodeType#COMPOSITE_SNAPSHOT}. */ @GetMapping(value = "/composite-snapshot/{uniqueId}/nodes", produces = JSON) - public List getCompositeSnapshotNodes(@PathVariable String uniqueId) { + public List getCompositeSnapshotNodes(@PathVariable("uniqueId") String uniqueId) { CompositeSnapshotData compositeSnapshotData = nodeDAO.getCompositeSnapshotData(uniqueId); return nodeDAO.getNodes(compositeSnapshotData.getReferencedSnapshotNodes()); } @@ -124,7 +124,7 @@ public List getCompositeSnapshotNodes(@PathVariable String uniqueId) { * @return List of {@link SnapshotItem}s contained in the referenced {@link Node}s */ @GetMapping(value = "/composite-snapshot/{uniqueId}/items", produces = JSON) - public List getCompositeSnapshotItems(@PathVariable String uniqueId) { + public List getCompositeSnapshotItems(@PathVariable("uniqueId") String uniqueId) { return nodeDAO.getSnapshotItemsFromCompositeSnapshot(uniqueId); } diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationController.java index 8194a083e7..6486a0a826 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/ConfigurationController.java @@ -91,7 +91,7 @@ public Configuration createConfiguration(@RequestParam(value = "parentNodeId") S */ @SuppressWarnings("unused") @GetMapping(value = "/{uniqueId}", produces = JSON) - public ConfigurationData getConfigurationData(@PathVariable String uniqueId) { + public ConfigurationData getConfigurationData(@PathVariable("uniqueId") String uniqueId) { return nodeDAO.getConfigurationData(uniqueId); } diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java index 64359e43db..06bac5e254 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/HelpResource.java @@ -65,7 +65,7 @@ public class HelpResource { @SuppressWarnings("unused") @GetMapping(value = "{what}", produces = CONTENT_TYPE) public String getHelpContent(@RequestParam(name = "lang", required = false) String lang, - @PathVariable String what, + @PathVariable("what") String what, HttpServletRequest request) { String language = determineLang(lang, request); String content; diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/NodeController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/NodeController.java index 1a83548bca..efe6f9b8a8 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/NodeController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/NodeController.java @@ -125,7 +125,7 @@ public List getNodes(@RequestBody List uniqueNodeIds) { */ @SuppressWarnings("unused") @GetMapping(value = "/node/{uniqueNodeId}/parent", produces = JSON) - public Node getParentNode(@PathVariable String uniqueNodeId) { + public Node getParentNode(@PathVariable("uniqueNodeId") String uniqueNodeId) { return nodeDAO.getParentNode(uniqueNodeId); } @@ -183,7 +183,7 @@ public void deleteNodes(@RequestBody List nodeIds) { @SuppressWarnings("unused") @DeleteMapping(value = "/node/{nodeId}", produces = JSON) @PreAuthorize("@authorizationHelper.mayDelete(#nodeId, #root)") - public void deleteNode(@PathVariable String nodeId) { + public void deleteNode(@PathVariable("nodeId") String nodeId) { deleteNodes(List.of(nodeId)); } diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotController.java index 6e124b9780..29ed4471c9 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotController.java @@ -57,7 +57,7 @@ public class SnapshotController extends BaseController { * @return SnapshotData object associated with #uniqueId. */ @GetMapping(value = "/snapshot/{uniqueId}", produces = JSON) - public SnapshotData getSnapshotData(@PathVariable String uniqueId) { + public SnapshotData getSnapshotData(@PathVariable("uniqueId") String uniqueId) { return nodeDAO.getSnapshotData(uniqueId); } diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/StructureController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/StructureController.java index e5fb1a0c63..2f42e76944 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/StructureController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/StructureController.java @@ -123,7 +123,7 @@ public Node copyNodes(@RequestParam(value = "to") String to, */ @SuppressWarnings("unused") @GetMapping("/path/{uniqueNodeId}") - public String getFullPath(@PathVariable String uniqueNodeId) { + public String getFullPath(@PathVariable("uniqueNodeId") String uniqueNodeId) { String fullPath = nodeDAO.getFullPath(uniqueNodeId); if (fullPath == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND); diff --git a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotController.java b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotController.java index c321e57dd6..a20f523190 100644 --- a/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotController.java +++ b/services/save-and-restore/src/main/java/org/phoebus/service/saveandrestore/web/controllers/TakeSnapshotController.java @@ -48,7 +48,7 @@ public class TakeSnapshotController extends BaseController { */ @SuppressWarnings("unused") @GetMapping(value = "/take-snapshot/{configNodeId}", produces = JSON) - public List takeSnapshot(@PathVariable String configNodeId) { + public List takeSnapshot(@PathVariable("configNodeId") String configNodeId) { Node configNode = nodeDAO.getNode(configNodeId); LOG.log(Level.INFO, "Take snapshot for configuration '" + configNode.getName() + "'"); ConfigurationData configurationData = nodeDAO.getConfigurationData(configNodeId); @@ -75,7 +75,7 @@ public List takeSnapshot(@PathVariable String configNodeId) { */ @SuppressWarnings("unused") @PutMapping(value = "/take-snapshot/{configNodeId}", produces = JSON) - public Snapshot takeSnapshotAndSave(@PathVariable String configNodeId, + public Snapshot takeSnapshotAndSave(@PathVariable("configNodeId") String configNodeId, @RequestParam(name = "name", required = false) String snapshotName, @RequestParam(name = "comment", required = false) String comment) { if (snapshotName != null) { diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/WebConfigTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/WebConfigTest.java index 67633bc4df..f597120ee5 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/WebConfigTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/WebConfigTest.java @@ -20,17 +20,15 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.phoebus.service.saveandrestore.persistence.dao.NodeDAO; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; -@ExtendWith(SpringExtension.class) -@ContextHierarchy({@ContextConfiguration(classes = {WebConfiguration.class, ControllersTestConfig.class, WebSecurityConfig.class})}) -@TestPropertySource(locations = "classpath:test_application.properties") +@SpringBootTest(classes = {WebConfiguration.class, ControllersTestConfig.class, WebSecurityConfig.class}, + webEnvironment = SpringBootTest.WebEnvironment.MOCK) +@TestPropertySource(locations = "classpath:test_application.properties", + properties = "spring.main.allow-bean-definition-overriding=true") @SuppressWarnings("unused") public class WebConfigTest { diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java index a47e4e2bb5..9ae174235a 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/HelpResourceTest.java @@ -19,20 +19,36 @@ package org.phoebus.service.saveandrestore.web.controllers; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; + +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; +import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) @TestPropertySource(locations = "classpath:test_application.properties") public class HelpResourceTest{ @Autowired - protected MockMvc mockMvc; + private WebApplicationContext webApplicationContext; + + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + } @Test public void testGetSearchHelp() throws Exception{ @@ -58,4 +74,4 @@ public void testGetCheatSheetUnsupportedHelpType() throws Exception{ MockHttpServletRequestBuilder request = get("/help/unsupported"); mockMvc.perform(request).andExpect(status().isNotFound()); } -} \ No newline at end of file +} From 18eefbe05878141e5d5c48e35663c2501ddf2729 Mon Sep 17 00:00:00 2001 From: shroffk Date: Wed, 5 Aug 2026 14:41:57 -0400 Subject: [PATCH 08/12] fix windows test for the Path calculations --- .../src/test/java/org/csstudio/display/builder/PathTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/display/model/src/test/java/org/csstudio/display/builder/PathTest.java b/app/display/model/src/test/java/org/csstudio/display/builder/PathTest.java index c045769227..0d88ba0352 100644 --- a/app/display/model/src/test/java/org/csstudio/display/builder/PathTest.java +++ b/app/display/model/src/test/java/org/csstudio/display/builder/PathTest.java @@ -56,6 +56,7 @@ public void testDirectory() } @Test + @DisabledOnOs(OS.WINDOWS) public void testCombineNotWindows() { String path = ModelResourceUtil.combineDisplayPaths(null, "example.opi"); From bc14788817af613fdabe6c9649a13a6c4c3a198c Mon Sep 17 00:00:00 2001 From: shroffk Date: Wed, 5 Aug 2026 14:42:50 -0400 Subject: [PATCH 09/12] Add the need compiler flag "-parameter" --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5acabadc98..28de983841 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,7 @@ ${maven.compiler.target} true + -parameters -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED @@ -148,7 +149,7 @@ - + org.apache.maven.plugins maven-javadoc-plugin From 52a048408f0c3a281b86ef9dca83a382249dd238 Mon Sep 17 00:00:00 2001 From: shroffk Date: Wed, 5 Aug 2026 14:45:38 -0400 Subject: [PATCH 10/12] switch some of the tests to use real SnapshotUtil --- ...nControllerRealSnapshotUtilTestConfig.java | 16 +++++++++++++ .../controllers/ComparisonControllerTest.java | 24 +++++++++++++++---- .../SnapshotRestorerControllerTest.java | 2 +- 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ComparisonControllerRealSnapshotUtilTestConfig.java diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ComparisonControllerRealSnapshotUtilTestConfig.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ComparisonControllerRealSnapshotUtilTestConfig.java new file mode 100644 index 0000000000..421dc9aa1e --- /dev/null +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/config/ComparisonControllerRealSnapshotUtilTestConfig.java @@ -0,0 +1,16 @@ +package org.phoebus.service.saveandrestore.web.config; + +import org.phoebus.saveandrestore.util.SnapshotUtil; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +@TestConfiguration +public class ComparisonControllerRealSnapshotUtilTestConfig { + + @Bean("realSnapshotUtil") + @Primary + public SnapshotUtil snapshotUtil() { + return new SnapshotUtil(); + } +} diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java index 3e8e534a45..b43dd213d1 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/ComparisonControllerTest.java @@ -24,10 +24,12 @@ import org.phoebus.applications.saveandrestore.model.SnapshotData; import org.phoebus.applications.saveandrestore.model.SnapshotItem; import org.phoebus.service.saveandrestore.persistence.dao.NodeDAO; +import org.phoebus.service.saveandrestore.web.config.ComparisonControllerRealSnapshotUtilTestConfig; import org.phoebus.service.saveandrestore.web.config.ControllersTestConfig; import org.phoebus.service.saveandrestore.web.config.WebSecurityConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -44,8 +46,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest(classes = {ControllersTestConfig.class, WebSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK) +@SpringBootTest( + classes = {ControllersTestConfig.class, WebSecurityConfig.class}, + webEnvironment = SpringBootTest.WebEnvironment.MOCK, + properties = "spring.main.allow-bean-definition-overriding=true") @TestPropertySource(locations = "classpath:test_application.properties") +@Import(ComparisonControllerRealSnapshotUtilTestConfig.class) public class ComparisonControllerTest { @Autowired @@ -99,7 +105,8 @@ public void testSingleSnapshot() throws Exception { ConfigPv configPv2 = new ConfigPv(); configPv2.setPvName("loc://y(771.0)"); - when(nodeDAO.getParentNode("nodeId")).thenReturn(Node.builder().nodeType(NodeType.CONFIGURATION).uniqueId("configId").build()); + when(nodeDAO.getParentNode("nodeId")).thenReturn(Node.builder().nodeType(NodeType.CONFIGURATION) + .uniqueId("configId").build()); ConfigurationData configurationData = new ConfigurationData(); configurationData.setUniqueId("configId"); @@ -125,10 +132,13 @@ public void testSingleSnapshot() throws Exception { MvcResult result = mockMvc.perform(request).andExpect(status().isOk()).andExpect(content().contentType(JSON)) .andReturn(); + String responseBody = result.getResponse().getContentAsString(); + List compareResults = - objectMapper.readValue(result.getResponse().getContentAsString(), + objectMapper.readValue(responseBody, new TypeReference<>() { }); + assertEquals(2, compareResults.size()); compareResults.forEach(cr -> assertTrue(cr.isEqual())); @@ -140,6 +150,7 @@ public void testSingleSnapshot() throws Exception { public void testCompositeSnapshot() throws Exception{ when(nodeDAO.getNode("nodeId")). thenReturn(Node.builder().uniqueId("nodeId").nodeType(NodeType.COMPOSITE_SNAPSHOT).build()); + CompositeSnapshotData compositeSnapshotData = new CompositeSnapshotData(); compositeSnapshotData.setReferencedSnapshotNodes(List.of("id1", "id2")); when(nodeDAO.getCompositeSnapshotData("nodeId")).thenReturn(compositeSnapshotData); @@ -184,14 +195,17 @@ public void testCompositeSnapshot() throws Exception{ MvcResult result = mockMvc.perform(request).andExpect(status().isOk()).andExpect(content().contentType(JSON)) .andReturn(); + String responseBody = result.getResponse().getContentAsString(); + List compareResults = - objectMapper.readValue(result.getResponse().getContentAsString(), + objectMapper.readValue(responseBody, new TypeReference<>() { }); + assertEquals(2, compareResults.size()); compareResults.forEach(cr -> assertTrue(cr.isEqual())); reset(nodeDAO); } -} \ No newline at end of file +} diff --git a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java index 1033e9be46..6fc16f1981 100644 --- a/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java +++ b/services/save-and-restore/src/test/java/org/phoebus/service/saveandrestore/web/controllers/SnapshotRestorerControllerTest.java @@ -159,4 +159,4 @@ public void testRestoreFromSnapshotItems() throws Exception { new TypeReference>() { }); } -} \ No newline at end of file +} From 16ad5dad68f4c41aca2072a4d92394fd2f451972 Mon Sep 17 00:00:00 2001 From: shroffk Date: Thu, 6 Aug 2026 14:09:33 -0400 Subject: [PATCH 11/12] upgrade springdoc version --- dependencies/phoebus-target/pom.xml | 22 +++++++++++----------- pom.xml | 1 + services/alarm-logger/pom.xml | 23 +++++++++++++++++------ services/save-and-restore/pom.xml | 2 +- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/dependencies/phoebus-target/pom.xml b/dependencies/phoebus-target/pom.xml index e0abdbc8e3..465cdc7d7f 100644 --- a/dependencies/phoebus-target/pom.xml +++ b/dependencies/phoebus-target/pom.xml @@ -12,8 +12,8 @@ - release @@ -60,7 +60,7 @@ - org.phoebus @@ -481,10 +481,10 @@ - org.springdoc - springdoc-openapi-ui - 1.7.0 - + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + javax.validation @@ -500,7 +500,7 @@ - + org.slf4j slf4j-jdk14 1.7.28 @@ -551,7 +551,7 @@ epics-jackie-client 3.1.0 - + @@ -570,7 +570,7 @@ bcprov-jdk18on 1.84 - + org.apache.poi @@ -610,7 +610,7 @@ tika-core 3.2.0 - + io.fair-acc diff --git a/pom.xml b/pom.xml index 28de983841..cef83da960 100644 --- a/pom.xml +++ b/pom.xml @@ -99,6 +99,7 @@ 1.26.1 5.3.22 2.7.18 + 3.1.0 diff --git a/services/alarm-logger/pom.xml b/services/alarm-logger/pom.xml index 8f85792902..457a882f32 100644 --- a/services/alarm-logger/pom.xml +++ b/services/alarm-logger/pom.xml @@ -62,16 +62,27 @@ kafka-clients ${kafka.version} - - org.elasticsearch.client - elasticsearch-rest-client-sniffer - ${elasticsearch.version} - co.elastic.clients elasticsearch-java ${elasticsearch.version} + + + org.apache.httpcomponents.client5 + httpclient5 + 5.2.3 + + + org.apache.httpcomponents.core5 + httpcore5 + 5.2.4 + + + org.apache.httpcomponents.core5 + httpcore5-h2 + 5.2.4 + tools.jackson.core jackson-databind @@ -144,7 +155,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - 2.8.17 + ${springdoc.version} diff --git a/services/save-and-restore/pom.xml b/services/save-and-restore/pom.xml index 0928cd2d8e..1e48b038ce 100644 --- a/services/save-and-restore/pom.xml +++ b/services/save-and-restore/pom.xml @@ -54,7 +54,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - 2.8.17 + ${springdoc.version} From f75352fcabdfd0bcff46c7199d1587c95dd59505 Mon Sep 17 00:00:00 2001 From: shroffk Date: Thu, 6 Aug 2026 14:17:41 -0400 Subject: [PATCH 12/12] updating the elastic client to 9.4.4 --- .../alarm/logging/AlarmMessageLogger.java | 12 +- .../alarm/logging/ElasticClientHelper.java | 283 +++++++++++------- .../logging/rest/AlarmLogSearchUtil.java | 158 ++++++++-- .../alarm/logging/rest/SearchController.java | 9 +- 4 files changed, 322 insertions(+), 140 deletions(-) diff --git a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/AlarmMessageLogger.java b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/AlarmMessageLogger.java index 8e29dc51e5..0885c90c75 100644 --- a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/AlarmMessageLogger.java +++ b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/AlarmMessageLogger.java @@ -57,7 +57,7 @@ public class AlarmMessageLogger implements Runnable { * Create a alarm logger for the alarm messages (both state and configuration) * for a given alarm server topic. * This runnable will create the kafka streams for the given alarm messages which match the format 'topic' - * + * * @param topic - the alarm topic in kafka */ public AlarmMessageLogger(String topic) { @@ -189,9 +189,9 @@ public long extract(ConsumerRecord record, long previousTimestam alarms.split(Named.as("alarm-")) .branch((k, v) -> k.startsWith("state"), - Branched.withConsumer(alarmStateStream -> processAlarmStateStream(alarmStateStream))) + Branched.withConsumer(this::processAlarmStateStream)) .branch((k, v) -> k.startsWith("config"), - Branched.withConsumer(alarmConfigStream -> processAlarmConfigurationStream(alarmConfigStream))) + Branched.withConsumer(this::processAlarmConfigurationStream)) .defaultBranch(Branched.withConsumer(stream -> { // Log each unmatched key in the default branch stream.foreach((k, v) -> logger.warning("Unknown alarm message type for key: " + k)); @@ -314,7 +314,7 @@ public void init(ProcessorContext context) { @Override public KeyValue transform(String key, AlarmMessage value) { - + key = key.replace("\\", ""); if(value != null) { AlarmConfigMessage newValue = value.getAlarmConfigMessage(); @@ -328,9 +328,9 @@ public KeyValue transform(String key, AlarmMessage v @Override public void close() { - + } - + }; } }); diff --git a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/ElasticClientHelper.java b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/ElasticClientHelper.java index d6e306e0ec..b3d1b819a1 100644 --- a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/ElasticClientHelper.java +++ b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/ElasticClientHelper.java @@ -4,24 +4,19 @@ package org.phoebus.alarm.logging; import co.elastic.clients.elasticsearch.ElasticsearchClient; -import co.elastic.clients.elasticsearch._types.Refresh; -import co.elastic.clients.elasticsearch.core.BulkRequest; -import co.elastic.clients.elasticsearch.core.BulkResponse; -import co.elastic.clients.elasticsearch.indices.ExistsIndexTemplateRequest; -import co.elastic.clients.elasticsearch.indices.PutIndexTemplateRequest; -import co.elastic.clients.elasticsearch.indices.PutIndexTemplateResponse; import co.elastic.clients.json.jackson.Jackson3JsonpMapper; import co.elastic.clients.transport.ElasticsearchTransport; -import co.elastic.clients.transport.rest_client.RestClientTransport; -import tools.jackson.databind.ObjectMapper; -import org.apache.http.Header; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.message.BasicHeader; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.sniff.Sniffer; +import co.elastic.clients.transport.rest5_client.Rest5ClientTransport; +import co.elastic.clients.transport.rest5_client.low_level.Request; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; +import co.elastic.clients.transport.rest5_client.low_level.Rest5ClientBuilder; +import co.elastic.clients.transport.rest5_client.low_level.ResponseException; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.message.BasicHeader; import org.phoebus.applications.alarm.messages.AlarmCommandMessage; import org.phoebus.applications.alarm.messages.AlarmConfigMessage; import org.phoebus.applications.alarm.messages.AlarmStateMessage; @@ -29,6 +24,9 @@ import java.io.IOException; import java.io.InputStream; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.net.URISyntaxException; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Arrays; @@ -54,14 +52,12 @@ public class ElasticClientHelper { Properties props = PropertiesHelper.getProperties(); - private static RestClient restClient; + private static Rest5Client restClient; private static ElasticsearchTransport transport; private static ElasticsearchClient client; - private static AtomicReference instance = new AtomicReference<>(); - private static Sniffer sniffer; - + private static final AtomicReference instance = new AtomicReference<>(); private static final AtomicBoolean esInitialized = new AtomicBoolean(); private static final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4); @@ -73,15 +69,14 @@ public class ElasticClientHelper { BlockingQueue> commandMessagedQueue = new LinkedBlockingDeque<>(); - private final JsonMapper mapper = new JsonMapper(); - private ElasticClientHelper() { try { Runtime.getRuntime().addShutdownHook(new Thread(() -> { logger.info("Shutting down the ElasticClientHelper."); if (client != null) { try { - client.shutdown(); + // Do not call client.shutdown() with Rest5 transport because some + // client versions assume RestClientTransport internally. transport.close(); restClient.close(); } catch (IOException ex) { @@ -97,6 +92,7 @@ private ElasticClientHelper() { HttpHost[] esHttpHosts; if (esUrls.isEmpty()) { final var http_host = new HttpHost( + "http", esHost.isEmpty() ? "localhost" : esHost, esPort.isEmpty() ? 9200 : Integer.parseInt(esPort)); esHttpHosts = new HttpHost[] {http_host}; @@ -104,12 +100,20 @@ private ElasticClientHelper() { if (!esHost.isEmpty() || !esPort.isEmpty()) { logger.warning("Only one of es_urls or es_host and es_port can be specified, ignoring es_host and es_port."); } - esHttpHosts = Arrays.stream(esUrls.split(",")).map(HttpHost::create).toArray(HttpHost[]::new); + esHttpHosts = Arrays.stream(esUrls.split(",")) + .map(url -> { + try { + return HttpHost.create(url); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid URL in es_urls: " + url, e); + } + }) + .toArray(HttpHost[]::new); } final var esAuthHeader = props.getProperty("es_auth_header", ""); final var esAuthUsername = props.getProperty("es_auth_username", ""); final var esAuthPassword = props.getProperty("es_auth_password", ""); - final var restClientBuilder = RestClient.builder(esHttpHosts); + final Rest5ClientBuilder restClientBuilder = Rest5Client.builder(esHttpHosts); if (!esAuthHeader.isEmpty()) { if (!esAuthUsername.isEmpty() || !esAuthPassword.isEmpty()) { logger.warning("Only one of es_auth_header or es_auth_username and es_auth_password can be specified. Ignoring es_auth_username and es_auth_password."); @@ -118,19 +122,20 @@ private ElasticClientHelper() { new Header[] {new BasicHeader("Authorization", esAuthHeader)}); } else if (!esAuthUsername.isEmpty() || !esAuthPassword.isEmpty()) { final var credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esAuthUsername, esAuthPassword)); + credentialsProvider.setCredentials( + new AuthScope(esHttpHosts[0]), + new UsernamePasswordCredentials(esAuthUsername, esAuthPassword.toCharArray())); restClientBuilder.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)); } restClient = restClientBuilder.build(); - transport = new RestClientTransport( + transport = new Rest5ClientTransport( restClient, - new Jackson3JsonpMapper(mapper) + new Jackson3JsonpMapper(new JsonMapper()) ); client = new ElasticsearchClient(transport); if (props.getProperty("es_sniff").equals("true")) { - sniffer = Sniffer.builder(restClient).build(); - logger.log(Level.INFO, "ES Sniff feature is enabled"); + logger.log(Level.WARNING, "es_sniff=true is ignored because Rest5Client does not support the legacy sniffer API."); } // Initialize the elastic templates esInitialized.set(!Boolean.parseBoolean(props.getProperty("es_create_templates"))); @@ -140,11 +145,15 @@ private ElasticClientHelper() { 0, 250, TimeUnit.MILLISECONDS); } catch (Exception e) { try { - job.cancel(false); - sniffer.close(); - transport.close(); - restClient.close(); - client.shutdown(); + if (job != null) { + job.cancel(false); + } + if (transport != null) { + transport.close(); + } + if (restClient != null) { + restClient.close(); + } } catch (IOException ex) { logger.log(Level.WARNING, "Failed to close the elastic client", ex); } @@ -178,6 +187,10 @@ public ElasticsearchClient getClient() { return client; } + public Rest5Client getRestClient() { + return restClient; + } + /** * Index an alarm state message * @@ -246,42 +259,89 @@ public void run() { logger.log(Level.SEVERE, "failed to create the alarm log indices ", e); } } - if (stateMessagedQueue.size() + configMessagedQueue.size() > 0) { - logger.log(Level.INFO, "batch execution of : " + stateMessagedQueue.size() + " state messages and " + configMessagedQueue.size() + " config messages"); - BulkRequest.Builder bulkRequest = new BulkRequest.Builder().refresh(Refresh.True); + int stateSize = stateMessagedQueue.size(); + int configSize = configMessagedQueue.size(); + int commandSize = commandMessagedQueue.size(); + if (stateSize + configSize + commandSize > 0) { + logger.log(Level.INFO, "batch execution of : " + stateSize + " state, " + configSize + " config, " + commandSize + " command messages"); Collection> statePairs = new ArrayList<>(); stateMessagedQueue.drainTo(statePairs); Collection> configPairs = new ArrayList<>(); configMessagedQueue.drainTo(configPairs); Collection> commandPairs = new ArrayList<>(); commandMessagedQueue.drainTo(commandPairs); - statePairs.forEach(pair -> bulkRequest.operations(op -> op - .index(idx -> idx - .index(pair.getKey().toLowerCase()) - .document(pair.getValue().sourceMap())))); - configPairs.forEach(pair -> bulkRequest.operations(op -> op - .index(idx -> idx - .index(pair.getKey().toLowerCase()) - .document(pair.getValue().sourceMap())))); - commandPairs.forEach(pair -> bulkRequest.operations(op -> op - .index(idx -> idx - .index(pair.getKey().toLowerCase()) - .document(pair.getValue().sourceMap())))); try { - BulkResponse bulkResponse = client.bulk(bulkRequest.build()); - bulkResponse.items().forEach(item -> { - if (item.error() != null) { - logger.log(Level.SEVERE, "Failed while indexing to " + item.index() + " type " - + item.operationType() + item.error().reason() + "]"); - } - } - ); + performBulkIndex(statePairs, configPairs, commandPairs); } catch (IOException e) { logger.log(Level.SEVERE, "failed to log messages to index ", e); + } catch (Exception e) { + logger.log(Level.SEVERE, "Unexpected error during bulk indexing: " + e.getClass().getName() + " - " + e.getMessage(), e); } } } + /** + * Perform bulk indexing using low-level Rest5 API to avoid media-type header issues + * with elasticsearch-java 9.x high-level client against ES 8.x backends. + */ + private void performBulkIndex(Collection> statePairs, + Collection> configPairs, + Collection> commandPairs) + throws IOException { + if (statePairs.isEmpty() && configPairs.isEmpty() && commandPairs.isEmpty()) { + return; + } + + StringBuilder bulkPayload = new StringBuilder(); + long successCount = 0L; + + // Add state pairs + for (var pair : statePairs) { + String indexName = pair.getKey().toLowerCase(); + bulkPayload.append("{\"index\":{\"_index\":\"").append(indexName).append("\"}}\n"); + String jsonDoc = ElasticClientHelper.toJson(pair.getValue().sourceMap()); + bulkPayload.append(jsonDoc).append("\n"); + successCount++; + } + + // Add config pairs + for (var pair : configPairs) { + String indexName = pair.getKey().toLowerCase(); + bulkPayload.append("{\"index\":{\"_index\":\"").append(indexName).append("\"}}\n"); + String jsonDoc = ElasticClientHelper.toJson(pair.getValue().sourceMap()); + bulkPayload.append(jsonDoc).append("\n"); + successCount++; + } + + // Add command pairs + for (var pair : commandPairs) { + String indexName = pair.getKey().toLowerCase(); + bulkPayload.append("{\"index\":{\"_index\":\"").append(indexName).append("\"}}\n"); + String jsonDoc = ElasticClientHelper.toJson(pair.getValue().sourceMap()); + bulkPayload.append(jsonDoc).append("\n"); + successCount++; + } + + if (bulkPayload.isEmpty()) { + return; + } + + Request request = new Request("POST", "/_bulk"); + request.addParameter("refresh", "true"); + request.setJsonEntity(bulkPayload.toString()); + + try { + int statusCode = restClient.performRequest(request).getStatusCode(); + if (statusCode >= 200 && statusCode < 300) { + logger.log(Level.INFO, "Bulk indexing completed successfully: " + successCount + " items indexed"); + } else { + logger.log(Level.WARNING, "Bulk indexing returned HTTP " + statusCode + " but " + successCount + " items were sent"); + } + } catch (ResponseException e) { + logger.log(Level.SEVERE, "Bulk indexing failed with HTTP " + e.getResponse().getStatusCode(), e); + } + } + private static final Properties props = new Properties(); static { @@ -303,66 +363,63 @@ public void run() { * @throws IOException if Elasticsearch interaction fails */ public void initializeIndices() throws IOException { - // Create the alarm state messages index template - boolean exists = client.indices().existsIndexTemplate(ExistsIndexTemplateRequest.of(i -> i.name(ALARM_STATE_TEMPLATE))).value(); - - if (!exists) { - try (InputStream is = ElasticClientHelper.class.getResourceAsStream("/alarms_state_template.json")) { - PutIndexTemplateRequest templateRequest = new PutIndexTemplateRequest.Builder() - .name(ALARM_STATE_TEMPLATE) - .indexPatterns(Arrays.asList(ALARM_STATE_TEMPLATE_PATTERN)) - .withJson(is) - .priority(1L) - .create(true) - .build(); - PutIndexTemplateResponse putTemplateResponse = client.indices().putIndexTemplate(templateRequest); - putTemplateResponse.acknowledged(); - logger.log(Level.INFO, "Created " + ALARM_STATE_TEMPLATE + " template."); - } catch (Exception e) { - logger.log(Level.INFO, "Failed to create template " + ALARM_STATE_TEMPLATE + " template.", e); - } - } + createTemplateIfMissing(ALARM_STATE_TEMPLATE, ALARM_STATE_TEMPLATE_PATTERN, "/alarms_state_template.json", 1L); + createTemplateIfMissing(ALARM_CMD_TEMPLATE, ALARM_CMD_TEMPLATE_PATTERN, "/alarms_cmd_template.json", 2L); + createTemplateIfMissing(ALARM_CONFIG_TEMPLATE, ALARM_CONFIG_TEMPLATE_PATTERN, "/alarms_config_template.json", 3L); + } - // Create the alarm command messages index template - exists = client.indices().existsIndexTemplate(ExistsIndexTemplateRequest.of(i -> i.name(ALARM_CMD_TEMPLATE))).value(); - - if (!exists) { - try (InputStream is = ElasticClientHelper.class.getResourceAsStream("/alarms_cmd_template.json")) { - PutIndexTemplateRequest templateRequest = new PutIndexTemplateRequest.Builder() - .name(ALARM_CMD_TEMPLATE) - .indexPatterns(Arrays.asList(ALARM_CMD_TEMPLATE_PATTERN)) - .withJson(is) - .priority(2L) - .create(true) - .build(); - PutIndexTemplateResponse putTemplateResponse = client.indices().putIndexTemplate(templateRequest); - putTemplateResponse.acknowledged(); - logger.log(Level.INFO, "Created " + ALARM_CMD_TEMPLATE + " template."); - } catch (Exception e) { - logger.log(Level.INFO, "Failed to create template " + ALARM_CMD_TEMPLATE + " template.", e); + private void createTemplateIfMissing(String templateName, + String pattern, + String resource, + long priority) { + try (InputStream is = ElasticClientHelper.class.getResourceAsStream(resource)) { + if (is == null) { + throw new IOException("Template resource not found: " + resource); } - } - - // Create the alarm config messages index template - exists = client.indices().existsIndexTemplate(ExistsIndexTemplateRequest.of(i -> i.name(ALARM_CONFIG_TEMPLATE))).value(); - - if (!exists) { - try (InputStream is = ElasticClientHelper.class.getResourceAsStream("/alarms_config_template.json")) { - PutIndexTemplateRequest templateRequest = new PutIndexTemplateRequest.Builder() - .name(ALARM_CONFIG_TEMPLATE) - .indexPatterns(Arrays.asList(ALARM_CONFIG_TEMPLATE_PATTERN)) - .withJson(is) - .priority(3L) - .create(true) - .build(); - PutIndexTemplateResponse putTemplateResponse = client.indices().putIndexTemplate(templateRequest); - putTemplateResponse.acknowledged(); - logger.log(Level.INFO, "Created " + ALARM_CONFIG_TEMPLATE + " template."); - } catch (Exception e) { - logger.log(Level.INFO, "Failed to create template " + ALARM_CONFIG_TEMPLATE + " template.", e); + final String templateJson = new String(is.readAllBytes(), StandardCharsets.UTF_8).trim(); + final String payload = toComposableTemplatePayload(templateJson, pattern, priority); + final String endpoint = "/_index_template/" + URLEncoder.encode(templateName, StandardCharsets.UTF_8); + + Request request = new Request("PUT", endpoint); + request.addParameter("create", "true"); + request.setJsonEntity(payload); + + int statusCode = restClient.performRequest(request).getStatusCode(); + if (statusCode >= 200 && statusCode < 300) { + logger.log(Level.INFO, "Created " + templateName + " template."); + } else { + logger.log(Level.WARNING, "Template creation returned HTTP " + statusCode + " for " + templateName + "."); + } + } catch (ResponseException e) { + if (e.getResponse().getStatusCode() == 409) { + logger.log(Level.FINE, "Template " + templateName + " already exists."); + return; } + logger.log(Level.INFO, "Failed to create template " + templateName + " template.", e); + } catch (Exception e) { + logger.log(Level.INFO, "Failed to create template " + templateName + " template.", e); } } + + /** + * Builds a composable template payload by combining existing template JSON + * content with runtime index pattern and priority. + */ + private String toComposableTemplatePayload(String templateJson, String pattern, long priority) throws IOException { + String trimmed = templateJson.trim(); + if (!trimmed.startsWith("{")) { + throw new IOException("Invalid template JSON content."); + } + String escapedPattern = pattern.replace("\\", "\\\\").replace("\"", "\\\""); + return "{\"index_patterns\":[\"" + escapedPattern + "\"],\"priority\":" + priority + "," + trimmed.substring(1); + } + } + + /** + * Serialize a map to JSON string using the mapper. + */ + static String toJson(java.util.Map map) { + return new tools.jackson.databind.json.JsonMapper().writeValueAsString(map); } } diff --git a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/AlarmLogSearchUtil.java b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/AlarmLogSearchUtil.java index a3393cebfe..80a3427bd6 100644 --- a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/AlarmLogSearchUtil.java +++ b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/AlarmLogSearchUtil.java @@ -10,7 +10,8 @@ import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery; import co.elastic.clients.elasticsearch._types.query_dsl.WildcardQuery; import co.elastic.clients.elasticsearch.core.SearchRequest; -import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.transport.rest5_client.low_level.Request; +import co.elastic.clients.transport.rest5_client.low_level.Rest5Client; import tools.jackson.core.JacksonException; import tools.jackson.databind.JsonNode; import tools.jackson.databind.ObjectMapper; @@ -70,10 +71,12 @@ public class AlarmLogSearchUtil { * Find all the log (state and config) messages which match the search criteria * * @param client elastic client + * @param restClient low-level Rest5Client for performing requests * @param searchParameters search parameters * @return list of alarm state and config messages */ public static List search(ElasticsearchClient client, + Rest5Client restClient, Map searchParameters) { logger.fine("searching for alarm log entires : " + searchParameters.entrySet().stream().map(e -> e.getKey() + ": " + e.getValue()).collect(Collectors.joining())); @@ -276,16 +279,53 @@ public static List search(ElasticsearchClient client, } SearchRequest searchRequest = searchRequestBuilder.build(); try { - SearchResponse strResponse = client.search(searchRequest, JsonNode.class); - return strResponse.hits().hits().stream().map(hit -> { - JsonNode jsonNode = hit.source(); + // Build the search request body as JSON for low-level API + String requestBody = buildSearchJson(searchRequest); + + // Determine the target indices + String indexParam = indexList.isEmpty() ? "" : String.join(",", indexList); + String endpoint = indexParam.isEmpty() ? "/_search" : "/" + indexParam + "/_search"; + + logger.fine("Search endpoint: " + endpoint); + logger.fine("Search body: " + requestBody); + + // Execute search via low-level API (use POST for requests with body) + Request request = new Request("POST", endpoint); + request.setJsonEntity(requestBody); + var response = restClient.performRequest(request); + + if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) { + // Parse the response + JsonNode responseJson = mapper.readTree(response.getEntity().getContent()); + JsonNode hits = responseJson.get("hits").get("hits"); + + List results = new ArrayList<>(); + if (hits.isArray()) { + for (JsonNode hit : hits) { + JsonNode source = hit.get("_source"); + if (source != null) { + try { + results.add(mapper.treeToValue(source, AlarmLogMessage.class)); + } catch (JacksonException e) { + logger.log(Level.SEVERE, "Failed to parse the searched alarm log messages. " + source, e); + } + } + } + } + return results; + } else { + // Log the error response body + String errorBody = ""; try { - return mapper.treeToValue(jsonNode, AlarmLogMessage.class); - } catch (JacksonException e) { - logger.log(Level.SEVERE, "Failed to parse the searched alarm log messages. " + hit, e); + errorBody = new String(response.getEntity().getContent().readAllBytes()); + } catch (Exception e) { + logger.log(Level.WARNING, "Could not read error response body", e); } - return null; - }).collect(Collectors.toList()); + logger.log(Level.SEVERE, "Search failed with status code: " + response.getStatusCode() + + "\nEndpoint: " + endpoint + + "\nRequest body: " + requestBody + + "\nError response: " + errorBody); + } } catch (IOException e) { logger.log(Level.SEVERE, "Failed to search for alarm logs ", e); } @@ -296,10 +336,13 @@ public static List search(ElasticsearchClient client, * Return the latest alarm config message associated with 'config' * * @param client elastic client + * @param restClient low-level Rest5Client for performing requests * @param allRequestParams the wildcard pattern which matches the 'config' * @return last alarm config message for the given 'config' */ - public static List searchConfig(ElasticsearchClient client, Map allRequestParams) { + public static List searchConfig(ElasticsearchClient client, + Rest5Client restClient, + Map allRequestParams) { String configString = allRequestParams.get("config"); // Determine which alarm config to specify as Elasticsearch index, convert to lower case as // indices are created using lower case. @@ -323,16 +366,50 @@ public static List searchConfig(ElasticsearchClient client, Map ); try { - SearchResponse strResponse = client.search(searchRequest, JsonNode.class); - return strResponse.hits().hits().stream().map(hit -> { - JsonNode jsonNode = hit.source(); + // Build the search request body as JSON for low-level API + String requestBody = buildSearchJson(searchRequest); + String endpoint = "/" + alarmConfig + "_alarms_config_*/_search"; + + logger.fine("Search config endpoint: " + endpoint); + logger.fine("Search config body: " + requestBody); + + // Execute search via low-level API (use POST for requests with body) + Request request = new Request("POST", endpoint); + request.setJsonEntity(requestBody); + var response = restClient.performRequest(request); + + if (response.getStatusCode() >= 200 && response.getStatusCode() < 300) { + // Parse the response + JsonNode responseJson = mapper.readTree(response.getEntity().getContent()); + JsonNode hits = responseJson.get("hits").get("hits"); + + List results = new ArrayList<>(); + if (hits.isArray()) { + for (JsonNode hit : hits) { + JsonNode source = hit.get("_source"); + if (source != null) { + try { + results.add(mapper.treeToValue(source, AlarmLogMessage.class)); + } catch (JacksonException e) { + logger.log(Level.SEVERE, "Failed to parse the searched alarm config messages. " + source, e); + } + } + } + } + return results; + } else { + // Log the error response body + String errorBody = ""; try { - return mapper.treeToValue(jsonNode, AlarmLogMessage.class); - } catch (JacksonException e) { - logger.log(Level.SEVERE, "Failed to parse the searched alarm config messages. " + hit, e); + errorBody = new String(response.getEntity().getContent().readAllBytes()); + } catch (Exception e) { + logger.log(Level.WARNING, "Could not read error response body", e); } - return null; - }).collect(Collectors.toList()); + logger.log(Level.SEVERE, "Search config failed with status code: " + response.getStatusCode() + + "\nEndpoint: " + endpoint + + "\nRequest body: " + requestBody + + "\nError response: " + errorBody); + } } catch (IOException e) { logger.log(Level.SEVERE, "Failed to search for alarm config logs ", e); } @@ -394,4 +471,49 @@ public static int getDateSpanInDays(String indexDateSpanUnits){ return -1; } } + + /** + * Helper method to convert SearchRequest to JSON string for low-level API + * This works by using Jackson to serialize the SearchRequest object tree to JSON + * NOTE: We exclude 'index' from the JSON since indices are specified in the URL path + */ + private static String buildSearchJson(SearchRequest searchRequest) throws IOException { + // Serialize the entire request first to get all fields + String fullJson = mapper.writeValueAsString(searchRequest); + JsonNode fullNode = mapper.readTree(fullJson); + + // Build a new JSON object with only the fields Elasticsearch expects in the body + Map searchBody = new java.util.LinkedHashMap<>(); + + // Query - only include if present + if (fullNode.has("query") && !fullNode.get("query").isNull()) { + searchBody.put("query", mapper.convertValue(fullNode.get("query"), Object.class)); + } + + // Size - only include if present + if (fullNode.has("size") && !fullNode.get("size").isNull()) { + searchBody.put("size", fullNode.get("size").asInt()); + } + + // Sort - only include if present + if (fullNode.has("sort") && !fullNode.get("sort").isNull() && fullNode.get("sort").isArray()) { + searchBody.put("sort", mapper.convertValue(fullNode.get("sort"), Object.class)); + } + + String result = mapper.writeValueAsString(searchBody); + logger.fine("Built search JSON: " + result); + return result; + } + + private static Object toMap(Query query) throws IOException { + // Serialize the Query object to a map via JSON round-trip + String json = mapper.writeValueAsString(query); + return mapper.readValue(json, Object.class); + } + + private static List toList(java.util.List list) throws IOException { + // Serialize the list to map via JSON round-trip + String json = mapper.writeValueAsString(list); + return mapper.readValue(json, List.class); + } } diff --git a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java index 33141d0048..ebde1f3efe 100644 --- a/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java +++ b/services/alarm-logger/src/main/java/org/phoebus/alarm/logging/rest/SearchController.java @@ -98,7 +98,8 @@ public String info() { }) @RequestMapping(value = "/search/alarm", method = RequestMethod.GET) public List search(@Parameter(hidden = true) @RequestParam Map allRequestParams) { - List result = AlarmLogSearchUtil.search(ElasticClientHelper.getInstance().getClient(), allRequestParams); + List result = AlarmLogSearchUtil.search(ElasticClientHelper.getInstance().getClient(), + ElasticClientHelper.getInstance().getRestClient(), allRequestParams); return result; } @@ -107,7 +108,8 @@ public List search(@Parameter(hidden = true) @RequestParam Map< public List searchPv(@Parameter(name="pv", description = "PV name") @PathVariable String pv) { Map searchParameters = new HashMap<>(); searchParameters.put("pv", pv); - List result = AlarmLogSearchUtil.search(ElasticClientHelper.getInstance().getClient(), searchParameters); + List result = AlarmLogSearchUtil.search(ElasticClientHelper.getInstance().getClient(), + ElasticClientHelper.getInstance().getRestClient(), searchParameters); return result; } @@ -124,7 +126,8 @@ public List searchConfig(@Parameter(hidden = true) @RequestPara allRequestParams.get("config").isEmpty()) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST); } - List result = AlarmLogSearchUtil.searchConfig(ElasticClientHelper.getInstance().getClient(), allRequestParams); + List result = AlarmLogSearchUtil.searchConfig(ElasticClientHelper.getInstance().getClient(), + ElasticClientHelper.getInstance().getRestClient(), allRequestParams); return result; }