blob: 33896cbcc2ec1e91c65b7b6abcdb2dae06ba559a [file] [view]
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apache/iggy/refs/heads/master/assets/logo/SVG/iggy-apache-color-darkbg.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/apache/iggy/refs/heads/master/assets/logo/SVG/iggy-apache-color-lightbg.svg">
<img alt="Apache Iggy" src="https://raw.githubusercontent.com/apache/iggy/refs/heads/master/assets/logo/SVG/iggy-apache-color-lightbg.svg" width="320">
</picture>
</div>
# Java SDK for Apache Iggy
Official Java client SDK for [Apache Iggy](https://iggy.apache.org) message streaming.
_This is part of the Apache Iggy monorepo. For the main project, see the [root repository](https://github.com/apache/iggy)._
## Installation
These examples target server **0.9.0**. SDK `0.9.0` is on Maven Central and works with server `0.9.0`. The older `0.8.0` artifact speaks the previous TCP protocol and does not work with server `0.9.0`. Java 17 or newer is required.
Add the dependency to your project:
**Gradle:**
```gradle
implementation 'org.apache.iggy:iggy:0.9.0'
```
**Maven:**
```xml
<dependency>
<groupId>org.apache.iggy</groupId>
<artifactId>iggy</artifactId>
<version>0.9.0</version>
</dependency>
```
See [Maven Central](https://central.sonatype.com/artifact/org.apache.iggy/iggy) for all published versions.
### Snapshot Versions
Development builds of the next release carry the version `0.9.1-SNAPSHOT`. Get them from the ASF snapshot repository:
**Gradle:**
```gradle
repositories {
mavenCentral()
maven {
url = uri("https://repository.apache.org/content/repositories/snapshots/")
}
}
dependencies {
implementation 'org.apache.iggy:iggy:0.9.1-SNAPSHOT'
}
```
**Maven:**
```xml
<repositories>
<repository>
<id>apache-snapshots</id>
<url>https://repository.apache.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.iggy</groupId>
<artifactId>iggy</artifactId>
<version>0.9.1-SNAPSHOT</version>
</dependency>
</dependencies>
```
## Quick Start
`Iggy.tcpClientBuilder()` handles the routing and the session for you. Over TCP and TCP/TLS, the client keeps the consumer group membership on the coordinator. It polls each partition through a separate connection to the primary of that partition.
Start the server with the [example prerequisites](../../examples/java/#running-examples) and matching credentials. The following snippets show alternative clients. Close a blocking client with `close()` or an async client with `close().join()` when finished.
### TCP Client (Blocking)
```java
import org.apache.iggy.Iggy;
// Create and connect with auto-login
var client = Iggy.tcpClientBuilder()
.blocking()
.host("localhost")
.port(8090)
.credentials("iggy", "iggy")
.buildAndLogin();
// Or build, connect, and login separately
var client = Iggy.tcpClientBuilder()
.blocking()
.host("localhost")
.port(8090)
.build();
client.connect();
client.users().login("iggy", "iggy");
```
### TCP Client (Async)
```java
import org.apache.iggy.Iggy;
// Create async client
var asyncClient = Iggy.tcpClientBuilder()
.async()
.host("localhost")
.port(8090)
.credentials("iggy", "iggy")
.buildAndLogin()
.join();
// Or with manual connect and login
var asyncClient = Iggy.tcpClientBuilder()
.async()
.host("localhost")
.build();
asyncClient.connect().join();
asyncClient.users().login("iggy", "iggy").join();
```
### HTTP Client
```java
import org.apache.iggy.Iggy;
// Using URL
var httpClient = Iggy.httpClientBuilder()
.blocking()
.url("http://localhost:3000")
.credentials("iggy", "iggy")
.buildAndLogin();
// Using host/port
var httpClient = Iggy.httpClientBuilder()
.blocking()
.host("localhost")
.port(3000)
.credentials("iggy", "iggy")
.buildAndLogin();
```
### TLS Support
Both TCP and HTTP clients support TLS:
```java
// TCP with TLS
var secureClient = Iggy.tcpClientBuilder()
.blocking()
.host("iggy-server.example.com")
.port(8090)
.enableTls()
.tlsCertificate("/path/to/ca.pem") // Optional custom CA
.credentials("admin", "secret")
.buildAndLogin();
// HTTPS
var secureHttpClient = Iggy.httpClientBuilder()
.blocking()
.host("iggy-server.example.com")
.port(443)
.enableTls()
.credentials("admin", "secret")
.buildAndLogin();
```
### Builder Options
The client builders support additional configuration:
```java
var client = Iggy.tcpClientBuilder()
.blocking()
.host("localhost")
.port(8090)
.connectionTimeout(Duration.ofSeconds(10))
.requestTimeout(Duration.ofSeconds(30))
.retryPolicy(RetryPolicy.exponentialBackoff())
.credentials("iggy", "iggy")
.buildAndLogin();
```
### Event Loop Threads
Each TCP client drives a single connection, so by default it creates an event loop group
with one thread. An application that opens many clients can instead register them all on
one caller-owned group. The clients never shut that group down. Close the clients first,
then shut the group down:
```java
var group = new MultiThreadIoEventLoopGroup(2, NioIoHandler.newFactory());
var producer = Iggy.tcpClientBuilder()
.blocking()
.eventLoopGroup(group)
.credentials("iggy", "iggy")
.buildAndLogin();
var consumer = Iggy.tcpClientBuilder()
.blocking()
.eventLoopGroup(group)
.credentials("iggy", "iggy")
.buildAndLogin();
// ... later
producer.close();
consumer.close();
group.shutdownGracefully();
```
Do not block in a completion callback. Callbacks run on the group's loops, so a blocked
callback stalls every client that shares the group.
### Version Information
```java
// Get SDK version
String version = Iggy.version(); // e.g., "0.9.0"
// Get detailed version info
IggyVersion info = Iggy.versionInfo();
info.getVersion(); // Version string
info.getBuildTime(); // Build timestamp
info.getGitCommit(); // Git commit hash
info.getUserAgent(); // User-Agent string for HTTP
```
## Exception Handling
The SDK's custom exception types inherit from `IggyException`. When you join a failed future, the cause can come back inside a `CompletionException`. The HTTP client's `close()` method declares `IOException`. Handle these two boundaries as well as the specific SDK errors.
## Examples
See the **[Java Examples](../../examples/java/)** directory for runnable applications demonstrating the SDK:
- **GettingStartedProducer**: synchronous message production with batch sending
- **GettingStartedConsumer**: synchronous consumption with polling loops
- **AsyncProducer**: non-blocking batch production with concurrent request submission
- **AsyncConsumer**: async consumption with backpressure and error recovery
The examples README describes blocking and async clients, CompletableFuture patterns, and thread pool management.
For Apache Flink integration, see the [Flink Connector Library](external-processors/iggy-connector-flink/iggy-connector-library/README.md).
## Building from Source
This project uses the Gradle Wrapper. Due to Apache Software Foundation policy, the `gradle-wrapper.jar` binary is not checked into the repository. Instead, the `gradlew` script automatically downloads it on first run.
```bash
# Build the project
./gradlew build
# Run tests
./gradlew test
```
The wrapper script will:
1. Download `gradle-wrapper.jar` from the official Gradle repository if missing
2. Verify the SHA256 checksum for security
3. Execute the requested Gradle command
No manual Gradle installation is required.
**Note:** Only the Unix shell wrapper (`gradlew`) is provided. On Windows, use WSL or Git Bash, or install Gradle manually.
## Contributing
Before opening a pull request:
1. **Format code:** `./gradlew spotlessApply`
2. **Validate build:** `./gradlew check`
3. **Use AssertJ for assertions:** Write test assertions with [AssertJ](https://assertj.github.io/doc/) (`assertThat(...)`) instead of JUnit assertions.
These steps keep the code style compliant and make sure that all tests and checkstyle validations pass.