From b06274432e8135549839b4fc99eea7f2a62408b8 Mon Sep 17 00:00:00 2001 From: Jean-Kevin KPADEY Date: Sun, 31 May 2026 19:59:12 +0200 Subject: [PATCH 1/3] build: upgrade Java version from 17 to 21 - Update maven.compiler.source/target to 21 in root pom.xml - Update java-version to 21 in all GitHub Actions workflows (maven-verify, release, codeql, sonar-pr-analysis) - Update DeepSource runtime_version from 16 to 21 - Update CodeClimate sonar.java.source from 8 to 21 - Update AGENTS.md tech stack table --- .codeclimate.yml | 2 +- .deepsource.toml | 2 +- .github/workflows/codeql.yml | 4 ++-- .github/workflows/maven-verify.yml | 4 ++-- .github/workflows/release.yml | 2 +- .github/workflows/sonar-pr-analysis.yml | 2 +- AGENTS.md | 2 +- pom.xml | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index bce59244..b193156a 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -41,4 +41,4 @@ plugins: sonar-java: enabled: true config: - sonar.java.source: 8 + sonar.java.source: 21 diff --git a/.deepsource.toml b/.deepsource.toml index f64f73b3..94e8f41d 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -15,4 +15,4 @@ name = "java" enabled = true [analyzers.meta] - runtime_version = "16" + runtime_version = "21" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1418c01c..7072a3e8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -26,11 +26,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v5 with: distribution: 'adopt' - java-version: '17' + java-version: '21' cache: 'maven' # Initializes the CodeQL tools for scanning. diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml index 8f699025..6741749d 100644 --- a/.github/workflows/maven-verify.yml +++ b/.github/workflows/maven-verify.yml @@ -17,7 +17,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '21' distribution: 'adopt' - name: Cache SonarQube packages uses: actions/cache@v5 @@ -84,7 +84,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '21' distribution: 'adopt' - name: Generate the javadoc run: mvn --batch-mode -ntp install -DskipTests && mvn --batch-mode -ntp javadoc:javadoc diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4372565f..8e9dd738 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: uses: actions/setup-java@v5 with: distribution: 'adopt' - java-version: '17' + java-version: '21' cache: 'maven' server-id: central server-username: MAVEN_CENTRAL_USERNAME diff --git a/.github/workflows/sonar-pr-analysis.yml b/.github/workflows/sonar-pr-analysis.yml index 768943e5..6bedc86f 100644 --- a/.github/workflows/sonar-pr-analysis.yml +++ b/.github/workflows/sonar-pr-analysis.yml @@ -45,7 +45,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '21' distribution: 'adopt' - name: Cache SonarQube packages uses: actions/cache@v5 diff --git a/AGENTS.md b/AGENTS.md index 116c56fc..9762edc4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,7 +30,7 @@ manually. | Concern | Technology | |---|---| -| Language | Java 17 | +| Language | Java 21 | | Build | Apache Maven (multi-module) | | Unit tests | JUnit 5 (`junit-jupiter` 5.11.4) | | Assertions | Hamcrest 3.0 | diff --git a/pom.xml b/pom.xml index eec351ef..ae7e229b 100644 --- a/pom.xml +++ b/pom.xml @@ -44,8 +44,8 @@ - 17 - 17 + 21 + 21 UTF-8 0.98 0.96 From 08e8306391f46aa63e519050ab41082a6a59c3c5 Mon Sep 17 00:00:00 2001 From: Jean-Kevin KPADEY Date: Sun, 31 May 2026 20:21:09 +0200 Subject: [PATCH 2/3] refactor!: remove deprecated methods BREAKING CHANGE: Removed all deprecated methods: - Messages.setLocale(Locale) (since 2.17.0) - Messages.clearLocale() (since 2.17.0) - MetarParser.getInstance() (since 2.19.0) - TAFParser.getInstance() (since 2.19.0) - RemarkParser.getInstance() (since 2.19.0) - FMTrendParser.getInstance() (since 2.19.0) - ProbTrendParser.getInstance() (since 2.19.0) - TrendValididyParser.getInstance() (since 2.19.0) Use the constructor directly for parsers. For locale-aware string lookup, use Messages.getString(Locale, String). --- .../mivek/internationalization/Messages.java | 31 ++----------------- .../internationalization/MessagesTest.java | 20 ------------ .../mivek/enums/IcingIntensityTest.java | 4 +-- .../mivek/enums/TurbulenceIntensityTest.java | 4 +-- .../io/github/mivek/parser/FMTrendParser.java | 9 ------ .../io/github/mivek/parser/MetarParser.java | 11 ------- .../github/mivek/parser/ProbTrendParser.java | 9 ------ .../io/github/mivek/parser/RemarkParser.java | 8 ----- .../io/github/mivek/parser/TAFParser.java | 9 ------ .../mivek/parser/TrendValididyParser.java | 9 ------ ...yMaximumMinimumTemperatureCommandTest.java | 7 ----- .../HourlyMaximumTemperatureCommandTest.java | 7 ----- .../HourlyMinimumTemperatureCommandTest.java | 7 ----- .../HourlyPrecipitationAmountCommandTest.java | 7 ----- .../remark/HourlyPressureCommandTest.java | 7 ----- .../HourlyTemperatureDewPointCommandTest.java | 7 ----- .../remark/IceAccretionCommandTest.java | 7 ----- .../PrecipitationAmount24HourCommandTest.java | 7 ----- .../PrecipitationAmount36HourCommandTest.java | 7 ----- .../remark/PrecipitationBegCommandTest.java | 7 ----- .../remark/PrecipitationEndCommandTest.java | 7 ----- .../command/remark/SnowDepthCommandTest.java | 7 ----- .../remark/SunshineDurationCommandTest.java | 7 ----- .../WaterEquivalentSnowCommandTest.java | 7 ----- .../mivek/parser/FMTrendParserTest.java | 9 +----- .../github/mivek/parser/MetarParserTest.java | 11 ------- .../mivek/parser/ProbTrendParserTest.java | 7 +---- .../github/mivek/parser/RemarkParserTest.java | 7 ----- .../io/github/mivek/parser/TAFParserTest.java | 6 ---- .../mivek/parser/TrendValididyParserTest.java | 7 ----- 30 files changed, 6 insertions(+), 253 deletions(-) diff --git a/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java b/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java index 4826885e..ad37c9e8 100644 --- a/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java +++ b/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java @@ -14,10 +14,9 @@ * {@link #getString(Locale, String, Object...)} require an explicit * {@code Locale} parameter and never touch thread-local state. * These are the preferred path for new code. - *
  • Stateful (legacy) — {@link #getString(String)} and + *
  • Stateful — {@link #getString(String)} and * {@link #getString(String, Object...)} read from a per-thread - * {@link ResourceBundle} controlled by {@link #setLocale(Locale)}. - * Scheduled for removal in a future major release.
  • + * {@link ResourceBundle} using the JVM default locale. * * * All lookups degrade gracefully: if a key is missing in the requested bundle @@ -46,32 +45,6 @@ public static Messages getInstance() { return INSTANCE; } - /** - * Sets the locale of the bundle for the current thread. - * - * @param locale the locale to set. - * @deprecated Use {@link #getString(Locale, String)} instead. - * Scheduled for removal in a future major release. - */ - @Deprecated(since = "2.17.0", forRemoval = true) - public void setLocale(final Locale locale) { - bundleHolder.set(ResourceBundle.getBundle(BUNDLE_NAME, locale)); - } - - /** - * Clears the locale for the current thread, resetting it to the JVM default. - * - *

    Must be called in thread-pool environments (e.g., servlets, Spring) - * after each request to prevent locale leakage between tasks on the same thread. - * - * @deprecated Use {@link #getString(Locale, String)} instead. - * Scheduled for removal in a future major release. - */ - @Deprecated(since = "2.17.0", forRemoval = true) - public void clearLocale() { - bundleHolder.remove(); - } - /** * Returns a localized string for the given key using the thread-local locale. * diff --git a/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java b/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java index 8efb1b65..4eca2a0f 100644 --- a/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java +++ b/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java @@ -13,32 +13,12 @@ import java.util.Properties; import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; class MessagesTest { - @Test - @SuppressWarnings("java:S5738") - void testSetLocale() { - Messages.getInstance().setLocale(Locale.FRENCH); // NOSONAR java:S5738 - assertEquals("peu", Messages.getInstance().getString("CloudQuantity.FEW")); - Messages.getInstance().setLocale(Locale.ENGLISH); // NOSONAR java:S5738 - assertEquals("few", Messages.getInstance().getString("CloudQuantity.FEW")); - Messages.getInstance().clearLocale(); // NOSONAR java:S5738 - } - - @Test - @SuppressWarnings("java:S5738") - void testClearLocale() { - Messages.getInstance().setLocale(Locale.FRENCH); // NOSONAR java:S5738 - assertEquals("peu", Messages.getInstance().getString("CloudQuantity.FEW")); - Messages.getInstance().clearLocale(); // NOSONAR java:S5738 - assertDoesNotThrow(() -> Messages.getInstance().getString("CloudQuantity.FEW")); - } - @Test void testGetStringWithArgs() { assertEquals("ceiling varying between 5 and 15 feet", diff --git a/metarParser-entities/src/test/java/io/github/mivek/enums/IcingIntensityTest.java b/metarParser-entities/src/test/java/io/github/mivek/enums/IcingIntensityTest.java index 9ee59914..93a751a5 100644 --- a/metarParser-entities/src/test/java/io/github/mivek/enums/IcingIntensityTest.java +++ b/metarParser-entities/src/test/java/io/github/mivek/enums/IcingIntensityTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.*; -import io.github.mivek.internationalization.Messages; import java.util.Locale; import org.junit.jupiter.api.Test; @@ -22,7 +21,6 @@ void testGetEnumValid() { @Test void testToString() { - Messages.getInstance().setLocale(Locale.ENGLISH); - assertEquals("Severe Mixed Icing", IcingIntensity.SEVERE_MIXED_ICING.toString()); + assertEquals("Severe Mixed Icing", IcingIntensity.SEVERE_MIXED_ICING.toString(Locale.ENGLISH)); } } diff --git a/metarParser-entities/src/test/java/io/github/mivek/enums/TurbulenceIntensityTest.java b/metarParser-entities/src/test/java/io/github/mivek/enums/TurbulenceIntensityTest.java index 6514cb0f..b81698ff 100644 --- a/metarParser-entities/src/test/java/io/github/mivek/enums/TurbulenceIntensityTest.java +++ b/metarParser-entities/src/test/java/io/github/mivek/enums/TurbulenceIntensityTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.*; -import io.github.mivek.internationalization.Messages; import java.util.Locale; import org.junit.jupiter.api.Test; @@ -23,7 +22,6 @@ void testGetEnumValid() { @Test void testToString() { - Messages.getInstance().setLocale(Locale.ENGLISH); - assertEquals("Extreme turbulence", TurbulenceIntensity.EXTREME.toString()); + assertEquals("Extreme turbulence", TurbulenceIntensity.EXTREME.toString(Locale.ENGLISH)); } } diff --git a/metarParser-parsers/src/main/java/io/github/mivek/parser/FMTrendParser.java b/metarParser-parsers/src/main/java/io/github/mivek/parser/FMTrendParser.java index e82f2bdc..76285b7f 100644 --- a/metarParser-parsers/src/main/java/io/github/mivek/parser/FMTrendParser.java +++ b/metarParser-parsers/src/main/java/io/github/mivek/parser/FMTrendParser.java @@ -41,15 +41,6 @@ public AbstractTafTrend parse(final String[] code) { return trend; } - /** - * @return The singleton instance. - * @deprecated Use the constructor instead. - */ - @Deprecated(forRemoval = true, since = "2.19.0") - public static FMTrendParser getInstance() { - return new FMTrendParser(); - } - /** * Parses the validity of a {@link FMTafTrend} object. * diff --git a/metarParser-parsers/src/main/java/io/github/mivek/parser/MetarParser.java b/metarParser-parsers/src/main/java/io/github/mivek/parser/MetarParser.java index fa911f5f..70c3b287 100644 --- a/metarParser-parsers/src/main/java/io/github/mivek/parser/MetarParser.java +++ b/metarParser-parsers/src/main/java/io/github/mivek/parser/MetarParser.java @@ -45,17 +45,6 @@ public MetarParser(final CommonCommandSupplier commonCommandSupplier, final Rema supplier = Objects.requireNonNull(metarCommandSupplier); } - /** - * Get instance method. - * - * @return the instance of MetarParser. - * @deprecated Use the constructor instead. - */ - @Deprecated(forRemoval = true, since = "2.19.0") - public static MetarParser getInstance() { - return new MetarParser(); - } - /** * This is the main method of the parser. This method checks if the airport * exists. If it does then the metar code is decoded. diff --git a/metarParser-parsers/src/main/java/io/github/mivek/parser/ProbTrendParser.java b/metarParser-parsers/src/main/java/io/github/mivek/parser/ProbTrendParser.java index 18db26bd..e8aacb26 100644 --- a/metarParser-parsers/src/main/java/io/github/mivek/parser/ProbTrendParser.java +++ b/metarParser-parsers/src/main/java/io/github/mivek/parser/ProbTrendParser.java @@ -48,15 +48,6 @@ public TafProbTrend parse(final String[] code) { return trend; } - /** - * @return The ProbTrendParser instance. - * @deprecated Use the constructor instead. - */ - @Deprecated(forRemoval = true, since = "2.19.0") - public static ProbTrendParser getInstance() { - return new ProbTrendParser(); - } - /** * parses the probability out of PROB. * diff --git a/metarParser-parsers/src/main/java/io/github/mivek/parser/RemarkParser.java b/metarParser-parsers/src/main/java/io/github/mivek/parser/RemarkParser.java index 29e38e4a..e45362a0 100644 --- a/metarParser-parsers/src/main/java/io/github/mivek/parser/RemarkParser.java +++ b/metarParser-parsers/src/main/java/io/github/mivek/parser/RemarkParser.java @@ -44,12 +44,4 @@ public String parse(final String remark) { return sb.toString(); } - /** - * @deprecated Use the default constructor instead. - * @return the instance of the parser. - */ - @Deprecated(forRemoval = true, since = "2.19.0") - public static RemarkParser getInstance() { - return new RemarkParser(); - } } diff --git a/metarParser-parsers/src/main/java/io/github/mivek/parser/TAFParser.java b/metarParser-parsers/src/main/java/io/github/mivek/parser/TAFParser.java index 2abb182d..8c6ca805 100644 --- a/metarParser-parsers/src/main/java/io/github/mivek/parser/TAFParser.java +++ b/metarParser-parsers/src/main/java/io/github/mivek/parser/TAFParser.java @@ -50,15 +50,6 @@ public TAFParser(final CommonCommandSupplier commonCommandSupplier, final Remark supplier = tafCommandSupplier; } - /** - * @deprecated Use constructor instead. - * @return the instance. - */ - @Deprecated(forRemoval = true, since = "2.19.0") - public static TAFParser getInstance() { - return new TAFParser(); - } - @Override public TAF parse(final String code) throws ParseException { String[][] lines = extractLineTokens(code); diff --git a/metarParser-parsers/src/main/java/io/github/mivek/parser/TrendValididyParser.java b/metarParser-parsers/src/main/java/io/github/mivek/parser/TrendValididyParser.java index d6d2254b..c1d40890 100644 --- a/metarParser-parsers/src/main/java/io/github/mivek/parser/TrendValididyParser.java +++ b/metarParser-parsers/src/main/java/io/github/mivek/parser/TrendValididyParser.java @@ -30,15 +30,6 @@ public TrendValididyParser() { this(new CommonCommandSupplier(), new RemarkParser(), new TAFCommandSupplier()); } - /** - * @deprecated Use constructor instead. - * @return The TrendValidityParser instance. - */ - @Deprecated(forRemoval = true, since = "2.19.0") - public static TrendValididyParser getInstance() { - return new TrendValididyParser(); - } - @Override public TafTrend parse(final String[] code) { TafTrend trend = FactoryProvider.getTAFTrendFactory().create(code[0]).orElseThrow(() -> new IllegalArgumentException(code[0])); diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumMinimumTemperatureCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumMinimumTemperatureCommandTest.java index 5aa5beaa..447f3a5f 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumMinimumTemperatureCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumMinimumTemperatureCommandTest.java @@ -1,11 +1,8 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -13,10 +10,6 @@ class HourlyMaximumMinimumTemperatureCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumTemperatureCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumTemperatureCommandTest.java index b6515458..ea68e373 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumTemperatureCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMaximumTemperatureCommandTest.java @@ -1,23 +1,16 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HourlyMaximumTemperatureCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecuteBelowZero() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMinimumTemperatureCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMinimumTemperatureCommandTest.java index 5c993249..77ec255e 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMinimumTemperatureCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyMinimumTemperatureCommandTest.java @@ -1,23 +1,16 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HourlyMinimumTemperatureCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecuteWithNegativeTemperature() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPrecipitationAmountCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPrecipitationAmountCommandTest.java index 368acddf..23302f56 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPrecipitationAmountCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPrecipitationAmountCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HourlyPrecipitationAmountCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPressureCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPressureCommandTest.java index d8e4d3de..8b1124db 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPressureCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyPressureCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class HourlyPressureCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute(){ diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyTemperatureDewPointCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyTemperatureDewPointCommandTest.java index 5899e273..0ab5c79b 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyTemperatureDewPointCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/HourlyTemperatureDewPointCommandTest.java @@ -1,11 +1,8 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,10 +11,6 @@ class HourlyTemperatureDewPointCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/IceAccretionCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/IceAccretionCommandTest.java index a3105764..0b2a107d 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/IceAccretionCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/IceAccretionCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class IceAccretionCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount24HourCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount24HourCommandTest.java index 8cbff3b6..64c64ab7 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount24HourCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount24HourCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class PrecipitationAmount24HourCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount36HourCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount36HourCommandTest.java index 4c63ad0e..408b99c3 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount36HourCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationAmount36HourCommandTest.java @@ -1,23 +1,16 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class PrecipitationAmount36HourCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute3Hours() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationBegCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationBegCommandTest.java index 008c3f1b..3bfbe6ba 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationBegCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationBegCommandTest.java @@ -1,23 +1,16 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class PrecipitationBegCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationEndCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationEndCommandTest.java index c50e7080..c582fad3 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationEndCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/PrecipitationEndCommandTest.java @@ -1,23 +1,16 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class PrecipitationEndCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SnowDepthCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SnowDepthCommandTest.java index ca57224b..88ba0665 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SnowDepthCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SnowDepthCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class SnowDepthCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SunshineDurationCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SunshineDurationCommandTest.java index 454a118c..918579bb 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SunshineDurationCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/SunshineDurationCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class SunshineDurationCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/WaterEquivalentSnowCommandTest.java b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/WaterEquivalentSnowCommandTest.java index f94722f2..10d7ccf3 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/command/remark/WaterEquivalentSnowCommandTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/command/remark/WaterEquivalentSnowCommandTest.java @@ -1,22 +1,15 @@ package io.github.mivek.command.remark; -import io.github.mivek.internationalization.Messages; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; class WaterEquivalentSnowCommandTest { - @BeforeEach - void setup() { - Messages.getInstance().setLocale(Locale.ENGLISH); - } @Test void testExecute() { diff --git a/metarParser-parsers/src/test/java/io/github/mivek/parser/FMTrendParserTest.java b/metarParser-parsers/src/test/java/io/github/mivek/parser/FMTrendParserTest.java index 6463d4f1..bf4397b1 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/parser/FMTrendParserTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/parser/FMTrendParserTest.java @@ -5,8 +5,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; /** * @author Jean-Kevin KPADEY @@ -23,10 +21,5 @@ void testParseBeginningValidity() { assertThat(res.getStartMinutes(), is(5)); } - @Test - @SuppressWarnings("java:S5738") - void testGetInstance() { - assertNotNull(FMTrendParser.getInstance()); - assertInstanceOf(FMTrendParser.class, FMTrendParser.getInstance()); - } } + diff --git a/metarParser-parsers/src/test/java/io/github/mivek/parser/MetarParserTest.java b/metarParser-parsers/src/test/java/io/github/mivek/parser/MetarParserTest.java index edf879f2..6f8cae64 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/parser/MetarParserTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/parser/MetarParserTest.java @@ -8,8 +8,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Locale; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; @@ -391,7 +389,6 @@ void testParseWithInvalidWeatherCondition() throws ParseException { @Test void testParseWithRemarks() throws ParseException { String code = "KCOS 261454Z 34012G18KT 10SM BKN060 BKN100 15/10 A3020 RMK AO2 RAE45 SLP171 P0000 60002 T01500100 51009 $"; - Messages.getInstance().setLocale(Locale.ENGLISH); Metar m = parser.parse(code); assertEquals("KCOS", m.getStation()); @@ -409,7 +406,6 @@ void testParseWithRemarks() throws ParseException { @Test void testParseWithMinimalVisibility() throws ParseException { String code = "SUMU 070520Z 34025KT 8000 2000SW VCSH SCT013CB BKN026 00/M05 Q1012 TEMPO 2000 SHSN="; - Messages.getInstance().setLocale(Locale.ENGLISH); Metar m = parser.parse(code); assertEquals("SUMU", m.getStation()); assertNotNull(m.getVisibility()); @@ -455,7 +451,6 @@ void testParseVC() throws ParseException { void testParseRunwayDeposit() throws ParseException { String code = "UUDD 212100Z 20005MPS 8000 -FZRA SCT005 M01/M02 Q1010 R14R/590335 NOSIG"; - Messages.getInstance().setLocale(Locale.ENGLISH); Metar m = parser.parse(code); assertEquals("UUDD", m.getStation()); assertThat(m.getRunways(), hasSize(1)); @@ -490,10 +485,4 @@ void testParseWithRecentRain() throws ParseException { assertEquals(Phenomenon.RAIN, m.getWeatherConditions().get(0).getPhenomenons().get(0)); } - @Test - @SuppressWarnings("java:S5738") - void testGetInstance() { - assertNotNull(MetarParser.getInstance()); - assertInstanceOf(MetarParser.class, MetarParser.getInstance()); - } } diff --git a/metarParser-parsers/src/test/java/io/github/mivek/parser/ProbTrendParserTest.java b/metarParser-parsers/src/test/java/io/github/mivek/parser/ProbTrendParserTest.java index a0575f42..31eee0ce 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/parser/ProbTrendParserTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/parser/ProbTrendParserTest.java @@ -58,10 +58,5 @@ void testParseWithProb() { MatcherAssert.assertThat(trend.getClouds(), hasSize(1)); } - @Test - @SuppressWarnings("java:S5738") - void testGetInstance() { - assertNotNull(ProbTrendParser.getInstance()); - assertInstanceOf(ProbTrendParser.class, ProbTrendParser.getInstance()); - } } + diff --git a/metarParser-parsers/src/test/java/io/github/mivek/parser/RemarkParserTest.java b/metarParser-parsers/src/test/java/io/github/mivek/parser/RemarkParserTest.java index b031c066..cd33f065 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/parser/RemarkParserTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/parser/RemarkParserTest.java @@ -8,7 +8,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; class RemarkParserTest { @@ -374,10 +373,4 @@ void testParseWithDistantLightning() { assertThat(remark, containsString(Messages.getInstance().getString("Remark.ALQDS"))); } - @Test - @SuppressWarnings("java:S5738") - void testGetInstance() { - assertNotNull(RemarkParser.getInstance()); - assertInstanceOf(RemarkParser.class, RemarkParser.getInstance()); - } } diff --git a/metarParser-parsers/src/test/java/io/github/mivek/parser/TAFParserTest.java b/metarParser-parsers/src/test/java/io/github/mivek/parser/TAFParserTest.java index a3ea8808..e1d1c69c 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/parser/TAFParserTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/parser/TAFParserTest.java @@ -959,10 +959,4 @@ void testParseWithoutDeliveryTime() throws ParseException { assertEquals(3, taf.getValidity().getEndHour()); } - @Test - @SuppressWarnings("java:S5738") - void testGetInstance() { - assertNotNull(TAFParser.getInstance()); - assertInstanceOf(TAFParser.class, TAFParser.getInstance()); - } } diff --git a/metarParser-parsers/src/test/java/io/github/mivek/parser/TrendValididyParserTest.java b/metarParser-parsers/src/test/java/io/github/mivek/parser/TrendValididyParserTest.java index c476d2b8..32beaaaa 100644 --- a/metarParser-parsers/src/test/java/io/github/mivek/parser/TrendValididyParserTest.java +++ b/metarParser-parsers/src/test/java/io/github/mivek/parser/TrendValididyParserTest.java @@ -43,11 +43,4 @@ void testParseTrend() { assertEquals(400, trend.getClouds().get(0).getHeight()); } - @Test - @SuppressWarnings("java:S5738") - void testGetInstance() { - assertNotNull(TrendValididyParser.getInstance()); - assertInstanceOf(TrendValididyParser.class, TrendValididyParser.getInstance()); - } - } From 042f0a3efe3fd495cbf6b219d263bd129cf2d17f Mon Sep 17 00:00:00 2001 From: Jean-Kevin KPADEY Date: Sun, 14 Jun 2026 23:14:34 +0200 Subject: [PATCH 3/3] fix(commons): add cleanup method for ThreadLocal to prevent memory leak --- .../mivek/internationalization/Messages.java | 14 ++++++++++++++ .../mivek/internationalization/MessagesTest.java | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java b/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java index ad37c9e8..222b5c81 100644 --- a/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java +++ b/metarParser-commons/src/main/java/io/github/mivek/internationalization/Messages.java @@ -45,6 +45,20 @@ public static Messages getInstance() { return INSTANCE; } + /** + * Clears the thread-local {@link ResourceBundle} for the current thread. + * + *

    Call this when a thread finishes using the stateful API + * ({@link #getString(String)} / {@link #getString(String, Object...)}), + * especially in thread pools, to prevent {@link ThreadLocal} memory leaks. + * + *

    Not needed for the stateless overloads {@link #getString(Locale, String)} + * and {@link #getString(Locale, String, Object...)}. + */ + public static void cleanup() { + INSTANCE.bundleHolder.remove(); + } + /** * Returns a localized string for the given key using the thread-local locale. * diff --git a/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java b/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java index 4eca2a0f..1ffb1393 100644 --- a/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java +++ b/metarParser-commons/src/test/java/io/github/mivek/internationalization/MessagesTest.java @@ -53,6 +53,14 @@ void testMissingKeyWithArgsReturnsKey() { assertEquals("NonExistent.Key", Messages.getInstance().getString(Locale.FRENCH, "NonExistent.Key", "arg1")); } + @Test + void testCleanup() { + Messages messages = Messages.getInstance(); + String before = messages.getString("CloudQuantity.FEW"); + Messages.cleanup(); + assertEquals(before, messages.getString("CloudQuantity.FEW")); + } + @ParameterizedTest @ValueSource(strings = {"messages_de", "messages_es", "messages_fr", "messages_it", "messages_pl_PL", "messages_ru_RU", "messages_tr_TR", "messages_zh_CN"})