From 2abd12e7cf07a4b12a83063f6bd2add1fd2cbe89 Mon Sep 17 00:00:00 2001
From: torarnet <6398417+torarnet@users.noreply.github.com>
Date: Tue, 24 Sep 2024 08:53:50 +0200
Subject: [PATCH 1/3] np-47138: update to java 21
---
.github/workflows/gradle.yml | 8 ++++----
.github/workflows/karate.yml | 8 ++++----
buildSrc/build.gradle | 6 +++---
buildspec.yml | 2 +-
template.yaml | 2 +-
5 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index e5bb83414..949644f6a 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -11,11 +11,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - name: Set up JDK 17
- uses: actions/setup-java@v3
+ - uses: actions/checkout@v4
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
with:
- java-version: 17
+ java-version: 21
distribution: corretto
- name: Grant execute permission for gradlew
diff --git a/.github/workflows/karate.yml b/.github/workflows/karate.yml
index 7661850e8..ceb3e3afb 100644
--- a/.github/workflows/karate.yml
+++ b/.github/workflows/karate.yml
@@ -27,14 +27,14 @@ jobs:
id-token: write
contents: read
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- uses: actions/setup-python@v2
with:
python-version: "3.8"
- - name: Set up JDK 17
- uses: actions/setup-java@v3
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
with:
- java-version: 17
+ java-version: 21
distribution: corretto
- name: Setup AWS SAM CLI
uses: aws-actions/setup-sam@v1
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index c25f6b0d3..3a5ddba9b 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -15,9 +15,9 @@ dependencies {
}
group 'no.unit.nva'
-version '1.0-JDK17'
-java.sourceCompatibility = JavaVersion.VERSION_17
-java.targetCompatibility = JavaVersion.VERSION_17
+version '1.0-JDK21'
+java.sourceCompatibility = JavaVersion.VERSION_21
+java.targetCompatibility = JavaVersion.VERSION_21
wrapper {
distributionType = Wrapper.DistributionType.ALL
diff --git a/buildspec.yml b/buildspec.yml
index b6a8327da..bd90b9940 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -4,7 +4,7 @@ phases:
install:
runtime-versions:
- java: corretto17
+ java: corretto21
commands:
pip3 install aws-sam-cli -U
build:
diff --git a/template.yaml b/template.yaml
index d836b6b03..25877334a 100644
--- a/template.yaml
+++ b/template.yaml
@@ -9,7 +9,7 @@ Globals:
Function:
Timeout: 40
MemorySize: 1798
- Runtime: java17
+ Runtime: java21
Architectures:
- arm64
Environment:
From fec5f085aab90ba81f25b7fbad8771d3d307779b Mon Sep 17 00:00:00 2001
From: Bruno Saxoni <789709+brinxmat@users.noreply.github.com>
Date: Thu, 26 Sep 2024 10:53:50 +0200
Subject: [PATCH 2/3] Add java 21 update fixes (#409)
* Add java 21 update fixes
* Use non-star import
---
...istin.service.core.java-conventions.gradle | 2 +-
config/pmd/ruleset.xml | 12 +++----
.../biobank/model/ParameterKeyBiobank.java | 18 ++++------
.../no/unit/nva/cristin/common/Utils.java | 9 +++--
.../nva/cristin/common/client/ApiClient.java | 4 ++-
.../java/no/unit/nva/utils/AccessUtils.java | 30 +++++++++-------
.../main/java/no/unit/nva/utils/UriUtils.java | 8 +++--
.../java/no/unit/nva/utils/UserUtils.java | 34 +++++++++++++------
.../model/cristin/CristinFundingSource.java | 3 +-
.../keyword/query/QueryKeywordsHandler.java | 2 +-
.../client/CristinOrganizationApiClient.java | 8 ++---
.../QueryCristinOrganizationHandler.java | 2 +-
.../person/client/CristinPersonApiClient.java | 1 +
.../person/model/cristin/CristinPerson.java | 8 ++---
.../projects/common/ParameterKeyProject.java | 19 +++++------
.../create/CreateCristinProjectValidator.java | 4 +--
.../model/cristin/CristinProjectBuilder.java | 2 +-
.../model/nva/ContributorRoleMapping.java | 2 +-
.../projects/model/nva/NvaProjectBuilder.java | 1 +
.../projects/model/nva/ProjectStatus.java | 2 +-
20 files changed, 93 insertions(+), 78 deletions(-)
diff --git a/buildSrc/src/main/groovy/nva.cristin.service.core.java-conventions.gradle b/buildSrc/src/main/groovy/nva.cristin.service.core.java-conventions.gradle
index 455196280..6d78f832e 100644
--- a/buildSrc/src/main/groovy/nva.cristin.service.core.java-conventions.gradle
+++ b/buildSrc/src/main/groovy/nva.cristin.service.core.java-conventions.gradle
@@ -103,7 +103,7 @@ tasks.register('karateTest', Test) {
}
pmd {
- toolVersion = '6.55.0'
+ toolVersion = '7.5.0'
ruleSetConfig = rootProject.resources.text.fromFile('config/pmd/ruleset.xml')
ruleSets = []
ignoreFailures = false
diff --git a/config/pmd/ruleset.xml b/config/pmd/ruleset.xml
index a784791b2..cb24d6cbc 100644
--- a/config/pmd/ruleset.xml
+++ b/config/pmd/ruleset.xml
@@ -10,13 +10,15 @@
.*/test/.*
-
+
+
+
@@ -40,12 +42,6 @@
-
-
-
-
-
-
+
+
diff --git a/cristin-biobank/src/main/java/no/unit/nva/biobank/model/ParameterKeyBiobank.java b/cristin-biobank/src/main/java/no/unit/nva/biobank/model/ParameterKeyBiobank.java
index 002c7d4b7..998a55313 100644
--- a/cristin-biobank/src/main/java/no/unit/nva/biobank/model/ParameterKeyBiobank.java
+++ b/cristin-biobank/src/main/java/no/unit/nva/biobank/model/ParameterKeyBiobank.java
@@ -34,7 +34,7 @@ public enum ParameterKeyBiobank implements IParameterKey {
public static final int IGNORE_PATH_PARAMETER_INDEX = 2;
public static final Set VALID_QUERY_PARAMETERS =
- Arrays.stream(ParameterKeyBiobank.values())
+ Arrays.stream(values())
.filter(ParameterKeyBiobank::ignorePathKeys)
.collect(Collectors.toSet());
@@ -103,16 +103,12 @@ public String toString() {
}
public static ParameterKeyBiobank keyFromString(String paramName, String value) {
- var result = Arrays.stream(ParameterKeyBiobank.values())
- .filter(ParameterKeyBiobank::ignorePathKeys)
- .filter(IParameterKey.equalTo(paramName))
- .collect(Collectors.toSet());
- return result.size() == 1
- ? result.stream().findFirst().get()
- : result.stream()
- .filter(IParameterKey.hasValidValue(value))
- .findFirst()
- .orElse(INVALID);
+ return Arrays.stream(values())
+ .filter(ParameterKeyBiobank::ignorePathKeys)
+ .filter(IParameterKey.equalTo(paramName))
+ .distinct()
+ .reduce((first, second) -> IParameterKey.hasValidValue(value).test(second) ? second : first)
+ .orElse(INVALID);
}
diff --git a/cristin-commons/src/main/java/no/unit/nva/cristin/common/Utils.java b/cristin-commons/src/main/java/no/unit/nva/cristin/common/Utils.java
index 4ced96040..f921ea3c3 100644
--- a/cristin-commons/src/main/java/no/unit/nva/cristin/common/Utils.java
+++ b/cristin-commons/src/main/java/no/unit/nva/cristin/common/Utils.java
@@ -29,7 +29,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class Utils {
+public final class Utils {
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
@@ -40,6 +40,9 @@ public class Utils {
public static final String USER_IS_INTERNAL_BACKEND = "User is internal backend";
public static final String USER_TOP_LEVEL_CRISTIN_ORGANIZATION = "User has top level cristin organization {}";
+ private Utils() {
+ // NO-OP
+ }
/**
* Check if a string supplied is a positive integer.
@@ -130,7 +133,7 @@ public static String getValidOrgId(RequestInfo requestInfo) throws BadRequestExc
private static boolean isValidIdentifier(String identifier) {
- return Utils.isPositiveInteger(identifier);
+ return isPositiveInteger(identifier);
}
/**
@@ -169,7 +172,7 @@ public static String extractCristinInstitutionIdentifier(RequestInfo requestInfo
private static String extractInstitution(URI organization) {
var organizationIdentifier = UriUtils.extractLastPathElement(organization);
- return Utils.removeUnitPartFromIdentifierIfPresent(organizationIdentifier);
+ return removeUnitPartFromIdentifierIfPresent(organizationIdentifier);
}
private static BadRequestException failedToRetrieveTopLevelOrgCristinId() {
diff --git a/cristin-commons/src/main/java/no/unit/nva/cristin/common/client/ApiClient.java b/cristin-commons/src/main/java/no/unit/nva/cristin/common/client/ApiClient.java
index d35f49e3e..b0bbddc33 100644
--- a/cristin-commons/src/main/java/no/unit/nva/cristin/common/client/ApiClient.java
+++ b/cristin-commons/src/main/java/no/unit/nva/cristin/common/client/ApiClient.java
@@ -240,9 +240,11 @@ private List> collectSuccessfulResponses(
.filter(Try::isSuccess)
.map(Try::get)
.filter(this::isSuccessfulRequest)
- .collect(Collectors.toList());
+ .toList();
}
+ // This is reported as unused, but it is…
+ @SuppressWarnings("PMD.UnusedPrivateMethod")
private boolean isSuccessfulRequest(HttpResponse response) {
try {
checkHttpStatusCode(response.uri(), response.statusCode(), response.body());
diff --git a/cristin-commons/src/main/java/no/unit/nva/utils/AccessUtils.java b/cristin-commons/src/main/java/no/unit/nva/utils/AccessUtils.java
index 39a182986..fcefbd376 100644
--- a/cristin-commons/src/main/java/no/unit/nva/utils/AccessUtils.java
+++ b/cristin-commons/src/main/java/no/unit/nva/utils/AccessUtils.java
@@ -12,7 +12,6 @@
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Base64;
@@ -20,6 +19,7 @@
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static java.net.http.HttpRequest.newBuilder;
+import static java.net.http.HttpResponse.BodyHandlers.ofString;
import static nva.commons.apigateway.AccessRight.MANAGE_CUSTOMERS;
import static nva.commons.apigateway.AccessRight.MANAGE_OWN_AFFILIATION;
import static nva.commons.core.attempt.Try.attempt;
@@ -80,23 +80,27 @@ public static boolean clientIsCustomerAdministrator(RequestInfo requestInfo) {
* Fetches an internal backend token from Cognito.
*/
public static String getBackendAccessToken() throws IOException, InterruptedException {
- var cognitoTokenUrl = getCognitoTokenUrl();
- var payload = GRANT_TYPE_PAYLOAD;
- var request = newBuilder(cognitoTokenUrl)
- .POST(HttpRequest.BodyPublishers.ofString(payload))
- .header(CONTENT_TYPE, APPLICATION_X_WWW_FORM_URLENCODED)
- .header(AUTHORIZATION, basicAuthHeader())
- .build();
- HttpClient client = HttpClient.newBuilder()
+ try (var client = createHttpClient()) {
+ var response = client.send(createTokenRequest(), ofString(StandardCharsets.UTF_8));
+ var jsonTree = JsonUtils.dtoObjectMapper.readTree(response.body());
+ return jsonTree.get(ACCESS_TOKEN).textValue();
+ }
+ }
+
+ private static HttpClient createHttpClient() {
+ return HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.connectTimeout(Duration.ofSeconds(30))
.build();
+ }
- HttpResponse response = client.send(request,
- HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
- var jsonTree = JsonUtils.dtoObjectMapper.readTree(response.body());
- return jsonTree.get(ACCESS_TOKEN).textValue();
+ private static HttpRequest createTokenRequest() {
+ return newBuilder(getCognitoTokenUrl())
+ .POST(HttpRequest.BodyPublishers.ofString(GRANT_TYPE_PAYLOAD))
+ .header(CONTENT_TYPE, APPLICATION_X_WWW_FORM_URLENCODED)
+ .header(AUTHORIZATION, basicAuthHeader())
+ .build();
}
private static URI getCognitoTokenUrl() {
diff --git a/cristin-commons/src/main/java/no/unit/nva/utils/UriUtils.java b/cristin-commons/src/main/java/no/unit/nva/utils/UriUtils.java
index 941cf1012..6c3883530 100644
--- a/cristin-commons/src/main/java/no/unit/nva/utils/UriUtils.java
+++ b/cristin-commons/src/main/java/no/unit/nva/utils/UriUtils.java
@@ -15,13 +15,17 @@
import java.util.regex.Pattern;
import nva.commons.core.paths.UriWrapper;
-public class UriUtils {
+public final class UriUtils {
public static final String POSITION = "position";
public static final String PROJECT = "project";
public static final String PERSON = "person";
private static final String NATIONAL_IDENTITY_PATTERN = "national_id=(\\d+)(\\d{2})";
+ private UriUtils() {
+ // NO-OP
+ }
+
/**
* Create URI identifying NVA resource from path and identifier.
*
@@ -85,7 +89,7 @@ public static URI getNvaApiUri(String path) {
public static URI createNvaProjectId(String identifier) {
return new UriWrapper(HTTPS, DOMAIN_NAME)
- .addChild(BASE_PATH).addChild(UriUtils.PROJECT).addChild(identifier).getUri();
+ .addChild(BASE_PATH).addChild(PROJECT).addChild(identifier).getUri();
}
public static String extractLastPathElement(URI uri) {
diff --git a/cristin-commons/src/main/java/no/unit/nva/utils/UserUtils.java b/cristin-commons/src/main/java/no/unit/nva/utils/UserUtils.java
index ab4741335..a9331b31e 100644
--- a/cristin-commons/src/main/java/no/unit/nva/utils/UserUtils.java
+++ b/cristin-commons/src/main/java/no/unit/nva/utils/UserUtils.java
@@ -1,7 +1,6 @@
package no.unit.nva.utils;
import com.fasterxml.jackson.annotation.JsonProperty;
-import java.net.http.HttpResponse;
import no.unit.nva.cognito.CognitoUtil;
import no.unit.nva.commons.json.JsonUtils;
import nva.commons.core.paths.UriWrapper;
@@ -19,16 +18,20 @@
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static java.net.http.HttpRequest.newBuilder;
+import static java.net.http.HttpResponse.BodyHandlers.ofString;
import static no.unit.nva.cristin.model.Constants.DOMAIN_NAME;
import static no.unit.nva.cristin.model.Constants.HTTPS;
import static no.unit.nva.utils.AccessUtils.BASIC;
-public class UserUtils {
+public final class UserUtils {
private static final Logger logger = LoggerFactory.getLogger(UserUtils.class);
public static final String RESPONSE_FROM_USER_CREATE = "Response from user create={}";
public static final String USER_CREATED_WITH_ROLES = "User {} created with role(s) '{}'";
+ private UserUtils() {
+ // NO-OP
+ }
/**
* Creates user in Cognito used for Karate tests.
@@ -50,20 +53,29 @@ public static void createUserWithRoles(String username, String password, String
private static void createNvaUserWithRoles(String nationalIdentityNumber, URI customerId, Set roles)
throws IOException, InterruptedException {
+ try (var client = createHttpClient()) {
+ final var response = client.send(createHttpRequest(nationalIdentityNumber, customerId, roles),
+ ofString(StandardCharsets.UTF_8));
+ logger.info(RESPONSE_FROM_USER_CREATE, response);
+ }
+ }
+
+ private static HttpClient createHttpClient() {
+ return HttpClient.newBuilder()
+ .followRedirects(HttpClient.Redirect.ALWAYS)
+ .connectTimeout(Duration.ofSeconds(30))
+ .build();
+ }
+
+ private static HttpRequest createHttpRequest(String nationalIdentityNumber,
+ URI customerId,
+ Set roles) throws IOException, InterruptedException {
final var userRoles = new UserRoles(nationalIdentityNumber, customerId, roles);
final var body = JsonUtils.dtoObjectMapper.writeValueAsString(userRoles);
- final var request = newBuilder(createUserServiceUri())
+ return newBuilder(createUserServiceUri())
.header(AUTHORIZATION, BASIC + AccessUtils.getBackendAccessToken())
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
- final var client = HttpClient.newBuilder()
- .followRedirects(HttpClient.Redirect.ALWAYS)
- .connectTimeout(Duration.ofSeconds(30))
- .build();
-
- final var response =
- client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
- logger.info(RESPONSE_FROM_USER_CREATE, response);
}
diff --git a/cristin-funding/src/main/java/no/unit/nva/cristin/funding/sources/model/cristin/CristinFundingSource.java b/cristin-funding/src/main/java/no/unit/nva/cristin/funding/sources/model/cristin/CristinFundingSource.java
index 1835e61f6..da8060c50 100644
--- a/cristin-funding/src/main/java/no/unit/nva/cristin/funding/sources/model/cristin/CristinFundingSource.java
+++ b/cristin-funding/src/main/java/no/unit/nva/cristin/funding/sources/model/cristin/CristinFundingSource.java
@@ -4,6 +4,8 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;
+// The private fields in the record are viewed as unused, this is a bug
+@SuppressWarnings("PMD.UnusedPrivateField")
public record CristinFundingSource(@JsonProperty(CODE_FIELD) String code,
@JsonProperty(NAME_FIELD) Map name) {
@@ -14,5 +16,4 @@ public record CristinFundingSource(@JsonProperty(CODE_FIELD) String code,
public Map name() {
return nonEmptyOrDefault(name);
}
-
}
diff --git a/cristin-keyword/src/main/java/no/unit/nva/cristin/keyword/query/QueryKeywordsHandler.java b/cristin-keyword/src/main/java/no/unit/nva/cristin/keyword/query/QueryKeywordsHandler.java
index 5929d4d89..c665c690a 100644
--- a/cristin-keyword/src/main/java/no/unit/nva/cristin/keyword/query/QueryKeywordsHandler.java
+++ b/cristin-keyword/src/main/java/no/unit/nva/cristin/keyword/query/QueryKeywordsHandler.java
@@ -59,7 +59,7 @@ protected Integer getSuccessStatusCode(Void input, SearchResponse outpu
return HTTP_OK;
}
- private ConcurrentHashMap parseQueryParams(RequestInfo requestInfo) throws BadRequestException {
+ private Map parseQueryParams(RequestInfo requestInfo) throws BadRequestException {
validateQueryParameterKeys(requestInfo);
var queryParams = new ConcurrentHashMap();
diff --git a/cristin-organization/src/main/java/no/unit/nva/cristin/organization/common/client/CristinOrganizationApiClient.java b/cristin-organization/src/main/java/no/unit/nva/cristin/organization/common/client/CristinOrganizationApiClient.java
index 38ce4665d..d665949d7 100644
--- a/cristin-organization/src/main/java/no/unit/nva/cristin/organization/common/client/CristinOrganizationApiClient.java
+++ b/cristin-organization/src/main/java/no/unit/nva/cristin/organization/common/client/CristinOrganizationApiClient.java
@@ -62,7 +62,6 @@ public class CristinOrganizationApiClient
public static final String NULL_HTTP_RESPONSE_ERROR_MESSAGE = "No HttpResponse found";
public static final int SINGLE_HIT = 1;
public static final String UNIQUELY_IDENTIFY_ORGANIZATION = "Identifier does not uniquely identify organization";
- public static final int FIRST_AND_ONLY_UNIT = 0;
private static final int NO_HITS = 0;
/**
@@ -120,12 +119,11 @@ public Organization executeFetch(Map params) throws ApiGatewayEx
private Organization extractOrganization(String identifier, HttpResponse response)
throws ApiGatewayException {
- List units = attempt(() ->
- OBJECT_MAPPER.readValue(response.body(), new TypeReference>() {
- }))
+ var type = new TypeReference>() {};
+ List units = attempt(() -> OBJECT_MAPPER.readValue(response.body(), type))
.orElseThrow(fail -> new FailedHttpRequestException(fail.getException()));
if (SINGLE_HIT == units.size()) {
- return toOrganization(identifier, units.get(FIRST_AND_ONLY_UNIT));
+ return toOrganization(identifier, units.getFirst());
} else {
throw new BadRequestException(UNIQUELY_IDENTIFY_ORGANIZATION);
}
diff --git a/cristin-organization/src/main/java/no/unit/nva/cristin/organization/query/QueryCristinOrganizationHandler.java b/cristin-organization/src/main/java/no/unit/nva/cristin/organization/query/QueryCristinOrganizationHandler.java
index 37d3b8129..113f279f9 100644
--- a/cristin-organization/src/main/java/no/unit/nva/cristin/organization/query/QueryCristinOrganizationHandler.java
+++ b/cristin-organization/src/main/java/no/unit/nva/cristin/organization/query/QueryCristinOrganizationHandler.java
@@ -78,7 +78,7 @@ protected Integer getSuccessStatusCode(Void input, SearchResponse
return HttpURLConnection.HTTP_OK;
}
- private ConcurrentHashMap extractQueryParameters(RequestInfo requestInfo)
+ private Map extractQueryParameters(RequestInfo requestInfo)
throws BadRequestException {
var requestQueryParams = new ConcurrentHashMap();
diff --git a/cristin-person/src/main/java/no/unit/nva/cristin/person/client/CristinPersonApiClient.java b/cristin-person/src/main/java/no/unit/nva/cristin/person/client/CristinPersonApiClient.java
index 0dd6e7a50..6777b716e 100644
--- a/cristin-person/src/main/java/no/unit/nva/cristin/person/client/CristinPersonApiClient.java
+++ b/cristin-person/src/main/java/no/unit/nva/cristin/person/client/CristinPersonApiClient.java
@@ -41,6 +41,7 @@
import static no.unit.nva.utils.UriUtils.getNvaApiId;
import static nva.commons.core.attempt.Try.attempt;
+@SuppressWarnings("PMD.CouplingBetweenObjects")
public class CristinPersonApiClient extends ApiClient
implements ClientVersion,
CristinAuthorizedQueryClient