Skip to content

Components & lifecycle

Every GGCommons component is built around one runtime object: GGCommons (Rust spells it GgCommons). You construct it once at startup from the standard CLI args, hold it for the lifetime of the process, and reach every subsystem through it — messaging, config, metrics, heartbeat, health, and the opt-in credentials, parameters, and streaming services. Teardown is owned by the library, not by your code.

This guide covers the three things you do with that object: build it, use its accessors, and let it shut down cleanly. For the full per-method API surface, see the API reference: entry point.

Always construct the runtime through the fluent builderGGCommonsBuilder (GgCommonsBuilder in Rust). The pattern is the same everywhere: name the component, hand it the CLI args, then build().

import com.mbreissi.ggcommons.GGCommons;
import com.mbreissi.ggcommons.GGCommonsBuilder;
public static void main(String[] args) {
// Use the FULL component name; pass argv straight through (already app-stripped).
GGCommons gg = GGCommonsBuilder.create("com.mbreissi.greengrass.JavaComponentSkeleton")
.withArgs(args)
.build();
// ... use gg ...
}

A few builder details worth knowing:

  • build() is async only in Rust and TypeScript (it connects messaging before returning). Java and Python build() are synchronous.
  • Construction is builder-first in every language. Java additionally keeps three deprecated public GGCommons(...) constructors for back-compat, and Python keeps a public GGCommons(...) constructor — but the builder is the recommended path and Rust/TS are builder-only. There is no init() facade in any language.
  • A null component name is rejected — Java build() throws IllegalStateException; Python additionally rejects an empty string (create()/the constructor raise ValueError for both empty and None).
  • withAppOptions / with_app_options let you register extra CLI options your component needs; receiveOwnMessages is covered below.

Once built, the runtime exposes a typed accessor per subsystem. The names follow each language’s convention — Java uses getX(), Python uses get_x(), Rust and TypeScript use bare x():

Subsystem Java Python Rust TypeScript
Config getConfigManager() get_config_manager() config() config()
Messaging getMessaging() get_messaging() messaging() messaging()
Metrics getMetrics() get_metrics() metrics() metrics()
Streaming getStreams() get_streams() streams() streams()
Credentials getCredentials() get_credentials() credentials() credentials()
Parameters getParameters() get_parameters() parameters() parameters()

The always-on subsystems (config, messaging, metrics) return their service directly:

var config = gg.getConfigManager(); // ConfigManager
var messaging = gg.getMessaging(); // MessagingClient
var metrics = gg.getMetrics(); // MetricEmitter

Credentials, parameters, and streaming are opt-in. The accessor returns “nothing” unless the matching section is present in your config — so a component that never configures credentials never pays for them. What “nothing” means follows each language’s idiom:

  • Java returns null.
  • Python returns None.
  • TypeScript returns undefined.
  • Rust returns Option (None) for credentials and parameters — but streams() is NOT an Option. It always returns an Arc<dyn StreamService>; that service is simply empty (no streams) when there is no streaming section. Check streams().stream_names(), not for None.
var streams = gg.getStreams(); // null if no `streaming` section
var credentials = gg.getCredentials(); // null if no `credentials` section
var parameters = gg.getParameters(); // null if no `parameters` section
if (credentials != null) {
// ... use the vault ...
}

See the per-subsystem guides for what each service does: Credentials, Parameters, and Streaming.

The runtime exposes an HTTP health endpoint (default-on for Kubernetes, opt-in elsewhere). Its /readyz probe answers a single predicate: messagingConnected && readyFlag && !shuttingDown. The readyFlag defaults to true, so a component is reported ready as soon as messaging connects.

If your component must not receive traffic until its own subscriptions (or other startup work) are established, call setReady(false) early and flip it back to true once you are ready. The flag only gates readiness — it cannot force a component ready while messaging is disconnected or during shutdown.

gg.setReady(false); // probe returns 503 while we set up
// ... subscribe to required topics ...
gg.setReady(true); // now /readyz can report ready

The most important rule on this page: the library owns the termination signal. When the Greengrass Nucleus or the kubelet stops your component, GGCommons catches the signal, flips /readyz to 503, unsubscribes every tracked subscription, and bounded-closes messaging/streams/heartbeat/vault before the process exits.

How teardown is wired differs by language:

// The library installs a JVM shutdown hook on SIGTERM + SIGINT.
// You do NOT add your own hook. An explicit call is optional and idempotent:
gg.shutdown(); // idempotent (guarded by an atomic CAS)

receiveOwnMessages controls whether a component receives messages it published itself (relevant when a component both publishes and subscribes to the same topic). It defaults to true and is set on the builder.

GGCommons gg = GGCommonsBuilder.create("com.example.MyComponent")
.withArgs(args)
.receiveOwnMessages(false) // honored on the IPC transport
.build();