From fef20284ea9fa567c2135b5f4e32e4c03af8ab4b Mon Sep 17 00:00:00 2001 From: Stephan Krusche Date: Mon, 2 Dec 2024 22:01:02 +0100 Subject: [PATCH] Development: Update Spring Boot to 3.4.0 (#9852) --- build.gradle | 54 +++++++---------- docs/dev/guidelines/server-tests.rst | 14 ++--- gradle.properties | 8 ++- .../buildagent/BuildAgentConfiguration.java | 4 +- ...on.java => EurekaClientConfiguration.java} | 37 +++++++----- .../core/config/LiquibaseConfiguration.java | 4 +- .../config/RestTemplateConfiguration.java | 5 -- .../communication/PostingServiceUnitTest.java | 4 +- ...InternalAuthenticationIntegrationTest.java | 8 +-- .../UserJenkinsGitlabIntegrationTest.java | 2 +- .../connector/GitlabRequestMockProvider.java | 4 ++ .../connector/JenkinsRequestMockProvider.java | 11 ++-- ...ountResourceWithGitLabIntegrationTest.java | 3 +- .../aet/artemis/exam/ExamIntegrationTest.java | 2 +- .../ExamParticipationIntegrationTest.java | 2 +- .../artemis/exam/ExamUserIntegrationTest.java | 2 +- .../exam/StudentExamIntegrationTest.java | 2 +- .../ParticipationIntegrationTest.java | 4 +- .../service/ParticipationServiceTest.java | 2 +- ...ogrammingIntegrationJenkinsGitlabTest.java | 4 -- ...encyCheckGitlabJenkinsIntegrationTest.java | 2 +- .../CourseGitlabJenkinsIntegrationTest.java | 2 +- ...gExerciseGitlabJenkinsIntegrationTest.java | 2 +- ...gExerciseIntegrationJenkinsGitlabTest.java | 2 +- ...rammingExerciseIntegrationTestService.java | 14 ++--- ...ammingExerciseTemplateIntegrationTest.java | 4 +- .../programming/ProgrammingExerciseTest.java | 4 +- ...AndResultGitlabJenkinsIntegrationTest.java | 2 +- .../ProgrammingSubmissionIntegrationTest.java | 16 ++--- .../icl/LocalVCInfoContributorTest.java | 4 +- .../JenkinsAuthorizationInterceptorTest.java | 2 +- .../JenkinsJobPermissionServiceTest.java | 2 +- .../service/JenkinsJobServiceTest.java | 2 +- .../service/JenkinsServiceTest.java | 2 +- .../util/ProgrammingExerciseTestService.java | 2 +- .../base/AbstractArtemisIntegrationTest.java | 58 +++++++++---------- ...ringIntegrationGitlabCIGitlabSamlTest.java | 17 +++--- ...tractSpringIntegrationIndependentTest.java | 10 ++-- ...actSpringIntegrationJenkinsGitlabTest.java | 21 ++++--- ...ctSpringIntegrationLocalCILocalVCTest.java | 18 +++--- 40 files changed, 176 insertions(+), 186 deletions(-) rename src/main/java/de/tum/cit/aet/artemis/core/config/{EurekaClientRestTemplateConfiguration.java => EurekaClientConfiguration.java} (52%) diff --git a/build.gradle b/build.gradle index 8c830f0784f8..618553ed0366 100644 --- a/build.gradle +++ b/build.gradle @@ -212,17 +212,16 @@ repositories { maven { url "https://build.shibboleth.net/maven/releases" } - // required for latest jgit 7.0.0 dependency - // TODO: remove this when jgit is available in the official maven repository + // TODO: remove this when spring cloud is available in the official maven repository maven { - url "https://repo.eclipse.org/content/repositories/jgit-releases" + url "https://repo.spring.io/milestone" } } ext["jackson.version"] = fasterxml_version ext["junit-jupiter.version"] = junit_version -ext { qDoxVersionReusable = "com.thoughtworks.qdox:qdox:2.1.0" } +ext { qDoxVersionReusable = "com.thoughtworks.qdox:qdox:2.2.0" } ext { springBootStarterWeb = "org.springframework.boot:spring-boot-starter-web:${spring_boot_version}" } dependencies { @@ -231,9 +230,8 @@ dependencies { // implementation "com.offbytwo.jenkins:jenkins-client:0.3.8" implementation files("libs/jenkins-client-0.4.1.jar") // The following 4 dependencies are explicitly integrated as transitive dependencies of jenkins-client-0.4.0.jar - // NOTE: we cannot upgrade to the latest version for org.apache.httpcomponents because of exceptions in Docker Java - implementation "org.apache.httpcomponents.client5:httpclient5:5.3.1" // also used by Docker Java - implementation "org.apache.httpcomponents.core5:httpcore5:5.2.5" + implementation "org.apache.httpcomponents.client5:httpclient5:5.4.1" + implementation "org.apache.httpcomponents.core5:httpcore5:5.3.1" implementation "org.apache.httpcomponents:httpmime:4.5.14" implementation("org.dom4j:dom4j:2.1.4") { // Note: avoid org.xml.sax.SAXNotRecognizedException: unrecognized feature http://xml.org/sax/features/external-general-entities @@ -246,7 +244,7 @@ dependencies { exclude module: "jaxb-api" } - implementation "org.gitlab4j:gitlab4j-api:6.0.0-rc.6" + implementation "org.gitlab4j:gitlab4j-api:6.0.0-rc.7" implementation "de.jplag:jplag:${jplag_version}" @@ -268,7 +266,7 @@ dependencies { implementation "org.apache.lucene:lucene-queryparser:${lucene_version}" implementation "org.apache.lucene:lucene-core:${lucene_version}" implementation "org.apache.lucene:lucene-analyzers-common:${lucene_version}" - implementation "com.google.protobuf:protobuf-java:4.28.3" + implementation "com.google.protobuf:protobuf-java:4.29.0" // we have to override those values to use the latest version implementation "org.slf4j:jcl-over-slf4j:${slf4j_version}" @@ -279,7 +277,7 @@ dependencies { } } - implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.1" + implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.2" // Note: spring-security-lti13 does not work with jakarta yet, so we built our own custom version and declare its transitive dependencies below // implementation "uk.ac.ox.ctl:spring-security-lti13:0.1.11" @@ -327,7 +325,7 @@ dependencies { // required by Saml2 implementation "org.apache.santuario:xmlsec:4.0.3" - implementation "org.jsoup:jsoup:1.18.1" + implementation "org.jsoup:jsoup:1.18.2" implementation "commons-codec:commons-codec:1.17.1" // needed for spring security saml2 // TODO: decide if we want to use OpenAPI and Swagger v3 @@ -335,16 +333,18 @@ dependencies { // implementation "org.springdoc:springdoc-openapi-ui:1.8.0" // use the latest version to avoid security vulnerabilities - implementation "org.springframework:spring-webmvc:6.1.14" + implementation "org.springframework:spring-webmvc:${spring_framework_version}" implementation "com.vdurmont:semver4j:3.1.0" implementation "com.github.docker-java:docker-java-core:${docker_java_version}" - implementation "com.github.docker-java:docker-java-transport-httpclient5:${docker_java_version}" + // Note: we explicitly use docker-java-transport-zerodep, because docker-java-transport-httpclient5 uses an outdated http5 version which is not compatible with Spring Boot >= 3.4.0 + implementation "com.github.docker-java:docker-java-transport-zerodep:${docker_java_version}" // use newest version of commons-compress to avoid security issues through outdated dependencies implementation "org.apache.commons:commons-compress:1.27.1" + // import JHipster dependencies BOM implementation platform("tech.jhipster:jhipster-dependencies:${jhipster_dependencies_version}") @@ -403,24 +403,19 @@ dependencies { implementation "org.springframework.boot:spring-boot-starter-oauth2-client:${spring_boot_version}" implementation "org.springframework.ldap:spring-ldap-core:3.2.8" - implementation "org.springframework.data:spring-data-ldap:3.3.5" + implementation "org.springframework.data:spring-data-ldap:3.4.0" - implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:4.1.3") { + implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:${spring_cloud_version}") { // NOTE: these modules contain security vulnerabilities and are not needed exclude module: "commons-jxpath" exclude module: "woodstox-core" } - implementation "org.springframework.cloud:spring-cloud-starter-config:4.1.3" - implementation "org.springframework.cloud:spring-cloud-commons:4.1.4" + implementation "org.springframework.cloud:spring-cloud-starter-config:${spring_cloud_version}" + implementation "org.springframework.cloud:spring-cloud-commons:${spring_cloud_version}" + implementation "io.netty:netty-all:4.1.115.Final" implementation "io.projectreactor.netty:reactor-netty:1.2.0" - implementation("io.netty:netty-common") { - version { - strictly netty_version - } - } - - implementation "org.springframework:spring-messaging:6.1.14" + implementation "org.springframework:spring-messaging:${spring_framework_version}" implementation "org.springframework.retry:spring-retry:2.0.10" implementation "org.springframework.security:spring-security-config:${spring_security_version}" @@ -428,7 +423,6 @@ dependencies { implementation "org.springframework.security:spring-security-core:${spring_security_version}" implementation "org.springframework.security:spring-security-oauth2-core:${spring_security_version}" implementation "org.springframework.security:spring-security-oauth2-client:${spring_security_version}" - implementation "org.springframework.security:spring-security-oauth2-resource-server:${spring_security_version}" // use newest version of nimbus-jose-jwt to avoid security issues through outdated dependencies implementation "com.nimbusds:nimbus-jose-jwt:9.47" @@ -547,18 +541,10 @@ dependencies { testImplementation "org.gradle:gradle-tooling-api:8.11.1" testImplementation "org.apache.maven.surefire:surefire-report-parser:3.5.2" testImplementation "com.opencsv:opencsv:5.9" - testImplementation("io.zonky.test:embedded-database-spring-test:2.5.1") { + testImplementation("io.zonky.test:embedded-database-spring-test:2.6.0") { exclude group: "org.testcontainers", module: "mariadb" exclude group: "org.testcontainers", module: "mssqlserver" } - testImplementation "org.testcontainers:testcontainers:${testcontainer_version}" - testImplementation "org.testcontainers:mysql:${testcontainer_version}" - testImplementation "org.testcontainers:postgresql:${testcontainer_version}" - testImplementation "org.testcontainers:testcontainers:${testcontainer_version}" - testImplementation "org.testcontainers:junit-jupiter:${testcontainer_version}" - testImplementation "org.testcontainers:jdbc:${testcontainer_version}" - testImplementation "org.testcontainers:database-commons:${testcontainer_version}" - testImplementation "com.tngtech.archunit:archunit:1.3.0" testImplementation("org.skyscreamer:jsonassert:1.5.3") { exclude module: "android-json" diff --git a/docs/dev/guidelines/server-tests.rst b/docs/dev/guidelines/server-tests.rst index 1e95860b8064..ef2b61d586a4 100644 --- a/docs/dev/guidelines/server-tests.rst +++ b/docs/dev/guidelines/server-tests.rst @@ -151,19 +151,19 @@ Follow these tips to write performant tests: * Limit object creation in tests and the test setup. -6. Avoid using @MockBean -========================= +6. Avoid using @MockitoBean +=========================== -Do not use the ``@SpyBean`` or ``@MockBean`` annotation unless absolutely necessary or possibly in an abstract Superclass. `Here `__ you can see why in more detail. -Whenever``@MockBean`` appears in a class, the application context cache gets marked as dirty, meaning the runner will clean the cache after finishing the test class. The application context is restarted, which leads to an additional server start with runtime overhead. +Do not use the ``@MockitoSpyBean`` or ``@MockitoBean`` annotation unless absolutely necessary or possibly in an abstract Superclass. `Here `__ you can see why in more detail. +Whenever``@MockitoBean`` appears in a class, the application context cache gets marked as dirty, meaning the runner will clean the cache after finishing the test class. The application context is restarted, which leads to an additional server start with runtime overhead. We want to keep the number of server starts minimal. -Below is an example of how to replace a ``@SpyBean``. To test an edge case where an ``IOException`` is thrown, we mocked the service method so it threw an Exception. +Below is an example of how to replace a ``@MockitoSpyBean``. To test an edge case where an ``IOException`` is thrown, we mocked the service method so it threw an Exception. .. code-block:: java class TestExport extends AbstractSpringIntegrationIndependentTest { - @SpyBean + @MockitoSpyBean private FileUploadSubmissionExportService fileUploadSubmissionExportService; @Test @@ -174,7 +174,7 @@ Below is an example of how to replace a ``@SpyBean``. To test an edge case where } } -To avoid new SpyBeans, we now use `static mocks `__. Upon examining the ``export()`` method, we find a ``File.newOutputStream(..)`` call. +To avoid new MockitoSpyBeans, we now use `static mocks `__. Upon examining the ``export()`` method, we find a ``File.newOutputStream(..)`` call. Now, instead of mocking the whole service, we can mock the static method: .. code-block:: java diff --git a/gradle.properties b/gradle.properties index b234044bcc8f..d3efd6837318 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,6 +9,10 @@ npm_version=10.8.0 jhipster_dependencies_version=8.7.2 spring_boot_version=3.3.6 spring_security_version=6.3.5 +spring_boot_version=3.4.0 +spring_framework_version=6.2.0 +spring_cloud_version=4.2.0-RC1 +spring_security_version=6.4.1 # TODO: upgrading to 6.6.0 currently leads to issues due to internal changes in Hibernate and potentially wrong use in Artemis server code hibernate_version=6.4.10.Final # TODO: can we update to 5.x? @@ -16,7 +20,7 @@ opensaml_version=4.3.2 jwt_version=0.12.6 jaxb_runtime_version=4.0.5 hazelcast_version=5.5.0 -fasterxml_version=2.18.1 +fasterxml_version=2.18.2 jgit_version=7.0.0.202409031743-r sshd_version=2.14.0 checkstyle_version=10.20.1 @@ -25,7 +29,7 @@ jplag_version=5.1.0 # NOTE: we do not need to use the latest version 9.x here as long as Stanford CoreNLP does not reference it lucene_version=8.11.4 slf4j_version=2.0.16 -sentry_version=7.18.0 +sentry_version=7.18.1 liquibase_version=4.30.0 docker_java_version=3.4.0 logback_version=1.5.12 diff --git a/src/main/java/de/tum/cit/aet/artemis/buildagent/BuildAgentConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/buildagent/BuildAgentConfiguration.java index b58d6dbd2fa8..186ca2433639 100644 --- a/src/main/java/de/tum/cit/aet/artemis/buildagent/BuildAgentConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/buildagent/BuildAgentConfiguration.java @@ -23,8 +23,8 @@ import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.DockerClientImpl; -import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; import com.github.dockerjava.transport.DockerHttpClient; +import com.github.dockerjava.zerodep.ZerodepDockerHttpClient; import com.google.common.util.concurrent.ThreadFactoryBuilder; import de.tum.cit.aet.artemis.core.config.ProgrammingLanguageConfiguration; @@ -151,7 +151,7 @@ public ExecutorService localCIBuildExecutorService() { public DockerClient dockerClient() { log.debug("Create bean dockerClient"); DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost(dockerConnectionUri).build(); - DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder().dockerHost(config.getDockerHost()).sslConfig(config.getSSLConfig()).build(); + DockerHttpClient httpClient = new ZerodepDockerHttpClient.Builder().dockerHost(config.getDockerHost()).sslConfig(config.getSSLConfig()).build(); DockerClient dockerClient = DockerClientImpl.getInstance(config, httpClient); log.debug("Docker client created with connection URI: {}", dockerConnectionUri); diff --git a/src/main/java/de/tum/cit/aet/artemis/core/config/EurekaClientRestTemplateConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/core/config/EurekaClientConfiguration.java similarity index 52% rename from src/main/java/de/tum/cit/aet/artemis/core/config/EurekaClientRestTemplateConfiguration.java rename to src/main/java/de/tum/cit/aet/artemis/core/config/EurekaClientConfiguration.java index b66038d20469..26634548eb3b 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/config/EurekaClientRestTemplateConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/config/EurekaClientConfiguration.java @@ -8,38 +8,42 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.configuration.SSLContextFactory; import org.springframework.cloud.configuration.TlsProperties; +import org.springframework.cloud.netflix.eureka.RestClientTimeoutProperties; +import org.springframework.cloud.netflix.eureka.http.DefaultEurekaClientHttpRequestFactorySupplier; import org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; -import org.springframework.cloud.netflix.eureka.http.RestTemplateDiscoveryClientOptionalArgs; -import org.springframework.cloud.netflix.eureka.http.RestTemplateTransportClientFactories; +import org.springframework.cloud.netflix.eureka.http.RestClientDiscoveryClientOptionalArgs; +import org.springframework.cloud.netflix.eureka.http.RestClientTransportClientFactories; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +import org.springframework.web.client.RestClient; /** * This class is necessary to avoid using Jersey (which has an issue deserializing Eureka responses) after the spring boot upgrade. - * It provides the RestTemplateTransportClientFactories and RestTemplateDiscoveryClientOptionalArgs that would normally not be instantiated + * It provides the RestClientTransportClientFactories and RestClientDiscoveryClientOptionalArgs that would normally not be instantiated * when Jersey is found by Eureka. */ @Profile({ PROFILE_CORE, PROFILE_BUILDAGENT }) @Configuration -public class EurekaClientRestTemplateConfiguration { +public class EurekaClientConfiguration { - private static final Logger log = LoggerFactory.getLogger(EurekaClientRestTemplateConfiguration.class); + private static final Logger log = LoggerFactory.getLogger(EurekaClientConfiguration.class); /** - * Configures and returns {@link RestTemplateDiscoveryClientOptionalArgs} for Eureka client communication, + * Configures and returns {@link RestClientDiscoveryClientOptionalArgs} for Eureka client communication, * with optional TLS/SSL setup based on provided configuration. *

- * This method leverages the {@link EurekaClientHttpRequestFactorySupplier} to configure the RestTemplate + * This method leverages the {@link EurekaClientHttpRequestFactorySupplier} to configure the RestClient * specifically for Eureka client interactions. If TLS is enabled in the provided {@link TlsProperties}, * a custom SSLContext is set up to ensure secure communication. *

* - * @param tlsProperties The TLS configuration properties, used to check if TLS is enabled and to configure it accordingly. - * @param eurekaClientHttpRequestFactorySupplier Supplies the HTTP request factory for the Eureka client RestTemplate. - * @return A configured instance of {@link RestTemplateDiscoveryClientOptionalArgs} for Eureka client, + * @param tlsProperties The TLS configuration properties, used to check if TLS is enabled and to configure it accordingly. + * @param restClientBuilderProvider The provider for the {@link RestClient.Builder} instance, if available. + * @return A configured instance of {@link RestClientDiscoveryClientOptionalArgs} for Eureka client, * potentially with SSL/TLS enabled if specified in the {@code tlsProperties}. * @throws GeneralSecurityException If there's an issue with setting up the SSL/TLS context. * @throws IOException If there's an I/O error during the setup. @@ -47,12 +51,13 @@ public class EurekaClientRestTemplateConfiguration { * @see EurekaClientHttpRequestFactorySupplier */ @Bean - public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(TlsProperties tlsProperties, - EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) throws GeneralSecurityException, IOException { - log.debug("Using RestTemplate for the Eureka client."); + public RestClientDiscoveryClientOptionalArgs restClientDiscoveryClientOptionalArgs(TlsProperties tlsProperties, ObjectProvider restClientBuilderProvider) + throws GeneralSecurityException, IOException { + log.debug("Using RestClient for the Eureka client."); // The Eureka DiscoveryClientOptionalArgsConfiguration invokes a private method setupTLS. // This code is taken from that method. - var args = new RestTemplateDiscoveryClientOptionalArgs(eurekaClientHttpRequestFactorySupplier); + var supplier = new DefaultEurekaClientHttpRequestFactorySupplier(new RestClientTimeoutProperties()); + var args = new RestClientDiscoveryClientOptionalArgs(supplier, () -> restClientBuilderProvider.getIfAvailable(RestClient::builder)); if (tlsProperties.isEnabled()) { SSLContextFactory factory = new SSLContextFactory(tlsProperties); args.setSSLContext(factory.createSSLContext()); @@ -61,7 +66,7 @@ public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOption } @Bean - public RestTemplateTransportClientFactories restTemplateTransportClientFactories(RestTemplateDiscoveryClientOptionalArgs optionalArgs) { - return new RestTemplateTransportClientFactories(optionalArgs); + public RestClientTransportClientFactories restClientTransportClientFactories(RestClientDiscoveryClientOptionalArgs optionalArgs) { + return new RestClientTransportClientFactories(optionalArgs); } } diff --git a/src/main/java/de/tum/cit/aet/artemis/core/config/LiquibaseConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/core/config/LiquibaseConfiguration.java index 5aa0b02bcc36..5a0847aeedcb 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/config/LiquibaseConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/config/LiquibaseConfiguration.java @@ -75,14 +75,14 @@ public SpringLiquibase liquibase(@LiquibaseDataSource ObjectProvider SpringLiquibase liquibase = SpringLiquibaseUtil.createSpringLiquibase(liquibaseDataSource.getIfAvailable(), liquibaseProperties, dataSource, dataSourceProperties); Scope.setScopeManager(new SingletonScopeManager()); liquibase.setChangeLog("classpath:config/liquibase/master.xml"); - liquibase.setContexts(liquibaseProperties.getContexts()); + liquibase.setContexts(liquibaseProperties.getContexts() != null ? liquibaseProperties.getContexts().getFirst() : null); liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema()); liquibase.setLiquibaseSchema(liquibaseProperties.getLiquibaseSchema()); liquibase.setLiquibaseTablespace(liquibaseProperties.getLiquibaseTablespace()); liquibase.setDatabaseChangeLogLockTable(liquibaseProperties.getDatabaseChangeLogLockTable()); liquibase.setDatabaseChangeLogTable(liquibaseProperties.getDatabaseChangeLogTable()); liquibase.setDropFirst(liquibaseProperties.isDropFirst()); - liquibase.setLabelFilter(liquibaseProperties.getLabelFilter()); + liquibase.setLabelFilter(liquibaseProperties.getLabelFilter() != null ? liquibaseProperties.getLabelFilter().getFirst() : null); liquibase.setChangeLogParameters(liquibaseProperties.getParameters()); liquibase.setRollbackFile(liquibaseProperties.getRollbackFile()); liquibase.setTestRollbackOnUpdate(liquibaseProperties.isTestRollbackOnUpdate()); diff --git a/src/main/java/de/tum/cit/aet/artemis/core/config/RestTemplateConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/core/config/RestTemplateConfiguration.java index 0730267fb379..922e3f072f23 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/config/RestTemplateConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/config/RestTemplateConfiguration.java @@ -9,7 +9,6 @@ import jakarta.validation.constraints.NotNull; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -43,14 +42,12 @@ public class RestTemplateConfiguration { @Bean @Profile("gitlab | gitlabci") - @Autowired // ok public RestTemplate gitlabRestTemplate(GitLabAuthorizationInterceptor gitlabInterceptor) { return initializeRestTemplateWithInterceptors(gitlabInterceptor, createRestTemplate()); } @Bean @Profile("jenkins") - @Autowired // ok public RestTemplate jenkinsRestTemplate(JenkinsAuthorizationInterceptor jenkinsInterceptor) { return initializeRestTemplateWithInterceptors(jenkinsInterceptor, createRestTemplate()); } @@ -89,14 +86,12 @@ public RestTemplate pyrisRestTemplate(PyrisAuthorizationInterceptor pyrisAuthori @Bean @Profile("gitlab | gitlabci") - @Autowired // ok public RestTemplate shortTimeoutGitlabRestTemplate(GitLabAuthorizationInterceptor gitlabInterceptor) { return initializeRestTemplateWithInterceptors(gitlabInterceptor, createShortTimeoutRestTemplate()); } @Bean @Profile("jenkins") - @Autowired // ok public RestTemplate shortTimeoutJenkinsRestTemplate(JenkinsAuthorizationInterceptor jenkinsInterceptor) { return initializeRestTemplateWithInterceptors(jenkinsInterceptor, createShortTimeoutRestTemplate()); } diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/PostingServiceUnitTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/PostingServiceUnitTest.java index 554da34e0c7f..ced0b420a7a7 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/PostingServiceUnitTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/PostingServiceUnitTest.java @@ -157,7 +157,7 @@ void testParseUserMentionsWithNonExistentUser() { void testParseUserMentionsWithInvalidName() { Course course = new Course(); String content = "[user]Test User 2(test_user_1)[/user]"; - User user = this.createUser("Test User 1", "test_user_1"); // Different name than mentioned + User user = createUser("Test User 1", "test_user_1"); // Different name than mentioned setupUserRepository(Set.of("test_user_1"), Set.of(user)); when(authorizationCheckService.isAtLeastStudentInCourse(eq(course), any(User.class))).thenReturn(true); @@ -169,7 +169,7 @@ void testParseUserMentionsWithInvalidName() { void testParseUserMentionsWithUserNotInCourse() { Course course = new Course(); String content = "[user]Test User 1(test_user_1)[/user]"; - User user = this.createUser("Test User 1", "test_user_1"); + User user = createUser("Test User 1", "test_user_1"); setupUserRepository(Set.of("test_user_1"), Set.of(user)); when(authorizationCheckService.isAtLeastStudentInCourse(eq(course), any(User.class))).thenReturn(false); diff --git a/src/test/java/de/tum/cit/aet/artemis/core/authentication/InternalAuthenticationIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/core/authentication/InternalAuthenticationIntegrationTest.java index 7ade409a5287..3a756bd65ede 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/authentication/InternalAuthenticationIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/authentication/InternalAuthenticationIntegrationTest.java @@ -37,12 +37,12 @@ import de.tum.cit.aet.artemis.core.security.SecurityUtils; import de.tum.cit.aet.artemis.core.service.user.PasswordService; import de.tum.cit.aet.artemis.core.util.CourseFactory; -import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise; import de.tum.cit.aet.artemis.programming.test_repository.ProgrammingExerciseTestRepository; import de.tum.cit.aet.artemis.programming.util.ProgrammingExerciseUtilService; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationJenkinsGitlabTest; import de.tum.cit.aet.artemis.tutorialgroup.util.TutorialGroupUtilService; +// TODO: rewrite this test to use LocalVC instead of GitLab class InternalAuthenticationIntegrationTest extends AbstractSpringIntegrationJenkinsGitlabTest { private static final String TEST_PREFIX = "internalauth"; @@ -81,17 +81,13 @@ class InternalAuthenticationIntegrationTest extends AbstractSpringIntegrationJen private static final String USERNAME = TEST_PREFIX + "student1"; - private ProgrammingExercise programmingExercise; - @BeforeEach void setUp() { - jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer); + jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer, jenkinsJobPermissionsService); userUtilService.addUsers(TEST_PREFIX, 1, 0, 0, 0); Course course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); courseUtilService.addOnlineCourseConfigurationToCourse(course); - programmingExercise = exerciseUtilService.getFirstExerciseWithType(course, ProgrammingExercise.class); - programmingExercise = programmingExerciseRepository.findWithEagerStudentParticipationsById(programmingExercise.getId()).orElseThrow(); final var userAuthority = new Authority(Role.STUDENT.getAuthority()); final var instructorAuthority = new Authority(Role.INSTRUCTOR.getAuthority()); diff --git a/src/test/java/de/tum/cit/aet/artemis/core/authentication/UserJenkinsGitlabIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/core/authentication/UserJenkinsGitlabIntegrationTest.java index b302e83631f5..50ff7b932516 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/authentication/UserJenkinsGitlabIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/authentication/UserJenkinsGitlabIntegrationTest.java @@ -66,7 +66,7 @@ class UserJenkinsGitlabIntegrationTest extends AbstractSpringIntegrationJenkinsG void setUp() throws Exception { userTestService.setup(TEST_PREFIX, this); gitlabRequestMockProvider.enableMockingOfRequests(); - jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer); + jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer, jenkinsJobPermissionsService); } @AfterEach diff --git a/src/test/java/de/tum/cit/aet/artemis/core/connector/GitlabRequestMockProvider.java b/src/test/java/de/tum/cit/aet/artemis/core/connector/GitlabRequestMockProvider.java index 6ac2c36c00db..c551387bdb68 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/connector/GitlabRequestMockProvider.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/connector/GitlabRequestMockProvider.java @@ -108,6 +108,8 @@ @Component @Profile("gitlab") +// Gitlab support will be removed in 8.0.0. Please migrate to LocalVC using e.g. the PR https://github.com/ls1intum/Artemis/pull/8972 +@Deprecated(since = "7.5.0", forRemoval = true) public class GitlabRequestMockProvider { private static final Logger log = LoggerFactory.getLogger(GitlabRequestMockProvider.class); @@ -129,6 +131,7 @@ public class GitlabRequestMockProvider { private MockRestServiceServer mockServerShortTimeout; + // NOTE: we currently cannot convert this into @MockitoSpyBean because then @InjectMocks doesn't work @SpyBean @InjectMocks private GitLabApi gitLabApi; @@ -154,6 +157,7 @@ public class GitlabRequestMockProvider { @Mock private PipelineApi pipelineApi; + // NOTE: we currently cannot convert this into @MockitoSpyBean because then @InjectMocks (see above) doesn't work @SpyBean private GitLabUserManagementService gitLabUserManagementService; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/connector/JenkinsRequestMockProvider.java b/src/test/java/de/tum/cit/aet/artemis/core/connector/JenkinsRequestMockProvider.java index 827953bc0b68..2adaa451e563 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/connector/JenkinsRequestMockProvider.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/connector/JenkinsRequestMockProvider.java @@ -22,12 +22,10 @@ import org.apache.http.client.HttpResponseException; import org.hamcrest.Matchers; -import org.mockito.InjectMocks; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Profile; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -70,12 +68,10 @@ public class JenkinsRequestMockProvider { private MockRestServiceServer shortTimeoutMockServer; - @SpyBean - @InjectMocks + // will be assigned in enableMockingOfRequests(), can be used like a MockitoSpyBean private JenkinsServer jenkinsServer; - @SpyBean - @InjectMocks + // will be assigned in enableMockingOfRequests(), can be used like a MockitoSpyBean private JenkinsJobPermissionsService jenkinsJobPermissionsService; @Autowired @@ -98,10 +94,11 @@ public JenkinsRequestMockProvider(@Qualifier("jenkinsRestTemplate") RestTemplate this.shortTimeoutRestTemplate.setInterceptors(List.of()); } - public void enableMockingOfRequests(JenkinsServer jenkinsServer) { + public void enableMockingOfRequests(JenkinsServer jenkinsServer, JenkinsJobPermissionsService jenkinsJobPermissionsService) { mockServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).bufferContent().build(); shortTimeoutMockServer = MockRestServiceServer.bindTo(shortTimeoutRestTemplate).ignoreExpectOrder(true).bufferContent().build(); this.jenkinsServer = jenkinsServer; + this.jenkinsJobPermissionsService = jenkinsJobPermissionsService; closeable = MockitoAnnotations.openMocks(this); } diff --git a/src/test/java/de/tum/cit/aet/artemis/core/user/AccountResourceWithGitLabIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/core/user/AccountResourceWithGitLabIntegrationTest.java index ea8267af3d4e..6c2f0472be45 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/user/AccountResourceWithGitLabIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/user/AccountResourceWithGitLabIntegrationTest.java @@ -24,6 +24,7 @@ import de.tum.cit.aet.artemis.core.user.util.UserFactory; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationJenkinsGitlabTest; +// TODO: rewrite this test to use LocalVC instead of GitLab class AccountResourceWithGitLabIntegrationTest extends AbstractSpringIntegrationJenkinsGitlabTest { @Autowired @@ -32,7 +33,7 @@ class AccountResourceWithGitLabIntegrationTest extends AbstractSpringIntegration @BeforeEach void setUp() { gitlabRequestMockProvider.enableMockingOfRequests(); - jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer); + jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer, jenkinsJobPermissionsService); } @AfterEach diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java index 52f93e2d6741..e86f315c26fc 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java @@ -991,7 +991,7 @@ void testDeleteExamWithOneTestRuns() throws Exception { @WithMockUser(username = TEST_PREFIX + "instructor1", roles = "INSTRUCTOR") void testDeleteExamWithMultipleTestRuns() throws Exception { gitlabRequestMockProvider.enableMockingOfRequests(); - jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer); + jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer, jenkinsJobPermissionsService); var exam = examUtilService.addExam(course1); exam = examUtilService.addTextModelingProgrammingExercisesToExam(exam, true, true); diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java index ec49d8ec78a7..c0bf3576b18b 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java @@ -756,7 +756,7 @@ private void lockAndAssessForSecondCorrection(Exam exam, Course course, List