Skip to content

Commit 45d9b33

Browse files
authored
Development: Update server dependencies (#10956)
1 parent a6e1f17 commit 45d9b33

21 files changed

+133
-88
lines changed

build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ plugins {
2121
id "com.google.cloud.tools.jib" version "3.4.5"
2222
id "com.gorylenko.gradle-git-properties" version "2.5.0"
2323
id "io.spring.dependency-management" version "1.1.7"
24-
id "nebula.lint" version "20.5.8"
24+
id "nebula.lint" version "20.6.0"
2525
id "org.liquibase.gradle" version "${liquibase_plugin_version}"
2626
id "org.owasp.dependencycheck" version "12.1.1"
2727
id "org.springframework.boot" version "${spring_boot_version}"
@@ -269,7 +269,7 @@ dependencies {
269269
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${fasterxml_version}"
270270

271271
// Avoid outdated version of netty to prevent security issues
272-
implementation("net.minidev:json-smart") { version { strictly "2.5.2" } }
272+
implementation("net.minidev:json-smart") { version {strictly "2.5.2" } }
273273

274274

275275
// Required for synchronization between nodes and build agents (LocalCI)
@@ -316,7 +316,7 @@ dependencies {
316316
implementation "org.springframework.ldap:spring-ldap-core:3.3.0"
317317

318318
implementation "org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:${spring_cloud_version}"
319-
implementation "org.springframework.cloud:spring-cloud-starter-config:4.2.2"
319+
implementation "org.springframework.cloud:spring-cloud-starter-config:${spring_cloud_version}"
320320
implementation "org.springframework.cloud:spring-cloud-commons:${spring_cloud_version}"
321321

322322
// required by the Websocket Broker Connection in WebsocketConfiguration (due to multi node setup support)
@@ -359,7 +359,7 @@ dependencies {
359359
implementation "org.bouncycastle:bcprov-jdk18on:1.80"
360360

361361
implementation "com.mysql:mysql-connector-j:${mysql_version}"
362-
implementation "org.postgresql:postgresql:42.7.5"
362+
implementation "org.postgresql:postgresql:42.7.6"
363363

364364
implementation "org.zalando:problem-spring-web:0.29.1"
365365
implementation "org.zalando:jackson-datatype-problem:0.27.1"

gradle.properties

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ npm_version=10.9.2
77

88
# Dependency versions
99
jhipster_dependencies_version=8.11.0
10-
spring_boot_version=3.4.6
10+
spring_boot_version=3.5.0
1111
spring_framework_version=6.2.7
12-
spring_cloud_version=4.2.1
12+
spring_cloud_version=4.3.0
1313
spring_security_version=6.5.0
1414
# TODO: upgrading to 6.6.x currently leads to issues due to internal changes in Hibernate and potentially wrong use in Artemis server code. See https://hibernate.atlassian.net/browse/HHH-19249
1515
hibernate_version=6.5.3.Final
@@ -26,7 +26,7 @@ jplag_version=6.1.0
2626
# NOTE: we cannot need to use the latest version 9.x or 10.x here as long as Stanford CoreNLP does not reference it
2727
lucene_version=8.11.4
2828
slf4j_version=2.0.17
29-
sentry_version=8.12.0
29+
sentry_version=8.13.2
3030
liquibase_version=4.32.0
3131
docker_java_version=3.5.1
3232
logback_version=1.5.18
@@ -38,8 +38,8 @@ micrometer_version=1.15.0
3838

3939
# testing
4040
# make sure both versions are compatible
41-
junit_version=5.12.2
42-
junit_platform_version=1.12.2
41+
junit_version=5.13.0
42+
junit_platform_version=1.13.0
4343
mockito_version=5.18.0
4444
testcontainer_version=1.20.4
4545

@@ -48,7 +48,7 @@ gradle_node_plugin_version=7.1.0
4848
apt_plugin_version=0.21
4949
liquibase_plugin_version=3.0.2
5050
modernizer_plugin_version=1.11.0
51-
spotless_plugin_version=7.0.3
51+
spotless_plugin_version=7.0.4
5252

5353
org.gradle.jvmargs=-Xmx2g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en \
5454
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \

src/main/java/de/tum/cit/aet/artemis/athena/config/AthenaHealthIndicator.java

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
import org.springframework.stereotype.Component;
1414
import org.springframework.web.client.RestTemplate;
1515

16-
import com.fasterxml.jackson.databind.JsonNode;
17-
1816
import de.tum.cit.aet.artemis.core.service.connectors.ConnectorHealth;
1917

2018
/**
@@ -30,18 +28,8 @@ public class AthenaHealthIndicator implements HealthIndicator {
3028

3129
private static final String ATHENA_URL_KEY = "url";
3230

33-
private static final String ATHENA_STATUS_KEY = "status";
34-
35-
private static final String ATHENA_MODULES_KEY = "modules";
36-
3731
private static final String ATHENA_ASSESSMENT_MODULE_MANAGER_KEY = "assessment module manager";
3832

39-
private static final String ATHENA_MODULE_URL_KEY = "url";
40-
41-
private static final String ATHENA_MODULE_EXERCISE_TYPE_KEY = "type";
42-
43-
private static final String ATHENA_MODULE_HEALTHY_KEY = "healthy";
44-
4533
private final RestTemplate shortTimeoutRestTemplate;
4634

4735
@Value("${artemis.athena.url}")
@@ -69,12 +57,12 @@ public Health health() {
6957
additionalInfo.put(ATHENA_URL_KEY, athenaUrl);
7058
ConnectorHealth health;
7159
try {
72-
final var response = shortTimeoutRestTemplate.getForObject(athenaUrl + "/health", JsonNode.class);
73-
final var athenaStatus = response != null ? response.get(ATHENA_STATUS_KEY).asText() : null;
60+
final var healthResponse = shortTimeoutRestTemplate.getForObject(athenaUrl + "/health", AthenaHealthResponse.class);
61+
final var athenaStatus = healthResponse != null ? healthResponse.status() : null;
7462

7563
if (athenaStatus != null) {
7664
additionalInfo.put(ATHENA_ASSESSMENT_MODULE_MANAGER_KEY, athenaStatus);
77-
additionalInfo.putAll(getAdditionalInfoForModules(response));
65+
additionalInfo.putAll(getAdditionalInfoForModules(healthResponse));
7866
}
7967
else {
8068
additionalInfo.put(ATHENA_ASSESSMENT_MODULE_MANAGER_KEY, "not available");
@@ -91,17 +79,13 @@ public Health health() {
9179
/**
9280
* Get additional information about the health of the assessment modules.
9381
*/
94-
private Map<String, Object> getAdditionalInfoForModules(JsonNode athenaHealthResponse) {
82+
private Map<String, Object> getAdditionalInfoForModules(AthenaHealthResponse athenaHealthResponse) {
9583
var additionalModuleInfo = new HashMap<String, Object>();
96-
if (athenaHealthResponse.has(ATHENA_MODULES_KEY)) {
97-
JsonNode modules = athenaHealthResponse.get(ATHENA_MODULES_KEY);
98-
// keys are module names, values are description maps
99-
modules.fields().forEachRemaining(module -> {
100-
var moduleHealth = new AthenaModuleHealth(module.getValue().get(ATHENA_MODULE_EXERCISE_TYPE_KEY).asText(),
101-
module.getValue().get(ATHENA_MODULE_HEALTHY_KEY).asBoolean(), module.getValue().get(ATHENA_MODULE_URL_KEY).asText());
102-
additionalModuleInfo.put(module.getKey(), moduleHealthToString(moduleHealth));
103-
});
104-
}
84+
var modules = athenaHealthResponse.modules();
85+
modules.forEach((moduleName, descriptionMap) -> {
86+
var moduleHealth = new AthenaModuleHealth(descriptionMap.type(), descriptionMap.healthy(), descriptionMap.url());
87+
additionalModuleInfo.put(moduleName, moduleHealthToString(moduleHealth));
88+
});
10589
return additionalModuleInfo;
10690
}
10791
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package de.tum.cit.aet.artemis.athena.config;
2+
3+
import java.util.Map;
4+
5+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
6+
import com.fasterxml.jackson.annotation.JsonInclude;
7+
8+
@JsonIgnoreProperties(ignoreUnknown = true)
9+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
10+
public record AthenaHealthResponse(String status, Map<String, ModuleHealth> modules) {
11+
12+
public record ModuleHealth(String url, String type, boolean healthy, boolean supportsEvaluation, boolean supportsNonGradedFeedbackRequests,
13+
boolean supportsGradedFeedbackRequests) {
14+
}
15+
}

src/main/java/de/tum/cit/aet/artemis/communication/repository/ConversationMessageRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private Specification<Post> configureSearchSpecification(Specification<Post> spe
7070
* @return returns a Page of Messages
7171
*/
7272
default Page<Post> findMessages(PostContextFilterDTO postContextFilter, Pageable pageable, long userId) {
73-
var specification = Specification.where(getConversationsSpecification(postContextFilter.conversationIds()));
73+
var specification = getConversationsSpecification(postContextFilter.conversationIds());
7474
specification = configureSearchSpecification(specification, postContextFilter, userId);
7575
// Fetch all necessary attributes to avoid lazy loading (even though relations are defined as EAGER in the domain class, specification queries do not respect this)
7676
return findPostsWithSpecification(pageable, specification);

src/main/java/de/tum/cit/aet/artemis/communication/repository/MessageSpecs.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import jakarta.persistence.criteria.JoinType;
1010
import jakarta.persistence.criteria.Order;
1111
import jakarta.persistence.criteria.Predicate;
12+
import jakarta.validation.constraints.NotNull;
1213

1314
import org.apache.commons.lang3.StringUtils;
1415
import org.springframework.data.jpa.domain.Specification;
@@ -42,12 +43,15 @@ public static Specification<Post> getSearchTextAndAuthorSpecification(String sea
4243
return (root, query, criteriaBuilder) -> {
4344
boolean hasText = searchText != null && !searchText.isBlank();
4445
boolean hasAuthors = authorIds != null && authorIds.length > 0;
46+
// no author ids and no search text means no filtering
4547
if (!hasText && !hasAuthors) {
4648
return null;
4749
}
50+
// if only a search text is given, use the search text specification
4851
if (hasText && !hasAuthors) {
4952
return getSearchTextSpecification(searchText).toPredicate(root, query, criteriaBuilder);
5053
}
54+
// if only author ids are given, use the author specification
5155
if (!hasText && hasAuthors) {
5256
return getAuthorSpecification(authorIds).toPredicate(root, query, criteriaBuilder);
5357
}
@@ -74,6 +78,7 @@ public static Specification<Post> getSearchTextAndAuthorSpecification(String sea
7478
* @param searchText Text to be searched within messages
7579
* @return specification used to chain DB operations
7680
*/
81+
@NotNull
7782
public static Specification<Post> getSearchTextSpecification(String searchText) {
7883
return ((root, query, criteriaBuilder) -> {
7984
if (searchText == null || searchText.isBlank()) {
@@ -103,6 +108,7 @@ else if (searchText.startsWith("#") && StringUtils.isNumeric(searchText.substrin
103108
* @param conversationIds ids of the conversation messages belong to
104109
* @return specification used to chain DB operations
105110
*/
111+
@NotNull
106112
public static Specification<Post> getConversationsSpecification(long[] conversationIds) {
107113
return ((root, query, criteriaBuilder) -> {
108114
if (conversationIds == null || conversationIds.length == 0) {
@@ -121,6 +127,7 @@ public static Specification<Post> getConversationsSpecification(long[] conversat
121127
* @param courseId id of course the posts belong to
122128
* @return specification used to chain DB operations
123129
*/
130+
@NotNull
124131
public static Specification<Post> getCourseWideChannelsSpecification(boolean filterToCourseWide, Long courseId) {
125132
return (root, query, criteriaBuilder) -> {
126133
if (!filterToCourseWide) {
@@ -142,6 +149,7 @@ public static Specification<Post> getCourseWideChannelsSpecification(boolean fil
142149
* @param authorIds ids of the post authors
143150
* @return specification used to chain DB operations
144151
*/
152+
@NotNull
145153
public static Specification<Post> getAuthorSpecification(long[] authorIds) {
146154
return ((root, query, criteriaBuilder) -> {
147155
if (authorIds == null || authorIds.length == 0) {
@@ -164,6 +172,7 @@ public static Specification<Post> getAuthorSpecification(long[] authorIds) {
164172
* @param userId id of the calling user
165173
* @return specification used to chain DB operations
166174
*/
175+
@NotNull
167176
public static Specification<Post> getAnsweredOrReactedSpecification(boolean answeredOrReacted, Long userId) {
168177
return ((root, query, criteriaBuilder) -> {
169178
if (!answeredOrReacted) {
@@ -190,6 +199,7 @@ public static Specification<Post> getAnsweredOrReactedSpecification(boolean answ
190199
* @param unresolved whether only the Posts without resolving answers should be fetched or not
191200
* @return specification used to chain DB operations
192201
*/
202+
@NotNull
193203
public static Specification<Post> getUnresolvedSpecification(boolean unresolved) {
194204
return ((root, query, criteriaBuilder) -> {
195205
if (!unresolved) {
@@ -218,9 +228,10 @@ public static Specification<Post> getUnresolvedSpecification(boolean unresolved)
218228
* @param sortingOrder direction of sorting (ASC, DESC)
219229
* @return specification used to chain DB operations
220230
*/
231+
@NotNull
221232
public static Specification<Post> getSortSpecification(boolean pagingEnabled, PostSortCriterion postSortCriterion, SortingOrder sortingOrder) {
222233
return ((root, query, criteriaBuilder) -> {
223-
if (pagingEnabled && postSortCriterion != null && sortingOrder != null) {
234+
if (pagingEnabled && postSortCriterion != null && sortingOrder != null && query != null) {
224235

225236
List<Order> orderList = new ArrayList<>();
226237

@@ -246,9 +257,12 @@ public static Specification<Post> getSortSpecification(boolean pagingEnabled, Po
246257
* incompatible with each other at server tests
247258
* <a href="https://github.com/h2database/h2database/issues/408">...</a>
248259
*/
260+
@NotNull
249261
public static Specification<Post> distinct() {
250262
return (root, query, criteriaBuilder) -> {
251-
query.groupBy(root.get(Post_.ID));
263+
if (query != null) {
264+
query.groupBy(root.get(Post_.ID));
265+
}
252266
return null;
253267
};
254268
}
@@ -259,6 +273,7 @@ public static Specification<Post> distinct() {
259273
* @param pinnedOnly whether only pinned posts should be fetched
260274
* @return specification used to chain DB operations
261275
*/
276+
@NotNull
262277
public static Specification<Post> getPinnedSpecification(boolean pinnedOnly) {
263278
return (root, query, criteriaBuilder) -> {
264279
if (!pinnedOnly) {

src/main/java/de/tum/cit/aet/artemis/core/repository/UserRepository.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,9 @@ default Page<UserDTO> getAllManagedUsers(UserPageableSearchDTO userSearch) {
786786
var noRegistrationNumber = userSearch.getRegistrationNumbers().contains(FILTER_WITHOUT_REG_NO);
787787
var withRegistrationNumber = userSearch.getRegistrationNumbers().contains(FILTER_WITH_REG_NO);
788788

789-
Specification<User> specification = Specification.where(distinct()).and(notSoftDeleted()).and(getSearchTermSpecification(searchTerm))
790-
.and(getInternalOrExternalSpecification(internal, external)).and(getActivatedOrDeactivatedSpecification(activated, deactivated))
791-
.and(getAuthoritySpecification(modifiedAuthorities)).and(getWithOrWithoutRegistrationNumberSpecification(noRegistrationNumber, withRegistrationNumber));
789+
Specification<User> specification = distinct().and(notSoftDeleted()).and(getSearchTermSpecification(searchTerm)).and(getInternalOrExternalSpecification(internal, external))
790+
.and(getActivatedOrDeactivatedSpecification(activated, deactivated)).and(getAuthoritySpecification(modifiedAuthorities))
791+
.and(getWithOrWithoutRegistrationNumberSpecification(noRegistrationNumber, withRegistrationNumber));
792792

793793
if (userSearch.isFindWithoutUserGroups()) {
794794
specification = specification.and(getAllUsersWithoutUserGroups());

src/main/java/de/tum/cit/aet/artemis/core/repository/UserSpecs.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import java.util.Arrays;
44
import java.util.Set;
55

6+
import jakarta.annotation.Nullable;
67
import jakarta.persistence.criteria.Join;
78
import jakarta.persistence.criteria.JoinType;
89
import jakarta.persistence.criteria.Predicate;
10+
import jakarta.validation.constraints.NotNull;
911

1012
import org.springframework.data.jpa.domain.Specification;
1113

@@ -27,6 +29,7 @@ public class UserSpecs {
2729
* @param searchTerm term to match
2830
* @return specification used to chain database operations
2931
*/
32+
@NotNull
3033
public static Specification<User> getSearchTermSpecification(String searchTerm) {
3134
String extendedSearchTerm = "%" + searchTerm + "%";
3235
return (root, query, criteriaBuilder) -> {
@@ -45,13 +48,15 @@ public static Specification<User> getSearchTermSpecification(String searchTerm)
4548
* @param authorities set of possible authorities
4649
* @return specification used to chain database operations
4750
*/
51+
@NotNull
4852
public static Specification<User> getAllUsersMatchingAuthorities(Set<String> authorities) {
4953
return (root, query, criteriaBuilder) -> {
5054
Join<User, Authority> joinedAuthorities = root.join(User_.AUTHORITIES, JoinType.LEFT);
5155
joinedAuthorities.on(criteriaBuilder.in(joinedAuthorities.get(Authority_.NAME)).value(authorities));
5256

53-
query.groupBy(root.get(User_.ID)).having(criteriaBuilder.equal(criteriaBuilder.count(joinedAuthorities), authorities.size()));
54-
57+
if (query != null) {
58+
query.groupBy(root.get(User_.ID)).having(criteriaBuilder.equal(criteriaBuilder.count(joinedAuthorities), authorities.size()));
59+
}
5560
return null;
5661
};
5762
}
@@ -61,6 +66,7 @@ public static Specification<User> getAllUsersMatchingAuthorities(Set<String> aut
6166
*
6267
* @return specification used to chain database operations
6368
*/
69+
@NotNull
6470
public static Specification<User> getAllUsersMatchingEmptyAuthorities() {
6571
return (root, query, criteriaBuilder) -> criteriaBuilder.isEmpty(root.get(User_.AUTHORITIES));
6672
}
@@ -71,6 +77,7 @@ public static Specification<User> getAllUsersMatchingEmptyAuthorities() {
7177
* @param authorities provided authorities
7278
* @return specification used to chain database operations
7379
*/
80+
@Nullable
7481
public static Specification<User> getAuthoritySpecification(Set<String> authorities) {
7582
if (authorities.contains(FILTER_NO_AUTHORITY)) {
7683
// Empty authorities
@@ -90,6 +97,7 @@ else if (!authorities.isEmpty()) {
9097
* @param external true if the account should be external
9198
* @return specification used to chain database operations
9299
*/
100+
@Nullable
93101
public static Specification<User> getInternalOrExternalSpecification(boolean internal, boolean external) {
94102
if (!internal && !external) {
95103
return null;
@@ -111,6 +119,7 @@ public static Specification<User> getInternalOrExternalSpecification(boolean int
111119
* @param withRegistrationNumber true if the account should have a registration number
112120
* @return specification used to chain database operations
113121
*/
122+
@Nullable
114123
public static Specification<User> getWithOrWithoutRegistrationNumberSpecification(Boolean noRegistrationNumber, Boolean withRegistrationNumber) {
115124
if (!noRegistrationNumber && !withRegistrationNumber) {
116125
return null;
@@ -136,6 +145,7 @@ public static Specification<User> getWithOrWithoutRegistrationNumberSpecificatio
136145
* @param deactivated true if the account should be deactivated
137146
* @return specification used to chain database operations
138147
*/
148+
@Nullable
139149
public static Specification<User> getActivatedOrDeactivatedSpecification(boolean activated, boolean deactivated) {
140150
if (!activated && !deactivated) {
141151
return null;
@@ -164,9 +174,12 @@ public static Specification<User> getAllUsersWithoutUserGroups() {
164174
*
165175
* @return specification used to chain database operations
166176
*/
177+
@NotNull
167178
public static Specification<User> distinct() {
168179
return (root, query, criteriaBuilder) -> {
169-
query.distinct(true);
180+
if (query != null) {
181+
query.distinct(true);
182+
}
170183
return null;
171184
};
172185
}
@@ -176,6 +189,7 @@ public static Specification<User> distinct() {
176189
*
177190
* @return specification used to chain database operations
178191
*/
192+
@NotNull
179193
public static Specification<User> notSoftDeleted() {
180194
return (root, query, criteriaBuilder) -> {
181195
Predicate notDeletedPredicate = criteriaBuilder.equal(root.get(User_.DELETED), false);

0 commit comments

Comments
 (0)