---
title: "Add to existing project"
description: "Take a Java service that already posts webhooks by hand and move one ad-hoc HTTP call onto a generated, type-safe Repost sender in about 15 minutes."
---


<RepostHighlight />

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:

```java
// 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.

<Note>
  The published runtime is version `1.0.18` and the schema engine is `0.9.0`. Kotlin projects should follow the [Kotlin guide](/docs/send/kotlin/existing-project) instead.
</Note>

<Steps>
  <Step title="Add the plugin and BOM">
    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.

    ```xml pom.xml
    <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.
  </Step>

  <Step title="Initialize a schema in your repo">
    From the repository root:

    ```bash
    repost schema init --language java --output ./src/main/java
    ```

    This scaffolds a `repost/` directory. Model the event you already send with a Java `generator` block:

    ```repost repost/schema.repost
    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](/docs/send/java/generation) explains the four extra generator fields.
  </Step>

  <Step title="Generate the client">
    The plugin binds to the `generate-sources` phase, so a normal compile already produces your client. To run generation on its own:

    ```bash
    ./mvnw repost:generate
    ```
  </Step>

  <Step title="Connect an environment">
    Create an environment in the [dashboard](https://app.repost.sh), copy its publish API key into your environment, then deploy your schema:

    ```bash
    repost auth login
    repost schema migrate deploy
    ```
  </Step>
</Steps>

## Replace 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:

```java
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](https://app.repost.sh). 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.

## Continue

<Columns cols={3} className="gap-y-4">
  <Card title="Code generation" icon="cog" href="/docs/send/java/generation" cta="Generation" arrow="true">
    The generator block, the `repost:check` CI gate, and multi-module builds.
  </Card>

  <Card title="Model your events" icon="table" href="/docs/send/schema" cta="Schema" arrow="true">
    Enums, nested models, and the full schema language.
  </Card>

  <Card title="Reliability" icon="shield-check" href="/docs/send/java/reliability" cta="Outcomes" arrow="true">
    Idempotency, the five delivery states, and backpressure.
  </Card>
</Columns>
