Skip to content

Quickstart

This guide takes you from an empty directory to a running Greengrass v2 component talking to a local MQTT broker. You will scaffold a component with the ggcommons CLI, look at what it generated, wire up the bootstrap code, build it, and run it on the HOST platform.

Pick your language with the tabs in each code block — the tabs stay in sync across the page.

  1. The scaffolding CLI is a Python tool, and each language has its own toolchain. At a minimum you need git, Python 3.9+ (to run the CLI), Docker (for the local MQTT broker), and the toolchain for the language you are targeting:

    • Java — JDK 25 and Maven. (The library targets Java 25, so the JDK must be 25 even though the generated component compiles to an older bytecode level.)
    • Python — Python 3.9+.
    • Rust — a rustup toolchain. The generated component crate is edition 2021 / MSRV 1.75.
    • TypeScript — Node 18+ and npm.

    See the Installation guide for full setup, including how to make the ggcommons library resolvable for each language. Once the toolchain is in place, install the CLI and confirm your environment:

Terminal window
# From the monorepo root — installs the `ggcommons` / `ggcommons-cli` commands.
pipx install ./cli # or: python -m pip install ./cli
ggcommons doctor # reports git, gdk, cargo, mvn, python3, node, npm, aws

ggcommons doctor checks eight tools and prints [ok] <name> -> <path> or [missing] <name> for each. It only reports status — a missing tool you do not need for your language will not stop you.

  1. ggcommons create-component generates a component from a bundled template. Templates ship inside the CLI, so scaffolding works offline. The output directory is <path>/<ComponentName>, where ComponentName is the last dot-segment of the name you pass (com.example.MyComponent produces a MyComponent/ directory).

    The interactive wizard prompts for everything (and starts automatically if you omit -n on a terminal):

Terminal window
ggcommons create-component -i

Or pass the flags directly. Use -l to choose the language (JAVA, PYTHON, RUST, or TYPESCRIPT):

Terminal window
# Choose -l to match the language tab you are following.
ggcommons create-component -n com.example.MyComponent -l JAVA
# -l PYTHON | -l RUST | -l TYPESCRIPT

On success the CLI prints Done. Component generated at: <dir>. By default the component targets all platforms (--platforms GREENGRASS,HOST,KUBERNETES) and uses a local library dependency (--dep-source local). The Kubernetes artifacts (Dockerfile, k8s/) are only emitted when KUBERNETES is among the selected platforms.

  1. The layout differs slightly per language, but every component carries your business-logic file, a build manifest, the Greengrass recipe.yaml + gdk-config.json, and sample configs under test-configs/.

MyComponent/
├─ src/main/java/.../MyComponent.java # your business logic
├─ pom.xml # Maven build (shaded JAR)
├─ recipe.yaml gdk-config.json # Greengrass recipe + GDK config
└─ test-configs/MyComponent.json # sample component config
  1. The entry point builds one GGCommons runtime from the standard CLI args, then reads each subsystem off it via typed accessors. The accessor names follow each language’s conventions (getMessaging() / get_messaging() / messaging()), but the shape is the same everywhere.

import com.mbreissi.ggcommons.GGCommons;
import com.mbreissi.ggcommons.GGCommonsBuilder;
public class MyComponent {
public static void main(String[] args) {
// Build the runtime from the standard CLI args (use the FULL component name).
GGCommons gg = GGCommonsBuilder.create("com.example.MyComponent")
.withArgs(args)
.build();
var config = gg.getConfigManager();
var messaging = gg.getMessaging();
var metrics = gg.getMetrics();
// ... your business logic ...
// Do NOT register your own shutdown hook: the library wires SIGTERM/SIGINT to a
// graceful, idempotent shutdown() for you.
}
}

The shipped Java template uses the deprecated direct constructor (new GGCommons(name, args)); the builder shown here is the canonical convention and is what the worked example uses.

  1. Build with your language’s standard toolchain. These commands are the same on Linux and Windows (forward-slash paths work in PowerShell too).

Terminal window
mvn clean package # produces target/MyComponent-1.0.0.jar (shaded, self-contained)
  1. The HOST platform with the MQTT transport connects to a local broker (and, optionally, to AWS IoT Core). Bring up the EMQX broker that ships with the repo — it exposes 1883 (plaintext) and 8883 (mutual TLS):

Terminal window
docker compose -f test-infra/compose.yaml up -d
# Or a throwaway broker anywhere: docker run -d -p 1883:1883 emqx/emqx:latest

The MQTT transport needs a small messaging-config JSON (the --transport MQTT <path> payload): messaging.local is required and messaging.iotCore is optional. Each running process needs a unique clientId. The Rust and TypeScript templates already ship one at test-configs/standalone-messaging.json; for Java and Python, create a standalone-messaging.json in the component directory:

{
"messaging": {
"local": {
"host": "localhost",
"port": 1883,
"clientId": "my-component-local"
}
}
}
  1. Start the component on the HOST platform, pointing --transport MQTT at the messaging config and -c FILE at a component config, with a Thing name via -t. Run from inside the generated component directory.

Terminal window
java -jar target/MyComponent-1.0.0.jar \
--platform HOST --transport MQTT ./standalone-messaging.json \
-c FILE test-configs/MyComponent.json -t my-thing

To confirm the component is alive, subscribe to heartbeat/+/+ on the broker (for example with MQTTX) and watch the periodic heartbeat messages arrive.