--- title: Java | Stainless description: Generate production-ready Java SDKs from your OpenAPI specification --- Java is [fully supported](https://www.stainless.com/changelog/java-kotlin-general-availability). The Stainless Java SDK generator creates idiomatic, type-safe Java client libraries from your OpenAPI specification. **Example repositories:** - [openai/openai-java](https://github.com/openai/openai-java) - [hiddenlayer-sdk-java](https://github.com/hiddenlayerai/hiddenlayer-sdk-java) - [lithic-com/lithic-java](https://github.com/lithic-com/lithic-java) - [Modern-Treasury/modern-treasury-java](https://github.com/Modern-Treasury/modern-treasury-java) ## Configuration To generate a Java SDK, add the `java` target to your Stainless configuration file: ``` targets: java: reverse_domain: com.example.api edition: java.2025-10-08 ``` ### Common configuration options ``` targets: java: reverse_domain: com.example.api # Specify the edition edition: java.2025-10-08 # Configure publishing publish: maven: sonatype_platform: portal # or: ossrh ``` For a complete list of configuration options, see the [Java target reference](/docs/reference/config#java/index.md). ## Editions Editions allow Stainless to make improvements to SDKs that aren’t backwards-compatible. You can explicitly opt in to new editions when you’re ready. See the [SDK and config editions reference](/docs/reference/editions/index.md) for more information. #### java.2025-10-08 - Initial edition for Java (used by default if no edition is specified) ## Publishing to Maven Central Publish your Java SDK to [Sonatype Maven Central](https://central.sonatype.com/) for distribution. Sonatype has both a [legacy (OSSRH) publishing flow](https://central.sonatype.org/register/legacy/) and a [new Central Portal publishing flow](https://central.sonatype.org/register/central-portal/). (The [Kotlin target](/docs/targets/kotlin#publishing-to-maven-central/index.md) uses the same Maven Central publishing process.) Before publishing, you need to [link a production repository](/docs/guides/publish#link-production-repos/index.md) where Stainless will push your SDK code. If you do not already publish to OSSRH, use the new Central Portal publishing flow. If you are already publishing to OSSRH, you can continue to do so. Setting up Sonatype can be an involved process. We recommend you go through this process after getting your SDKs into a satisfactory state. Update your Stainless config (Central Portal only) For backwards compatibility, the default `sonatype_platform` is `ossrh`. If you are using the Central Portal, update the [Stainless config](/docs/reference/config#java/index.md) to `portal`: ``` targets: java: reverse_domain: com.example.api publish: maven: sonatype_platform: portal ``` Register a namespace (Central Portal only) A **namespace** uniquely identifies your organization and becomes the prefix of the Maven packages (`groupId`) you publish. It must be the **reverse-DNS form of a domain you own** (e.g., the domain `api.example.com` becomes the namespace `com.example.api`). The namespace must match the domain exactly and in a future step, Sonatype will verify your ownership of the domain. For more details, see the [Sonatype documentation](https://central.sonatype.org/register/namespace/). 1. Log in or sign up at [Sonatype Central Portal](https://central.sonatype.com/api/auth/login). 2. Navigate to **Publish** > **[Namespaces](https://central.sonatype.com/publishing/namespaces)**. 3. Register a new namespace by clicking the **Register New Namespace** button and setting the namespace. 4. **Copy the Verification Key** Sonatype provides a verification key that you’ll use to prove ownership of the domain backing your namespace. Verify domain ownership **Central Portal flow:** Use the verification key provided by Sonatype as the TXT record value. **OSSRH (JIRA-based) flow:** Use the JIRA ticket ID (e.g., `OSSRH-12345`) as the TXT record value. 1. Add a [temporary DNS TXT record](https://central.sonatype.org/faq/how-to-set-txt-record/) on the domain that corresponds to the reverse-DNS namespace you registered. This DNS record proves you control the domain your namespace (and `groupId`) is based on. 2. From the **Publish** > **[Namespaces](https://central.sonatype.com/publishing/namespaces)** page, click on your namespace and verify that the TXT record is set. Generate user token and add to GitHub secrets (Central Portal only) 1. From the [Sonatype Central Portal dashboard](https://central.sonatype.com/usertoken), generate a user token. Set the token name and expiration date as appropriate. 2. Copy the **Username** and **Password** values. 3. In your production repo, navigate to **Secrets and variables** > **Actions** > **New repository secret**. The URL should look like `https://github.com///settings/secrets/actions/new`. 4. Add the following secrets: - `SONATYPE_USERNAME`: Paste the username you copied. - `SONATYPE_PASSWORD`: Paste the password (user token) you copied. Generate a PGP key 1. Install [GnuPG](https://gnupg.org/). 2. In a terminal, run `gpg --gen-key`. Enter your name, email, and a passphrase for the keypair. The passphrase you enter here is set on GitHub as a secret named `GPG_SIGNING_PASSWORD` later. 1. Run `gpg --list-keys --keyid-format short`: Terminal window ``` % gpg --list-keys --keyid-format short [keyboxd] --------- pub ed25519/7FAD9FAA 2023-08-02 [SC] [expires: 2026-08-01] 418D41921938A753CAAE57985114AD037FAD9FAA uid [ultimate] Your Organization sub cv25519/07EB38A7 2023-08-02 [E] [expires: 2026-08-01] ``` 2. Export the key in ASCII-armored format. In the above example, the short key ID is `7FAD9FAA`. Terminal window ``` $ gpg --export-secret-keys --armor 7FAD9FAA -----BEGIN PGP PRIVATE KEY BLOCK----- lIYEZMpnEhYJKwYBBAHaRw8BAQdA1FQMKz+wwliKNdLehegZP0QiaKrZJqADNyVn VCUzIrD+BwMCwZrqVbVPfSr8NwxEh3M6kWtMGmnLMOk/NWVe7dtCxDxo37l/Ncxj Mm9EZiH6WXwoXXq20nOW354oNOVz/UPvDU+oaRDDUM9SYs392i69WLQjWW91ciBP cmdhbml6YXRpb24gPHlvdUB5b3Vyb3JnLmNvbT6ImQQTFgoAQRYhBEGNQZIZOKdT yq5XmFEUrQN/rZ+qBQJkymcSAhsDBQkFo5qABQsJCAcCAiICBhUKCQgLAgQWAgMB Ah4HAheAAAoJEFEUrQN/rZ+qgtsBAMCBuTqYEJljxStRO7SsMLWOc47CIIXD0Yid CbySBX0ZAP9DXuuGVYbHFONvHxNKszu2hY9A1BbRuNjeGeWuVOw9ApyLBGTKZxIS CisGAQQBl1UBBQEBB0AFxkZ+ZdEN7Epwri/w5ETAf+MOqdwAP2sS6TccSjEiXQMB CAf+BwMCtKG1TBUSC/z8tn761I5j+ifVIuMqdQPYIhZtjvIyC+NyrBi0j1ZtUG4A DAeDKNyM63uyb7omOH8+Lu0J71SGhVnZWszUOf3rrT/TA5MktYh+BBgWCgAmFiEE QY1Bkhk4p1PKrleYURStA3+tn6oFAmTKZxICGwwFCQWjmoAACgkQURStA3+tn6qa XAD/W2ucVURngmCUiUtdjQAZz36yQYPQmBhcdabZMyXKHz0A/itwYkuRbD2mp4p/ xJk/QLXs/2/xBA6s0ROVVspy6MEA =p/g/ -----END PGP PRIVATE KEY BLOCK----- ``` 3. Publish your PGP public key. Terminal window ``` $ gpg --keyserver keyserver.ubuntu.com --send-keys 7FAD9FAA ``` If you get the following error: ``` gpg: sending key XXXXXX to hkp://keyserver.ubuntu.com gpg: keyserver send failed: No route to host ``` then your computer might be trying to use IPv6 and failing. Run the following to get keyserver.ubuntu.com’s IPv4 addresses: Terminal window ``` $ host keyserver.ubuntu.com keyserver.ubuntu.com has address XXX.XXX.XXX.XX keyserver.ubuntu.com has address XXX.XXX.XXX.XX keyserver.ubuntu.com has IPv6 address XXXX:XX:XXXX:XXXX::XXX keyserver.ubuntu.com has IPv6 address XXXX:XX:XXXX:XXXX::XXX ``` Then rerun the `gpg` command with one of the IPv4 addresses: Terminal window ``` $ gpg --keyserver XXX.XXX.XXX.XX --send-keys 7FAD9FAA ``` Add secrets to your production repo 1. In the production repo, navigate to **Secrets and variables** > **Actions** > **New repository secret**. The URL should look like `https://github.com///settings/secrets/actions/new`. 2. Add the following secrets: - `GPG_SIGNING_PASSWORD`: the passphrase you entered when creating the keypair. - `GPG_SIGNING_KEY`: your PGP private key. It should be the entire output of `gpg --export-secret-keys --armor `. - `SONATYPE_USERNAME`: username for your Sonatype account. - `SONATYPE_PASSWORD`: password for your Sonatype account (OSSRH) or your Sonatype user token (Central Portal).