๐ข Beginner: Stand up the lab#
Wire the OpenFeature Java SDK and the flagd contrib provider into a Spring Boot service so flag evaluations are resolved by a flagd sidecar against a flags.json file. Author your first flag, then prove that editing flags.json flips the response on the next request โ no app restart, no flagd restart, no redeploy.
The Spring Boot service runs on :8080; a flagd container is already running on :8013; flags.json is an empty skeleton ({"flags": {}}). The SDK is not wired in yet โ that's your job.
๐ Shoutout: This challenge was created by Simon Schrottner โ thank you!
๐ช The Backstory#
The lab is on its first shift and it isn't reading the chart. Every subject who walks through the door gets the same hard-coded reading on their record โ no matter what the lab director just signed off on. The label coming out of the lab is a literal string baked into the controller, not a reading pulled from the chart.
Your mission: replace that hard-coded label with an OpenFeature client, point that client at the flagd sidecar that already runs next to your Codespace, and let flags.json drive what gets recorded as the subject's vision_state. While you're at it, prove the lab can change what it records without restarting anything โ edit flags.json, save, and the next subject through the door has the new reading on their chart.
๐๏ธ Architecture#
This level runs as two containers side-by-side in your Codespace โ the Spring Boot lab and a flagd sidecar.
- Spring Boot service (the lab) โ a Spring Boot 4 service on
http://localhost:8080/with one endpoint,GET /. Today it returns a hard-coded"untreated"literal fromTrial. flags.jsonโ a flag-definition file in the level folder, mounted read-only into the flagd sidecar. The participant edits it through the IDE; flagd's file watcher picks up the change.- flagd sidecar โ
ghcr.io/open-feature/flagd:v0.15.4, started by the devcontainer compose stack. It serves flag evaluations over gRPC on:8013, watchesflags.jsonon disk, and reloads when it changes. - OpenFeature SDK + flagd contrib provider โ the OpenFeature Java SDK plus the flagd contrib provider in
Resolver.RPCmode. The provider readsFLAGD_HOST=flagd/FLAGD_PORT=8013from the environment (the compose file pre-sets them), so there is no host or port to hard-code.
๐ฏ Objective#
By the end of this level, you should:
- Have
curl http://localhost:8080/return avision_statereading resolved fromflags.json(not the hard-coded"untreated"fallback) - Confirm the response payload includes the OpenFeature evaluation details โ flag key, variant, reason, value
- Edit
flags.jsonto change thedefaultVariant, save, and have the next request return the new variant without restarting the app
๐ง What You'll Learn#
- How an OpenFeature client and provider work together โ the SDK is provider-agnostic and the flagd provider plugs in via dependency only
- What "remote provider" means in practice โ the SDK calls a separate flag service (flagd) over gRPC; the SDK does not parse
flags.jsonitself - What
flags.jsonlooks like for flagd (state,variants,defaultVariant) - Why hot-reload of the flag file matters operationally โ configuration without redeploy
๐งฐ Toolbox#
Your Codespace comes pre-configured with the following tools to help you solve the challenge:
./mvnw: The Maven wrapper checked in next topom.xml. Builds and runs the Spring Boot lab.curl: Hitshttp://localhost:8080/and shows you what reading the lab is recording.jq: Pretty-prints and filters the JSON evaluation details that come back from the SDK.- A flagd sidecar โ already running in the devcontainer's compose stack on the docker-internal network. The lab reaches it as
flagd:8013; you don't need to forward its ports to play this challenge.
โฐ Deadline#
Tuesday, 26 May 2026 at 23:59 CET
โน๏ธ You can still complete the challenge after this date, but points will only be awarded for submissions before the deadline.
๐ฌ Join the discussion#
Share your solutions and questions in the challenge thread in the Open Ecosystem Community.
โ How to Play#
1. Start Your Challenge#
- Click the "Fork" button in the top-right corner of the GitHub repo or use this link.
- From your fork, click the green Code button โ Codespaces hamburger menu โ New with options.
- Select the Adventure 04 | ๐ข Beginner (Stand up the lab) configuration.
โ ๏ธ Important: The challenge will not work if you choose another configuration (or the default).
The Codespace will install a Java 21 toolchain and resolve the Maven dependencies. Once it is ready you'll have a
terminal in
adventures/04-blind-by-design/beginner/.
2. Start the Lab#
Before you open the forwarded port, start the Spring Boot lab so it is actually serving on :8080. You have two options:
- Click โถ in VS Code. The Spring Boot Dashboard panel (one of the recommended extensions in this devcontainer) lists
Laboratorywith a Run button. Or press F5 withLaboratory.javaopen and pick Java as the debugger โ Spring's main class is detected automatically; no launch.json needed. - From the terminal in the level folder:
./mvnw spring-boot:run
The lab boots in the broken state โ Trial returns the hard-coded "untreated" literal โ and that is exactly the starting point you want.
Set port 8080 to Public. In the Ports tab, right-click port
8080and set its visibility to Public so the forwarded address is accessible in your browser.
3. Access the UI#
Open the Ports tab in the bottom panel. You should see:
- 8080 โ Lab (Spring Boot). Click the forwarded address. You should see the current hard-coded response:
untreated.
flagd is also running, but only inside the docker network โ you don't need to forward its ports to play this challenge.
4. Implement the Objective#
You are turning a hard-coded label into a real protocol-driven reading. Work through the steps in this order โ each step makes the next one possible.
a. Add the OpenFeature SDK and the flagd provider to pom.xml#
The lab needs two dependencies: the OpenFeature Java SDK and the flagd contrib provider. GroupIds, artifactIds, and current versions are in the OpenFeature Java SDK docs and the flagd Java provider readme.
b. Configure the OpenFeature provider#
Create a Spring @Configuration class that, at startup, builds a FlagdProvider in RPC mode and registers it on the global OpenFeature API. The flagd Java provider readme covers FlagdOptions / Resolver.RPC usage.
You don't need to set host or port โ the devcontainer pre-sets FLAGD_HOST=flagd and FLAGD_PORT=8013 in the environment, and the provider reads those automatically.
c. Author the vision_state flag in flags.json#
The level ships an empty flags.json next to pom.xml ({"flags": {}}) so the flagd sidecar has a valid file to mount at boot. Open it and add a flag named vision_state with two string variants (e.g. blurry and clouded) so you have something to flip in the verification step. The schema (state, variants, defaultVariant) is in the flagd flag-definitions reference.
Save โ flagd's file watcher picks the change up within about a second; no restart needed.
d. Read the chart from Trial#
Replace the hard-coded return "untreated"; with an OpenFeature evaluation of the vision_state flag, using "untreated" as the fallback. Return the full evaluation details (not just the value) so the response carries the flag key, variant, value, and reason โ that's what the verifier checks.
The Java SDK's evaluation methods are documented in the OpenFeature Java SDK reference.
e. Restart the lab, then prove hot-reload#
The lab is already running from step 2. Stop it (Ctrl+C in the terminal, or the Stop button in the Spring Boot Dashboard) and start it again so the new OpenFeatureConfig is picked up. Then, in a second terminal:
curl -s http://localhost:8080/ | jq
You should see "value": "blurry" and "flagKey": "vision_state". Now, without stopping the app or the flagd
sidecar, edit flags.json and change "defaultVariant": "blurry" to "defaultVariant": "clouded". Save, then
re-run the curl. The value should flip to "clouded" โ that's flagd's file watcher noticing the change on disk
and serving the new variant on the next gRPC evaluation. Nothing redeployed; nothing restarted.
5. Verify Your Solution#
Once you think you've solved the challenge, run the verification script:
./verify.sh
If the verification fails:
The script will tell you which checks failed. Fix the issues and run it again.
If the verification passes:
- The script will check if your changes are committed and pushed.
- Follow the on-screen instructions to commit your changes if needed.
- Once everything is ready, the script will generate a Certificate of Completion.
- Copy this certificate and paste it into the challenge thread to claim your victory! ๐