You already have a service that posts webhooks to your customers with HttpClient and a hand-built JSON body. This guide replaces one of those calls with a generated, type-safe sender: no rewrite, no big bang. Set aside about 15 minutes.
You start from something like this, scattered wherever an event happens:
// The ad-hoc send you have today.
HttpRequest request = HttpRequest.newBuilder(URI.create(customer.webhookUrl()))
.header("content-type", "application/json")
.POST(BodyPublishers.ofString("{\"type\":\"order.created\",\"data\":{\"id\":\"" + order.id() + "\"}}"))
.build();
httpClient.send(request, BodyHandlers.discarding());The runtime is published to Maven Central under sh.repost and is server-side only: it holds a publish credential.
The published runtime is version 1.0.18 and the schema engine is 0.9.0. Kotlin projects should follow the Kotlin guide instead.
Import the repost-bom to keep every Repost artifact on one version, depend on repost-client, and add the repost-maven-plugin to generate on every build.
<properties>
<maven.compiler.release>11</maven.compiler.release>
<repost.version>1.0.18</repost.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>sh.repost</groupId>
<artifactId>repost-bom</artifactId>
<version>${repost.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>sh.repost</groupId>
<artifactId>repost-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>sh.repost</groupId>
<artifactId>repost-maven-plugin</artifactId>
<version>${repost.version}</version>
<configuration>
<generators><generator>javaSdk</generator></generators>
</configuration>
<executions>
<execution>
<goals><goal>generate</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>The plugin adds no transitive HTTP, JSON, or logging libraries to your classpath, so it cannot collide with your own Jackson, SLF4J, or OkHttp versions.
From the repository root:
repost schema init --language java --output ./src/main/javaThis scaffolds a repost/ directory. Model the event you already send with a Java generator block:
generator javaSdk {
language = "java"
output = "../target/generated-sources/repost"
resourceOutput = "../target/generated-resources/repost"
packageName = "com.example.repost"
clientName = "RepostClient"
}
model Order {
id String
}
type Order {
created
}
event OrderCreated {
type @type(Order.created)
data Order
timestamp DateTime
}Add one field per key you send today. Code generation explains the four extra generator fields.
The plugin binds to the generate-sources phase, so a normal compile already produces your client. To run generation on its own:
./mvnw repost:generateCreate an environment in the dashboard, copy its publish API key into your environment, then deploy your schema:
repost auth login
repost schema migrate deployReplace the ad-hoc call#
Swap the raw HttpClient send for the generated sender. Repost fans the event out to the customer's registered endpoints, so you no longer track webhookUrl yourself. The client is AutoCloseable; create() reads the credential and endpoint from the environment:
Order order = Order.builder().id("order-123").build();
try (RepostClient repost = RepostClient.create()) {
SendResult sync = repost.webhooks().order().created("customer-123", order);
System.out.println(sync.getId());
SendResult async = repost.webhooks().order().createdAsync(
"customer-123",
order,
SendOptions.builder().idempotencyKey("order-123").build())
.toCompletableFuture()
.join();
System.out.println(async.getId());
}A successful send returns a SendResult whose getDeliveryState() is ACCEPTED; any failure throws a RepostException subclass. Always close a client you created.
Verify delivery#
Trigger the code path that fires the event, then open the dashboard. The send appears in the event stream with its msg_... id and per-endpoint delivery status. Once you trust it, delete the old HttpClient call and repeat for the next event type.