From 6b5f89880da726f63af52d7cb08e6c40e3967814 Mon Sep 17 00:00:00 2001 From: Mihaly Lengyel Date: Thu, 12 Mar 2026 09:51:45 +0100 Subject: [PATCH 1/2] fix: test and fix how we handle the POSTGRESQL_MINIMUM_IDLE_CONNECTIONS envvar --- build.gradle | 3 +- .../supertokens/storage/postgresql/Start.java | 16 +++- .../postgresql/test/EnvConfigTest.java | 95 +++++++++++++++++++ 3 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 src/test/java/io/supertokens/storage/postgresql/test/EnvConfigTest.java diff --git a/build.gradle b/build.gradle index 7c4ea849..6ceae109 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,8 @@ tasks.register('generateMetaInf') { build.dependsOn(generateMetaInf) test { - jvmArgs '-Djava.security.egd=file:/dev/urandom' + jvmArgs '-Djava.security.egd=file:/dev/urandom', + '--add-opens=java.base/java.util=ALL-UNNAMED' minHeapSize = "128m" // initial heap size maxHeapSize = "1024m" // maximum heap size testLogging { diff --git a/src/main/java/io/supertokens/storage/postgresql/Start.java b/src/main/java/io/supertokens/storage/postgresql/Start.java index 28cea0ee..3981bf69 100644 --- a/src/main/java/io/supertokens/storage/postgresql/Start.java +++ b/src/main/java/io/supertokens/storage/postgresql/Start.java @@ -863,18 +863,24 @@ public void updateConfigJsonFromEnv(JsonObject configJson) { .replace("\\\\", "\\"); } + // Empty/unset stringValue is already handled above (null/empty check), + // so boxed types (Integer, Long, etc.) can safely share branches + // with their primitive counterparts. if (field.getType().equals(String.class)) { configJson.addProperty(field.getName(), stringValue); - } else if (field.getType().equals(int.class)) { + } else if (field.getType().equals(int.class) || field.getType().equals(Integer.class)) { configJson.addProperty(field.getName(), Integer.parseInt(stringValue)); - } else if (field.getType().equals(long.class)) { + } else if (field.getType().equals(long.class) || field.getType().equals(Long.class)) { configJson.addProperty(field.getName(), Long.parseLong(stringValue)); - } else if (field.getType().equals(boolean.class)) { + } else if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) { configJson.addProperty(field.getName(), Boolean.parseBoolean(stringValue)); - } else if (field.getType().equals(float.class)) { + } else if (field.getType().equals(float.class) || field.getType().equals(Float.class)) { configJson.addProperty(field.getName(), Float.parseFloat(stringValue)); - } else if (field.getType().equals(double.class)) { + } else if (field.getType().equals(double.class) || field.getType().equals(Double.class)) { configJson.addProperty(field.getName(), Double.parseDouble(stringValue)); + } else { + throw new RuntimeException( + "Unknown field type " + field.getType().getName() + " for config field " + field.getName()); } } } diff --git a/src/test/java/io/supertokens/storage/postgresql/test/EnvConfigTest.java b/src/test/java/io/supertokens/storage/postgresql/test/EnvConfigTest.java new file mode 100644 index 00000000..28e72fd3 --- /dev/null +++ b/src/test/java/io/supertokens/storage/postgresql/test/EnvConfigTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.supertokens.storage.postgresql.test; + +import com.google.gson.JsonObject; +import io.supertokens.storage.postgresql.Start; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.util.Map; + +import static org.junit.Assert.*; + +public class EnvConfigTest { + + private static void setEnv(String key, String value) { + try { + Map env = System.getenv(); + Class cl = env.getClass(); + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + @SuppressWarnings("unchecked") + Map writableEnv = (Map) field.get(env); + writableEnv.put(key, value); + } catch (Exception e) { + throw new IllegalStateException("Failed to set environment variable", e); + } + } + + private static void removeEnv(String key) { + try { + Map env = System.getenv(); + Class cl = env.getClass(); + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + @SuppressWarnings("unchecked") + Map writableEnv = (Map) field.get(env); + writableEnv.remove(key); + } catch (Exception e) { + throw new IllegalStateException("Failed to remove environment variable", e); + } + } + + @Test + public void testUpdateConfigJsonFromEnvHandlesBoxedTypes() { + // Regression test: Integer fields like postgresql_minimum_idle_connections + // were silently dropped because updateConfigJsonFromEnv only checked + // primitive types (int.class) not boxed types (Integer.class). + Start start = new Start(); + try { + setEnv("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS", "5"); + + JsonObject configJson = new JsonObject(); + start.updateConfigJsonFromEnv(configJson); + + assertTrue("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS env var should be loaded into configJson", + configJson.has("postgresql_minimum_idle_connections")); + assertEquals(5, configJson.get("postgresql_minimum_idle_connections").getAsInt()); + } finally { + removeEnv("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS"); + } + } + + @Test + public void testUpdateConfigJsonFromEnvHandlesBoxedTypeWithZero() { + // Tests that Integer value of 0 is correctly loaded (not confused with null/unset) + Start start = new Start(); + try { + setEnv("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS", "0"); + + JsonObject configJson = new JsonObject(); + start.updateConfigJsonFromEnv(configJson); + + assertTrue("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS env var with value 0 should be loaded", + configJson.has("postgresql_minimum_idle_connections")); + assertEquals(0, configJson.get("postgresql_minimum_idle_connections").getAsInt()); + } finally { + removeEnv("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS"); + } + } +} From f165db50f976f1283cf80fc55b481d7fb36b3add Mon Sep 17 00:00:00 2001 From: tamassoltesz Date: Tue, 17 Mar 2026 15:41:35 +0100 Subject: [PATCH 2/2] chore: build ver and changelog --- CHANGELOG.md | 4 ++++ build.gradle | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b6f89cc..ac609c0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [9.4.1] + +- Fixes env var reading with specific types + ## [9.4.0] - Adds support for bulk query APIs for usermetadata and TOTP diff --git a/build.gradle b/build.gradle index 6ceae109..26bad82d 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java-library' } -version = "9.4.0" +version = "9.4.1" repositories { mavenCentral()