Skip to content

Parameters API

API reference for the opt-in parameters subsystem. This page lists the public surface verified against source; for the conceptual model, refresh semantics, and config keys, read the Parameters guide.

The subsystem is opt-in: the gg accessor returns nothing unless a parameters section is present in the active config (Rust additionally requires the parameters cargo feature). Reads are always served from a local cache — the network is touched only on refresh().

Fetch the ParameterService from your GGCommons instance. It is null / None / undefined when the parameters section is absent (Rust: also when the parameters feature is off). Depend on the ParameterService interface, not the concrete DefaultParameterService.

SDK Accessor Returns Empty when
Java ParameterService getParameters() ParameterService or null no parameters section
Python get_parameters() service or None no parameters section
Rust fn parameters(&self) -> Option<Arc<dyn ParameterService>> Some / None no section or parameters feature off
TypeScript parameters(): ParameterService | undefined service or undefined no parameters section

The gg instance owns the service lifecycle — it stops the background refresher at component shutdown — so you do not call close() yourself on the accessor-returned service.

The Rust accessor is compiled in only with the parameters feature; the awsSsm source additionally needs parameters-aws. Without parameters, gg.parameters() always returns None.

[dependencies]
ggcommons = { version = "*", features = ["parameters"] }
# add "parameters-aws" as well to use the awsSsm source

The interface to depend on. Six core methods plus four typed accessors (default/concrete methods that parse the underlying string). Signatures as they appear in source:

public interface ParameterService {
Optional<String> get(String name);
Optional<byte[]> getBytes(String name);
Map<String, String> getByPath(String path); // path = prefix; no recursive arg
List<String> names(String prefix); // pass "" for all
void refresh();
ParameterStats stats();
// typed accessors (default methods on the interface)
default Optional<Long> getInt(String name);
default Optional<Boolean> getBool(String name);
default Optional<JsonElement> getJson(String name);
default Optional<List<String>> getStringList(String name);
}

These hold in all four SDKs unless noted:

  • get(name) — the cached value of name decoded as a UTF-8 string. Errors on a non-UTF-8 value.
  • getBytes(name) — the raw value bytes (no decoding).
  • getByPath(path) — every cached parameter under the path prefix as a name -> string map. path is a prefix only; there is no recursive argument at read time (recursion is fixed by sync.paths at config time). Non-UTF-8 entries are silently skipped.
  • names(prefix) — cached parameter names under prefix (metadata only, no values). The prefix argument is required — pass "" to list everything.
  • refresh() — pulls the declared sync.names + sync.paths from the source into the cache. Async (Promise<void>) in TypeScript; synchronous in Java, Python, and Rust.
  • stats() — a non-sensitive ParameterStats snapshot, safe to log.
  • Typed accessors parse the underlying string. getInt is Long (Java, 64-bit), int (Python, arbitrary precision), i64 (Rust), number (TypeScript — IEEE-754, loses precision above 2^53; validated with a strict ^[+-]?\d+$ regex first). getBool accepts true/1/yes/on and false/0/no/off (case-insensitive). getStringList comma-splits and trims; an empty string yields an empty list. All reject malformed values.
  • Orderingnames / getByPath results are sorted in Java (TreeMap), Python (sorted), and Rust (BTreeMap). The TypeScript in-memory cache returns insertion order.

A complete read example. Parameters are addressed by SSM-style path names like /myapp/region.

ParameterService params = gg.getParameters();
if (params == null) return; // parameters subsystem is off
Optional<String> region = params.get("/myapp/region");
Optional<Long> poolSize = params.getInt("/myapp/poolSize");
Optional<Boolean> debug = params.getBool("/myapp/debug");
Map<String, String> db = params.getByPath("/myapp/db");
List<String> all = params.names(""); // every cached name
LOGGER.info("parameter subsystem stats [{}]", params.stats());

open / open_from_config / openFromConfig build a DefaultParameterService from a parsed parameters config section. The gg accessor calls these for you (after resolving template variables); call them directly only when wiring the service yourself.

SDK Signature
Java static DefaultParameterService open(JsonObject parametersConfig) · static DefaultParameterService open(JsonObject parametersConfig, String namespace)
Python open_from_config(parameters_cfg: dict, namespace: str = "") -> DefaultParameterService
Rust pub fn open(config: &ParametersConfig) -> Result<DefaultParameterService>
TypeScript async function openFromConfig(cfg: ParametersConfig = {}): Promise<DefaultParameterService>

Notes:

  • The namespace argument exists only in Java and Python, and is deliberately ignored. It is present for signature parity with Credentials.open; parameter keys are never namespaced (isolation comes from the per-component templated cache.path). Rust open and TypeScript openFromConfig take no namespace argument.
  • TypeScript openFromConfig is async (Promise) because building a remote source or KMS key provider is promise-based. The other three are synchronous.
  • The default cache.path when unset is the relative "param-cache". The accessor path substitutes template variables such as {ComponentFullName} and {ThingName} before calling the factory; the raw factory does no templating.

DefaultParameterService factories and lifecycle

Section titled “DefaultParameterService factories and lifecycle”

The concrete implementation. Use these static/builder factories to inject a custom ParameterSource (the only way to do so — config and the gg accessor know only the three built-in source types).

SDK Factories and lifecycle
Java withMemoryCache(source, syncNames, syncPaths) · withPersistentCache(source, LocalVault, Object lock, syncNames, syncPaths) · withRefresh(long intervalSecs) (returns this) · close() (AutoCloseable, stops the daemon)
Python with_memory_cache(source, sync_names, sync_paths) · with_persistent_cache(source, vault, lock, sync_names, sync_paths) · with_refresh(interval_secs) · close()
Rust with_memory_cache(source, sync_names, sync_paths) · with_persistent_cache(source, Arc<Mutex<LocalVault>>, sync_names, sync_paths) · with_refresh(interval_secs) (consumes + returns self) · no close()Refresher::drop stops + joins the thread (RAII)
TypeScript static withMemoryCache(...) · static withPersistentCache(source, vault, syncNames, syncPaths) · withRefresh(intervalSecs): this · close(): void

The syncPaths element is a (path, recursive) pair: Java List<Map.Entry<String, Boolean>>, Python List[Tuple[str, bool]], Rust Vec<(String, bool)>, TypeScript SyncPath = [string, boolean].

DefaultParameterService s = DefaultParameterService.withMemoryCache(
myCustomSource, List.of("/myapp/region"), List.of());
s.refresh();
// ... use s ...
s.close(); // you own the lifecycle when you build it yourself

A ParameterSource is the pluggable seam between the network/filesystem and the cache. There are three config-selectable built-ins — env, mountedDir, and awsSsm only (there is no custom config type). See the Parameters guide for config examples.

The ParameterSource interface:

  • fetch(name) -> Option<ParamValue>
  • fetchByPath(path, recursive) -> [(name, ParamValue)]
  • sourceId() -> "env" | "mountedDir" | "awsSsm"

In TypeScript fetch / fetchByPath are async (Promise). In Java, Python, and Rust they are synchronous (the Rust SSM implementation block_ons an internal runtime).

Source Constructor Behavior
EnvSource EnvSource(prefix) Maps a name to an env var: /myapp/db/host<PREFIX>MYAPP_DB_HOST (/, -, ._, uppercased). Always non-secure. Default prefix = "GG_PARAM_".
MountedDirSource MountedDirSource(root, securePaths) Each file under root is a parameter (bytes = value; name = / + path relative to root). A name under any securePaths prefix is secure=true. version is always null. Dotfiles are skipped (the kubelet ..data symlink farm); a directory at a name is “not a parameter”.
AwsSsmSource AwsSsmSource(region, endpointUrl, withDecryption=true) GetParameter / GetParametersByPath (paginated) with WithDecryption. SecureStringsecure=true; version = SSM version. Uses the default credential chain (TES on Greengrass). endpointUrl overrides for floci / LocalStack / a VPC endpoint.

The AWS SDK for SSM is an optional dependency in every SDK, but enforced differently:

  • Rust — feature-gated at compile time. awsSsm requires the parameters-aws feature; without it, build_source("awsSsm") errors (the message names only env / mountedDir as available).
  • Java / Python / TypeScript — loaded lazily at runtime: Java software.amazon.awssdk:ssm, Python boto3, TypeScript @aws-sdk/client-ssm (an optionalDependency). A missing dependency surfaces as a parameter error at first use.

The value type a source returns. Component developers rarely handle it directly — the typed accessors hand back plain strings, ints, and so on — but it is the source↔cache seam.

ParamValue {
value: bytes // the raw parameter value
secure: bool // set automatically: securePaths (mountedDir) or SecureString (awsSsm)
version: Option<String> // source-assigned version, when available
}
SDK Type + plain constructor Redaction on log
Java ParamValue record; plain(byte[]), plain(String) toString() redacts the value
Python ParamValue; ParamValue.plain(value) __repr__ redacts the value
Rust ParamValue; ParamValue::plain(...) derives Debugdoes NOT redact (raw bytes print)
TypeScript ParamValue interface; plainValue(value) plain interface — no redaction (the value buffer prints)

A non-sensitive observability snapshot returned by stats() — safe to log.

Field (Java / TS · Python / Rust) Type Meaning
parameterCount · parameter_count long / u64 / int Number of parameters currently cached.
lastRefreshAgeMs · last_refresh_age_ms nullable Long / Option<u64> / int Age of the last fully-clean refresh. null / None / undefined until the first fully-successful refresh.
refreshFailures · refresh_failures long / u64 / int Cumulative per-item refresh-failure count.
source String The active source id (env / mountedDir / awsSsm).

Type definitions:

  • Java — record ParameterStats(long parameterCount, Long lastRefreshAgeMs, long refreshFailures, String source)
  • Python — @dataclass ParameterStats
  • Rust — pub struct ParameterStats { parameter_count: u64, last_refresh_age_ms: Option<u64>, refresh_failures: u64, source: String }
  • TypeScript — interface ParameterStats

A quick reference to the differences that affect calling code:

  • TypeScript is async where the others are sync. refresh() returns Promise<void>, openFromConfig is async, and ParameterSource.fetch / fetchByPath return promises. The read accessors (get, getBytes, getByPath, names, typed getters) are still synchronous in TypeScript — they read the already-loaded cache.
  • Rust reads return Result. Every method is Result<…>; the other SDKs throw/raise.
  • Rust gates the subsystem behind cargo features (parameters, plus parameters-aws for SSM).
  • namespace exists only in Java/Python open and is ignored.
  • Lifecycle: Java/Python/TypeScript expose close(); Rust uses RAII (drop stops the refresher).
  • ParamValue redaction is enforced only in Java and Python.
  • names / getByPath ordering is sorted in Java/Python/Rust, insertion order in TypeScript.