Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ check/java/package: ## Build and verify publishable Maven archives without publi
check/java/package: build/java
go run ./java/bin/check-packages/main.go

.PHONY: check/java/release
check/java/release: ## Build a signed Maven Central bundle without uploading (requires an OpenPGP key)
check/java/release: generate/fixtures verify/java-migrations
$(java_mvn) -f java/pom.xml -Prelease clean deploy -Driver.test.database=sqlite -DexcludedGroups=postgres -Dmaven.install.skip=true -Dcentral.skipUpload=true

.PHONY: check/js/dependencies
check/js/dependencies: ## Audit JavaScript advisories and production dependency licenses
pnpm -C js audit
Expand Down
7 changes: 7 additions & 0 deletions java/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.1.0-alpha.1] - 2026-10-24

### Added

- First alpha release of River for Java. `com.riverqueue:river` provides a Java 21 client and worker runtime for Postgres and SQLite, sharing River's database schema and job protocol with other River clients. Includes typed jobs, virtual-thread workers, transactional inserts, unique, scheduled, periodic, and resumable jobs, queue management, hooks, middleware, events, and migrations.
- Standalone migration CLI, published as `com.riverqueue:river-cli` with classifier `all`. The executable JAR bundles both JDBC drivers and supports applying, reverting, listing, and exporting migrations.

### Changed

- **Breaking:** Replaced `Extension` and `Client.withExtension` with operation-specific hook and middleware interfaces, matching River for Go: `HookInsertBegin`, `HookPeriodicJobsStart`, `HookWorkBegin`, `HookWorkEnd`, `JobInsertMiddleware`, and `WorkerMiddleware`. Register them with `Client.withPlugins` to activate all interfaces an instance implements, or with `withHooks` and `withMiddleware` to activate only that side. Plugins run before separately registered hooks and middleware. Each operation-specific interface supports lambdas and checked exceptions. The `afterClaim` callback was removed; use worker middleware for work before the handler. [PR #1519](https://github.com/riverqueue/river/pull/1519).
Expand Down
4 changes: 3 additions & 1 deletion java/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: test test/conformance test/postgres test/sqlite test/tools lint lint/tools format package
.PHONY: test test/conformance test/postgres test/sqlite test/tools lint lint/tools format package package/release
test:
$(MAKE) -C .. test/java
test/conformance:
Expand All @@ -17,3 +17,5 @@ format:
mvn spotless:apply
package:
$(MAKE) -C .. check/java/package
package/release:
$(MAKE) -C .. check/java/release
8 changes: 4 additions & 4 deletions java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ retry, or work them using the same database.

## Installation

Java 21 or newer is required. Add `com.riverqueue:river:0.48.0-alpha.1` and a JDBC driver to your application's dependencies. Jackson 3 is included transitively.
Java 21 or newer is required. Add `com.riverqueue:river:0.1.0-alpha.1` and a JDBC driver to your application's dependencies. Jackson 3 is included transitively.

```xml
<dependency>
<groupId>com.riverqueue</groupId>
<artifactId>river</artifactId>
<version>0.48.0-alpha.1</version>
<version>0.1.0-alpha.1</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
Expand Down Expand Up @@ -83,7 +83,7 @@ runs with Java 21 or newer. It needs no application classpath.
For a local build, see the [development guide](docs/development.md#building-from-source). Set `RIVER_CLI` to the executable JAR, then run:

```sh
RIVER_CLI=/path/to/river-cli-0.48.0-alpha.1-all.jar
RIVER_CLI=/path/to/river-cli-0.1.0-alpha.1-all.jar
export DATABASE_URL=postgres://localhost/myapp
# For SQLite: export DATABASE_URL=jdbc:sqlite:/absolute/path/myapp.db

Expand All @@ -94,7 +94,7 @@ java -jar "$RIVER_CLI" migrate-up
```

The Maven executable artifact is `com.riverqueue:river-cli` with version
`0.48.0-alpha.1` and classifier `all`. Copy that single JAR into your deployment image to run
`0.1.0-alpha.1` and classifier `all`. Copy that single JAR into your deployment image to run
migrations before starting workers. `--database-url URL` overrides `DATABASE_URL`.
`--schema background_jobs` selects a Postgres schema; an actual migration up
creates it if needed. Listing and dry runs do not create schemas or migration tables.
Expand Down
8 changes: 4 additions & 4 deletions java/cli/pom.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent><groupId>com.riverqueue</groupId><artifactId>river-java</artifactId><version>0.48.0-alpha.1</version><relativePath>../pom.xml</relativePath></parent>
<artifactId>river-cli</artifactId><version>0.48.0-alpha.1</version>
<parent><groupId>com.riverqueue</groupId><artifactId>river-java</artifactId><version>0.1.0-alpha.1</version><relativePath>../pom.xml</relativePath></parent>
<artifactId>river-cli</artifactId><version>0.1.0-alpha.1</version>
<name>River Java migration CLI</name>
<licenses><license><name>Mozilla Public License 2.0</name><url>https://mozilla.org/MPL/2.0/</url><distribution>repo</distribution></license></licenses>
<description>Executable database migration tool for River on Postgres and SQLite</description>
<dependencies>
<dependency><groupId>com.riverqueue</groupId><artifactId>river</artifactId><version>0.48.0-alpha.1</version></dependency>
<dependency><groupId>com.riverqueue</groupId><artifactId>river</artifactId><version>0.1.0-alpha.1</version></dependency>
<dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency>
<dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId></dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><scope>test</scope></dependency>
Expand Down
4 changes: 2 additions & 2 deletions java/cli/src/test/java/com/riverqueue/cli/ExecutableIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ private String command(String... args) throws Exception {
List.of(
Path.of(System.getProperty("java.home"), "bin", "java").toString(),
"-jar",
"target/river-cli-0.48.0-alpha.1-all.jar"));
"target/river-cli-0.1.0-alpha.1-all.jar"));
command.addAll(List.of(args));
var output = directory.resolve("process.log").toFile();
var builder = new ProcessBuilder(command).redirectErrorStream(true).redirectOutput(output);
Expand All @@ -36,7 +36,7 @@ private String command(String... args) throws Exception {

@Test
void bundledJarRunsWithoutExternalClasspath() throws Exception {
assertTrue(command("--version").contains("0.48.0-alpha.1"));
assertTrue(command("--version").contains("0.1.0-alpha.1"));
assertTrue(command("migrate-up").contains("008 [up]"));
assertTrue(command("migrate-list").contains("applied"));
assertTrue(command("migrate-down", "--target-version", "0").contains("001 [down]"));
Expand Down
4 changes: 2 additions & 2 deletions java/conformance/bin/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
with (artifacts.parent / "build.lock").open("w") as lock:
fcntl.flock(lock, fcntl.LOCK_EX)
subprocess.run(["mvn", "-q", "-f", str(root / "pom.xml"), "package", "-DskipTests"], check=True)
jar = root / "conformance/target/river-conformance-0.48.0-alpha.1.jar"
jar = root / "conformance/target/river-conformance-0.1.0-alpha.1.jar"
# A stale shaded jar can otherwise silently retain an older dependency's classes.
with zipfile.ZipFile(root / "river/target/river-0.48.0-alpha.1.jar") as library, zipfile.ZipFile(jar) as bundled:
with zipfile.ZipFile(root / "river/target/river-0.1.0-alpha.1.jar") as library, zipfile.ZipFile(jar) as bundled:
for entry in library.namelist():
if entry.startswith("com/riverqueue/") and not entry.endswith("/"):
if library.read(entry) != bundled.read(entry):
Expand Down
2 changes: 1 addition & 1 deletion java/conformance/bin/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def main():
manifest_path = reference / "conformance/manifest.json"
manifest = json.loads(manifest_path.read_text())
manifest["implementations"]["java"] = {
"package": "com.riverqueue:river", "registry": "maven", "version": "0.48.0-alpha.1"
"package": "com.riverqueue:river", "registry": "maven", "version": "0.1.0-alpha.1"
}
manifest_path.write_text(json.dumps(manifest, indent=2) + "\n")
environment = os.environ | {
Expand Down
2 changes: 1 addition & 1 deletion java/conformance/candidate.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"postgres-full-v1",
"sqlite-runtime-v1"
],
"version": "0.48.0-alpha.1",
"version": "0.1.0-alpha.1",
"start_options": [
"elect_interval_ms",
"rescuer_interval_ms",
Expand Down
9 changes: 7 additions & 2 deletions java/conformance/pom.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent><groupId>com.riverqueue</groupId><artifactId>river-java</artifactId><version>0.48.0-alpha.1</version></parent>
<parent><groupId>com.riverqueue</groupId><artifactId>river-java</artifactId><version>0.1.0-alpha.1</version></parent>
<artifactId>river-conformance</artifactId>
<!-- This is a development adapter, not a publishable River artifact. -->
<properties><maven.install.skip>true</maven.install.skip><maven.deploy.skip>true</maven.deploy.skip></properties>
<properties>
<gpg.skip>true</gpg.skip>
<maven.install.skip>true</maven.install.skip>
<maven.deploy.skip>true</maven.deploy.skip>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
<dependencies>
<dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>7.1.0</version></dependency>
<dependency><groupId>com.riverqueue</groupId><artifactId>river</artifactId><version>${project.version}</version></dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ private JsonNode handle(String method, JsonNode params, String rawParams) throws
database.dialect() == Database.Dialect.POSTGRES ? "postgres" : "sqlite"),
Map.entry("capabilities", capabilities),
Map.entry("implementation", "java"),
Map.entry("implementation_version", "0.48.0-alpha.1"),
Map.entry("implementation_version", "0.1.0-alpha.1"),
Map.entry("methods", methods),
Map.entry("migration_lines", Map.of("main", 8)),
Map.entry("profile", profile),
Expand Down
2 changes: 1 addition & 1 deletion java/conformance/src/main/resources/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"java": {
"package": "com.riverqueue:river",
"registry": "maven",
"version": "0.48.0-alpha.1"
"version": "0.1.0-alpha.1"
}
},
"migration": {
Expand Down
Loading
Loading