Provide environment variables for config options (closes #161)
Change-Id: Iacb5902f4206fbf0a7a5bd6979aae4fe7a3be914
diff --git a/Changes b/Changes
index 30d50bc..42d6bb0 100644
--- a/Changes
+++ b/Changes
@@ -1,3 +1,6 @@
+ - Support environment variables overriding configuration properties.
+ (closes #161)(diewald)
+
0.3.3 2026-01-29
- Introduce announcements (diewald)
diff --git a/Dockerfile b/Dockerfile
index 5da636d..7b41b18 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,7 +23,7 @@
RUN addgroup -S korap && \
adduser -S export -G korap && \
mkdir export && \
- chown -R export.korap /export
+ chown -R export:korap /export
WORKDIR /export
diff --git a/README.md b/README.md
index bf4892c..ac8887e 100644
--- a/README.md
+++ b/README.md
@@ -129,9 +129,69 @@
Alternatively a file named `exportPlugin.conf` can be stored in the
same directory as the java jar.
+### Environment Variables
+
+Configuration can also be set via environment variables, which take precedence over
+configuration file values. This is particularly useful for Docker deployments and
+containerized environments.
+
+The priority order is (highest to lowest):
+1. Environment variables
+2. Custom configuration file (if provided as argument)
+3. Default configuration file (`exportPlugin.conf`)
+
+### Configuration Reference
+
+The following configuration options are available. Each can be set either in a
+configuration file (using the property name) or via an environment variable:
+
+#### Server Configuration
+
+- `server.port` or `KALAMAR_EXPORT_SERVER_PORT`: Port of the export server (default: `7777`)
+- `server.host` or `KALAMAR_EXPORT_SERVER_HOST`: Host address of the server (default: `localhost`)
+- `server.scheme` or `KALAMAR_EXPORT_SERVER_SCHEME`: URL scheme for the server (default: `https`)
+- `server.origin` or `KALAMAR_EXPORT_SERVER_ORIGIN`: CORS origin for SSE responses (default: `*`)
+
+#### API Configuration
+
+- `api.port` or `KALAMAR_EXPORT_API_PORT`: Port of the KorAP API backend (default: `443`)
+- `api.host` or `KALAMAR_EXPORT_API_HOST`: Host address of the KorAP API backend (default: `korap.ids-mannheim.de`)
+- `api.scheme` or `KALAMAR_EXPORT_API_SCHEME`: URL scheme for the API backend (default: `https`)
+- `api.source` or `KALAMAR_EXPORT_API_SOURCE`: Source string for exports, useful when running behind a proxy (optional)
+- `api.path` or `KALAMAR_EXPORT_API_PATH`: Additional path prefix for the API (default: empty)
+
+#### Asset Configuration
+
+- `asset.host` or `KALAMAR_EXPORT_ASSET_HOST`: Host address for assets/stylesheets (default: `korap.ids-mannheim.de`)
+- `asset.port` or `KALAMAR_EXPORT_ASSET_PORT`: Port for assets (default: empty, uses default port)
+- `asset.scheme` or `KALAMAR_EXPORT_ASSET_SCHEME`: URL scheme for assets (default: `https`)
+- `asset.path` or `KALAMAR_EXPORT_ASSET_PATH`: Path prefix for assets (default: empty)
+
+#### Export Configuration
+
+- `conf.page_size` or `KALAMAR_EXPORT_PAGE_SIZE`: Number of matches to fetch per API request (default: `5`)
+- `conf.max_exp_limit` or `KALAMAR_EXPORT_MAX_EXP_LIMIT`: Maximum number of matches allowed per export (default: `10000`)
+- `conf.file_dir` or `KALAMAR_EXPORT_FILE_DIR`: Directory for temporary export files (default: system temp directory)
+- `conf.default_hitc` or `KALAMAR_EXPORT_DEFAULT_HITC`: Default number of hits in the export form (default: `100`)
+
+#### Cookie Configuration
+
+- `cookie.name` or `KALAMAR_EXPORT_COOKIE_NAME`: Name of the Kalamar session cookie (default: `kalamar`)
+
+### Docker Example
+
+When running in Docker, you can set environment variables:
+
+```shell
+docker run -e KALAMAR_EXPORT_SERVER_PORT=8080 \
+ -e KALAMAR_EXPORT_API_HOST=api.example.com \
+ -e KALAMAR_EXPORT_MAX_EXP_LIMIT=50000 \
+ kalamar-export-plugin
+```
+
## License
-Copyright (c) 2020-2024, [IDS Mannheim](https://www.ids-mannheim.de/), Germany
+Copyright (c) 2020-2026, [IDS Mannheim](https://www.ids-mannheim.de/), Germany
Kalamar-Plugin-Export is developed as part of the [KorAP](https://korap.ids-mannheim.de/)
Corpus Analysis Platform at the Leibniz Institute for the German Language
diff --git a/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java b/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java
index d83c434..77801dc 100644
--- a/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java
+++ b/src/main/java/de/ids_mannheim/korap/plkexport/ExWSConf.java
@@ -10,7 +10,10 @@
import java.io.*;
import java.lang.String;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
+import java.util.function.Function;
import org.tinylog.Logger;
@@ -21,6 +24,41 @@
private static Properties prop;
+ // Environment provider function (can be overridden for testing)
+ private static Function<String, String> envProvider = System::getenv;
+
+ // Mapping from environment variable names to property names
+ private static final Map<String, String> ENV_TO_PROP = new HashMap<>();
+ static {
+ // Server configuration
+ ENV_TO_PROP.put("KALAMAR_EXPORT_SERVER_PORT", "server.port");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_SERVER_HOST", "server.host");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_SERVER_SCHEME", "server.scheme");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_SERVER_ORIGIN", "server.origin");
+
+ // API configuration
+ ENV_TO_PROP.put("KALAMAR_EXPORT_API_PORT", "api.port");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_API_HOST", "api.host");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_API_SCHEME", "api.scheme");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_API_SOURCE", "api.source");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_API_PATH", "api.path");
+
+ // Asset configuration
+ ENV_TO_PROP.put("KALAMAR_EXPORT_ASSET_HOST", "asset.host");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_ASSET_PORT", "asset.port");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_ASSET_SCHEME", "asset.scheme");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_ASSET_PATH", "asset.path");
+
+ // General configuration
+ ENV_TO_PROP.put("KALAMAR_EXPORT_PAGE_SIZE", "conf.page_size");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_MAX_EXP_LIMIT", "conf.max_exp_limit");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_FILE_DIR", "conf.file_dir");
+ ENV_TO_PROP.put("KALAMAR_EXPORT_DEFAULT_HITC", "conf.default_hitc");
+
+ // Cookie configuration
+ ENV_TO_PROP.put("KALAMAR_EXPORT_COOKIE_NAME", "cookie.name");
+ }
+
/*
* Returns version of the Export Plugin
*/
@@ -51,6 +89,20 @@
prop = null;
}
+ /*
+ * Sets a custom environment provider function.
+ * This is useful for testing environment variable overrides
+ * without actually setting system environment variables.
+ * Pass null to reset to the default System.getenv provider.
+ */
+ public static void setEnvironmentProvider(Function<String, String> provider) {
+ if (provider == null) {
+ envProvider = System::getenv;
+ } else {
+ envProvider = provider;
+ }
+ }
+
/**
*Loads properties from a UTF-8 encoded file
*/
@@ -94,6 +146,8 @@
* Returns export properties
* The properties in exportPlugin.conf are the default properties
* which can be overwritten by the properties in propFile.
+ * Environment variables have the highest priority and override both
+ * config file values.
*/
public static Properties properties (String propFile) {
@@ -106,8 +160,39 @@
if (propFile != null){
loadProp(prop, propFile);
}
+
+ // Apply environment variable overrides
+ applyEnvironmentOverrides(prop);
return prop;
};
+ /*
+ * Apply environment variable overrides to the properties.
+ * Environment variables have the highest priority.
+ */
+ private static void applyEnvironmentOverrides(Properties props) {
+ for (Map.Entry<String, String> entry : ENV_TO_PROP.entrySet()) {
+ String envValue = getEnvironmentVariable(entry.getKey());
+ if (envValue != null && !envValue.isEmpty()) {
+ props.setProperty(entry.getValue(), envValue);
+ }
+ }
+ }
+
+ /*
+ * Get an environment variable value using the configured provider.
+ */
+ protected static String getEnvironmentVariable(String name) {
+ return envProvider.apply(name);
+ }
+
+ /*
+ * Returns the mapping of environment variable names to property names.
+ * Useful for documentation and testing.
+ */
+ public static Map<String, String> getEnvToPropertyMapping() {
+ return new HashMap<>(ENV_TO_PROP);
+ }
+
}
diff --git a/src/test/java/de/ids_mannheim/korap/plkexport/ExWSConfEnvTest.java b/src/test/java/de/ids_mannheim/korap/plkexport/ExWSConfEnvTest.java
new file mode 100644
index 0000000..8df2693
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/plkexport/ExWSConfEnvTest.java
@@ -0,0 +1,443 @@
+package de.ids_mannheim.korap.plkexport;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test suite for environment variable overrides in ExWSConf.
+ * Tests that environment variables can override configuration file values
+ * and have higher priority than config files.
+ */
+public class ExWSConfEnvTest {
+
+ private Map<String, String> mockEnv;
+
+ @Before
+ public void setUp() {
+ // Create a mock environment map for each test
+ mockEnv = new HashMap<>();
+
+ // Clear any previously loaded properties
+ ExWSConf.clearProp();
+
+ // Reset to default environment provider
+ ExWSConf.setEnvironmentProvider(null);
+ }
+
+ @After
+ public void tearDown() {
+ // Reset state after each test
+ ExWSConf.clearProp();
+ ExWSConf.setEnvironmentProvider(null);
+ }
+
+ /**
+ * Test that the environment-to-property mapping contains all expected entries
+ */
+ @Test
+ public void testEnvMappingContainsAllExpectedVariables() {
+ Map<String, String> mapping = ExWSConf.getEnvToPropertyMapping();
+
+ // Server configuration
+ assertEquals("server.port", mapping.get("KALAMAR_EXPORT_SERVER_PORT"));
+ assertEquals("server.host", mapping.get("KALAMAR_EXPORT_SERVER_HOST"));
+ assertEquals("server.scheme", mapping.get("KALAMAR_EXPORT_SERVER_SCHEME"));
+ assertEquals("server.origin", mapping.get("KALAMAR_EXPORT_SERVER_ORIGIN"));
+
+ // API configuration
+ assertEquals("api.port", mapping.get("KALAMAR_EXPORT_API_PORT"));
+ assertEquals("api.host", mapping.get("KALAMAR_EXPORT_API_HOST"));
+ assertEquals("api.scheme", mapping.get("KALAMAR_EXPORT_API_SCHEME"));
+ assertEquals("api.source", mapping.get("KALAMAR_EXPORT_API_SOURCE"));
+ assertEquals("api.path", mapping.get("KALAMAR_EXPORT_API_PATH"));
+
+ // Asset configuration
+ assertEquals("asset.host", mapping.get("KALAMAR_EXPORT_ASSET_HOST"));
+ assertEquals("asset.port", mapping.get("KALAMAR_EXPORT_ASSET_PORT"));
+ assertEquals("asset.scheme", mapping.get("KALAMAR_EXPORT_ASSET_SCHEME"));
+ assertEquals("asset.path", mapping.get("KALAMAR_EXPORT_ASSET_PATH"));
+
+ // General configuration
+ assertEquals("conf.page_size", mapping.get("KALAMAR_EXPORT_PAGE_SIZE"));
+ assertEquals("conf.max_exp_limit", mapping.get("KALAMAR_EXPORT_MAX_EXP_LIMIT"));
+ assertEquals("conf.file_dir", mapping.get("KALAMAR_EXPORT_FILE_DIR"));
+ assertEquals("conf.default_hitc", mapping.get("KALAMAR_EXPORT_DEFAULT_HITC"));
+
+ // Cookie configuration
+ assertEquals("cookie.name", mapping.get("KALAMAR_EXPORT_COOKIE_NAME"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_SERVER_PORT environment variable overrides server.port
+ */
+ @Test
+ public void testServerPortEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "9999");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("9999", props.getProperty("server.port"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_SERVER_HOST environment variable overrides server.host
+ */
+ @Test
+ public void testServerHostEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_SERVER_HOST", "custom.host.example.com");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("custom.host.example.com", props.getProperty("server.host"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_SERVER_SCHEME environment variable overrides server.scheme
+ */
+ @Test
+ public void testServerSchemeEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_SERVER_SCHEME", "http");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("http", props.getProperty("server.scheme"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_API_PORT environment variable overrides api.port
+ */
+ @Test
+ public void testApiPortEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_API_PORT", "8080");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("8080", props.getProperty("api.port"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_API_HOST environment variable overrides api.host
+ */
+ @Test
+ public void testApiHostEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_API_HOST", "api.custom.example.com");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("api.custom.example.com", props.getProperty("api.host"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_API_SCHEME environment variable overrides api.scheme
+ */
+ @Test
+ public void testApiSchemeEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_API_SCHEME", "http");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("http", props.getProperty("api.scheme"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_API_SOURCE environment variable sets api.source
+ */
+ @Test
+ public void testApiSourceEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_API_SOURCE", "custom-source.example.com");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("custom-source.example.com", props.getProperty("api.source"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_API_PATH environment variable sets api.path
+ */
+ @Test
+ public void testApiPathEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_API_PATH", "/custom/api/path");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("/custom/api/path", props.getProperty("api.path"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_ASSET_HOST environment variable overrides asset.host
+ */
+ @Test
+ public void testAssetHostEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_ASSET_HOST", "assets.custom.example.com");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("assets.custom.example.com", props.getProperty("asset.host"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_ASSET_PORT environment variable sets asset.port
+ */
+ @Test
+ public void testAssetPortEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_ASSET_PORT", "8888");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("8888", props.getProperty("asset.port"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_ASSET_SCHEME environment variable overrides asset.scheme
+ */
+ @Test
+ public void testAssetSchemeEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_ASSET_SCHEME", "http");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("http", props.getProperty("asset.scheme"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_ASSET_PATH environment variable sets asset.path
+ */
+ @Test
+ public void testAssetPathEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_ASSET_PATH", "/custom/asset/path");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("/custom/asset/path", props.getProperty("asset.path"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_PAGE_SIZE environment variable overrides conf.page_size
+ */
+ @Test
+ public void testPageSizeEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_PAGE_SIZE", "25");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("25", props.getProperty("conf.page_size"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_MAX_EXP_LIMIT environment variable overrides conf.max_exp_limit
+ */
+ @Test
+ public void testMaxExpLimitEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_MAX_EXP_LIMIT", "50000");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("50000", props.getProperty("conf.max_exp_limit"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_FILE_DIR environment variable sets conf.file_dir
+ */
+ @Test
+ public void testFileDirEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_FILE_DIR", "/custom/export/dir");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("/custom/export/dir", props.getProperty("conf.file_dir"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_DEFAULT_HITC environment variable overrides conf.default_hitc
+ */
+ @Test
+ public void testDefaultHitcEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_DEFAULT_HITC", "500");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("500", props.getProperty("conf.default_hitc"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_SERVER_ORIGIN environment variable sets server.origin
+ */
+ @Test
+ public void testServerOriginEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_SERVER_ORIGIN", "https://custom.origin.example.com");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("https://custom.origin.example.com", props.getProperty("server.origin"));
+ }
+
+ /**
+ * Test that KALAMAR_EXPORT_COOKIE_NAME environment variable sets cookie.name
+ */
+ @Test
+ public void testCookieNameEnvOverride() {
+ mockEnv.put("KALAMAR_EXPORT_COOKIE_NAME", "custom_cookie_name");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+ assertEquals("custom_cookie_name", props.getProperty("cookie.name"));
+ }
+
+ /**
+ * Test that environment variables override values from configuration files
+ */
+ @Test
+ public void testEnvOverridesConfigFile() {
+ // First, get default config value
+ ExWSConf.clearProp();
+ ExWSConf.setEnvironmentProvider(name -> null); // No env vars
+ Properties propsWithoutEnv = ExWSConf.properties(null);
+ String defaultPort = propsWithoutEnv.getProperty("server.port");
+
+ // Now set environment variable to different value
+ ExWSConf.clearProp();
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "12345");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties propsWithEnv = ExWSConf.properties(null);
+ String envPort = propsWithEnv.getProperty("server.port");
+
+ assertEquals("12345", envPort);
+ assertNotEquals(defaultPort, envPort);
+ }
+
+ /**
+ * Test that environment variables also override values from additional config file
+ */
+ @Test
+ public void testEnvOverridesSecondaryConfigFile() {
+ // Set environment variable
+ mockEnv.put("KALAMAR_EXPORT_PAGE_SIZE", "999");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ // Load with secondary config file that also sets page_size
+ Properties props = ExWSConf.properties("exportPluginSec.conf");
+
+ // Environment should win
+ assertEquals("999", props.getProperty("conf.page_size"));
+ }
+
+ /**
+ * Test that empty environment variables do not override config values
+ */
+ @Test
+ public void testEmptyEnvDoesNotOverride() {
+ // Set empty environment variable
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+
+ // Should use config file value, not empty string
+ assertNotEquals("", props.getProperty("server.port"));
+ }
+
+ /**
+ * Test that null environment variables do not override config values
+ */
+ @Test
+ public void testNullEnvDoesNotOverride() {
+ // Set up provider that returns null for all variables
+ ExWSConf.setEnvironmentProvider(name -> null);
+
+ Properties props = ExWSConf.properties(null);
+
+ // Should use config file values
+ assertEquals("1024", props.getProperty("server.port"));
+ assertEquals("localhost", props.getProperty("server.host"));
+ }
+
+ /**
+ * Test multiple environment variables being set at once
+ */
+ @Test
+ public void testMultipleEnvOverrides() {
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "7777");
+ mockEnv.put("KALAMAR_EXPORT_SERVER_HOST", "multi.test.com");
+ mockEnv.put("KALAMAR_EXPORT_API_PORT", "8888");
+ mockEnv.put("KALAMAR_EXPORT_PAGE_SIZE", "50");
+ mockEnv.put("KALAMAR_EXPORT_MAX_EXP_LIMIT", "100000");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+
+ assertEquals("7777", props.getProperty("server.port"));
+ assertEquals("multi.test.com", props.getProperty("server.host"));
+ assertEquals("8888", props.getProperty("api.port"));
+ assertEquals("50", props.getProperty("conf.page_size"));
+ assertEquals("100000", props.getProperty("conf.max_exp_limit"));
+ }
+
+ /**
+ * Test that properties not set via environment use config file values
+ */
+ @Test
+ public void testNonOverriddenPropertiesRetainConfigValues() {
+ // Only override one property
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "9876");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+
+ // Overridden property
+ assertEquals("9876", props.getProperty("server.port"));
+
+ // Non-overridden properties should retain config file values
+ assertEquals("localhost", props.getProperty("server.host"));
+ assertEquals("https", props.getProperty("server.scheme"));
+ }
+
+ /**
+ * Test that environment variables work with numeric values as strings
+ */
+ @Test
+ public void testNumericEnvValues() {
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "65535");
+ mockEnv.put("KALAMAR_EXPORT_PAGE_SIZE", "100");
+ mockEnv.put("KALAMAR_EXPORT_MAX_EXP_LIMIT", "1000000");
+ mockEnv.put("KALAMAR_EXPORT_DEFAULT_HITC", "250");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties props = ExWSConf.properties(null);
+
+ // Verify these can be parsed as integers
+ assertEquals(65535, Integer.parseInt(props.getProperty("server.port")));
+ assertEquals(100, Integer.parseInt(props.getProperty("conf.page_size")));
+ assertEquals(1000000, Integer.parseInt(props.getProperty("conf.max_exp_limit")));
+ assertEquals(250, Integer.parseInt(props.getProperty("conf.default_hitc")));
+ }
+
+ /**
+ * Test resetting environment provider to default
+ */
+ @Test
+ public void testResetEnvironmentProvider() {
+ // Set mock provider
+ mockEnv.put("KALAMAR_EXPORT_SERVER_PORT", "1111");
+ ExWSConf.setEnvironmentProvider(mockEnv::get);
+
+ Properties propsWithMock = ExWSConf.properties(null);
+ assertEquals("1111", propsWithMock.getProperty("server.port"));
+
+ // Reset and reload
+ ExWSConf.clearProp();
+ ExWSConf.setEnvironmentProvider(null); // Reset to System.getenv
+
+ Properties propsReset = ExWSConf.properties(null);
+ // Should use config file value (assuming no actual env var is set)
+ assertEquals("1024", propsReset.getProperty("server.port"));
+ }
+}