Skip to main content

Resource filtering

Maven-style resource filtering — substituting ${VAR} placeholders inside resource files at build time — isn't a built-in feature in bleep. It's a focused sourcegen script: a few lines of real logic, plus enough Java boilerplate for one class.

This is intentional: filtering rules vary wildly between projects (Spring property syntax, Mustache templates, plain ${X} substitution, conditional includes, multi-environment overrides). A built-in implementation would force one of those models on you. A script lets you write exactly what you need, debug it in your IDE, and version it alongside the rest of your build.

Example: substitute build-time values into application.properties

Hand-written src/main/resources/application.properties.template:

app.name=${APP_NAME}
app.version=${APP_VERSION}
build.timestamp=${BUILD_TIMESTAMP}

Wire the script into bleep.yaml:

projects:
my-service:
sourcegen: scripts/myco.FilterResources

scripts:
dependencies:
- build.bleep:bleepscript:${BLEEP_VERSION}
java:
options: -proc:none --release 17
platform:
name: jvm
sources: ./src/main/java

The script:

package myco;

import bleepscript.BleepCodegenScript;
import bleepscript.CodegenTarget;
import bleepscript.Commands;
import bleepscript.Started;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.List;
import java.util.Map;

public final class FilterResources extends BleepCodegenScript {
public FilterResources() {
super("FilterResources");
}

@Override
public void run(Started started, Commands commands, List<CodegenTarget> targets, List<String> args) {
Map<String, String> substitutions = Map.of(
"APP_NAME", System.getenv().getOrDefault("APP_NAME", "my-service"),
"APP_VERSION", started.build().dynVer().version(),
"BUILD_TIMESTAMP", Instant.now().toString());

for (CodegenTarget target : targets) {
Path template = started.buildPaths().buildDir()
.resolve("my-service/src/main/resources/application.properties.template");
try {
String rendered = Files.readString(template);
for (Map.Entry<String, String> sub : substitutions.entrySet()) {
rendered = rendered.replace("${" + sub.getKey() + "}", sub.getValue());
}
Path out = target.resources().resolve("application.properties");
Files.createDirectories(out.getParent());
Files.writeString(out, rendered);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}

That's it. The generated application.properties lands in the project's resource path automatically and ships in the JAR / on the classpath at runtime.

Why this is the right shape

  • Your filtering, your rules. Need conditional sections? Mustache? Multi-environment YAML merge? Just write it.
  • Debuggable. Set a breakpoint in IntelliJ and step through.
  • Incremental. Bleep tracks the script's inputs and re-runs it only when they change.
  • Atomic. A failed script never leaves stale generated resources behind.

See Source generation for the full script API.