Binding · Java

Java — in 5 Minuten zum ersten Sample

Pure-Java, kein JNI, kein libzerodds.so nötig. OMG DDS-Java-PSM-konforme org.omg.dds.*-Interface-Surface. Modern Java: Records, sealed types, virtual threads. IDL→Java-Codegen via idlc java.

JDK: 17+ (LTS) · 21+ für Virtual-Threads Install: Maven / Gradle Status: ✓ RC3 · Vendor-Spec

5-Minuten-Quickstart

Maven-Dep, ein Java-File, mvn exec:java.

1 · Java-Binding installieren

Maven Central ist noch nicht published. Pure-Java-Pfad (kein JNI) ist fertig in crates/java-omgdds/ — heute aus Source bauen:

git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds/crates/java-omgdds
mvn install -DskipTests
# install legt ~/.m2/repository/org/zerodds/zerodds-java-omgdds/1.0.0-rc.3/*.jar an

Dann in deinem Projekt:

mvn archetype:generate -DgroupId=com.example -DartifactId=zerodds-hello \
    -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd zerodds-hello

pom.xml Dep (referenziert das lokal installierte Artefakt; ab RC3 dann direkt aus Maven Central):

<dependency>
    <groupId>org.zerodds</groupId>
    <artifactId>zerodds-java-omgdds</artifactId>
    <version>1.0.0-rc.3</version>
</dependency>

2 · Pub/Sub-Roundtrip (App.java)

import org.omg.dds.core.ServiceEnvironment;
import org.omg.dds.domain.DomainParticipant;
import org.omg.dds.domain.DomainParticipantFactory;
import org.omg.dds.topic.Topic;
import org.omg.dds.pub.DataWriter;
import org.omg.dds.sub.DataReader;

public class App {
    public static void main(String[] args) throws Exception {
        var env = ServiceEnvironment.createInstance("org.zerodds.ServiceEnvironmentImpl");
        var factory = DomainParticipantFactory.getInstance(env);
        var participant = factory.createParticipant(0);

        var topic = participant.createTopic("Chatter", byte[].class);
        var writer = participant.createPublisher().createDataWriter(topic);
        var reader = participant.createSubscriber().createDataReader(topic);

        Thread.sleep(500);

        writer.write("hello".getBytes());
        Thread.sleep(200);

        for (var sample : reader.take()) {
            System.out.println("got: " + new String(sample.getData()));
        }
    }
}

▶ Runnable example: java-quickstart-bytes

3 · Laufen

mvn compile exec:java -Dexec.mainClass=com.example.App
# got: hello

Installation

Maven Central

<dependency>
    <groupId>org.zerodds</groupId>
    <artifactId>zerodds-java-omgdds</artifactId>
    <version>1.0.0-rc.3</version>
</dependency>

Gradle

implementation 'org.zerodds:zerodds-java-omgdds:1.0.0-rc.3'

Aus dem Source

git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds/crates/java-omgdds/java
mvn install

Voraussetzungen

  • JDK 17 oder höher (21 für Virtual-Threads-Support).
  • Kein nativer Build nötig — Pure-Java-Implementation.
  • Kein JNI, kein libzerodds.so.

Typisierte Topics — idlc java

IDL (temperature.idl)

module sensor_msgs {
    module msg {
        struct Temperature {
            long celsius;
            string sensor_id;
        };
    };
};

Codegen + Nutzen

idlc java temperature.idl -o gen/
# erzeugt gen/sensor_msgs/msg/Temperature.java (JavaBean-Klasse)

// Nutzen
var topic = participant.createTopic("Temp", Temperature.class);
var writer = participant.createPublisher().createDataWriter(topic);
var t = new Temperature();          // Default-Konstruktor
t.setCelsius(23);
t.setSensor_id("A7");               // Bean-Setter, IDL-Feldname unverändert
writer.write(t);

▶ Runnable example: java-typed-temperature

Generierte Struct-Klasse: public class Temperature { private int celsius; private String sensor_id; … getCelsius()/setCelsius() … } — Default-Konstruktor + Bean-Getter/Setter, IDL-Feldnamen unverändert. Unions dagegen werden als sealed interface + Case-records generiert (Java 17). Vendor-Spec: zerodds-java-omgdds 1.0.

Java-8-Compat-Mode

Standard ist Java 17 (Unions nutzen sealed interface + record). Für Bestandssysteme auf älteren JVMs gibt es einen opt-in Compat-Mode, der alles auf Java 8 herunterzieht — ohne Java-9+-Konstrukte.

Codegen

Der idl-java-Codegen kennt den Schalter java8_compat (in JavaGenOptions). Damit werden Unions als abstract class mit privatem Konstruktor (Pseudo-Sealing) + static final-Subklassen emittiert statt als sealed interface + record:

// Standard (Java 17)
public sealed interface U permits U.A, U.B {
    record A(int a) implements U {}
    record B(String b) implements U {}
}

// java8_compat (Java 8)
public abstract class U {
    private U() {}
    public static final class A extends U {
        private final int a;
        public A(int a) { this.a = a; }
        public int a() { return a; }
    }
    public static final class B extends U { /* ... */ }
}

▶ Runnable example: java-union-codegen-illustration

Structs, Enums und Typedefs sind in beiden Modi identisch (Bean-Klassen — schon Java-8-tauglich).

Runtime-JAR bauen

# Standard (Java 17)
mvn install

# Java-8-Compat-Build
mvn -Pjava8 install

Der Hand-Code der Runtime ist var-frei und nutzt nur Java-8-Features (Lambdas, Consumer, default-Methoden). Das java8-Profil setzt source/target 8.

Multi-Process via gRPC-Bridge

Pure-Java läuft in-process. Für Cross-Process / Cross-Vendor-Kommunikation mit C++/Rust/C#-Peers gibt's in v1.1 die gRPC-Bridge: Java spricht gRPC zu einem libzerodds-Backend-Server, der RTPS-Wire spricht. Status: Roadmap.

  • Heute: Single-JVM (in-process, kein Multi-Vendor).
  • v1.1: gRPC-Bridge zu nativem libzerodds-Server.
  • v2.0: Pure-Java RTPS-Wire (Stretch-Goal).

Roadmap: Vendor-Spec §5 Phase-2-Plan

Binding · Java

Java — first sample in 5 minutes

Pure Java, no JNI, no libzerodds.so needed. An OMG DDS-Java-PSM-conformant org.omg.dds.* interface surface. Modern Java: records, sealed types, virtual threads. IDL→Java codegen via idlc java.

JDK: 17+ (LTS) · 21+ for virtual threads Install: Maven / Gradle Status: ✓ RC3 · vendor spec

5-minute quickstart

A Maven dep, one Java file, mvn exec:java.

1 · Install the Java binding

Maven Central is not published yet. The pure-Java path (no JNI) is finished in crates/java-omgdds/ — build from source today:

git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds/crates/java-omgdds
mvn install -DskipTests
# install puts ~/.m2/repository/org/zerodds/zerodds-java-omgdds/1.0.0-rc.3/*.jar in place

Then in your project:

mvn archetype:generate -DgroupId=com.example -DartifactId=zerodds-hello \
    -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd zerodds-hello

pom.xml dep (references the locally installed artifact; from RC3 directly from Maven Central):

<dependency>
    <groupId>org.zerodds</groupId>
    <artifactId>zerodds-java-omgdds</artifactId>
    <version>1.0.0-rc.3</version>
</dependency>

2 · Pub/sub roundtrip (App.java)

import org.omg.dds.core.ServiceEnvironment;
import org.omg.dds.domain.DomainParticipant;
import org.omg.dds.domain.DomainParticipantFactory;
import org.omg.dds.topic.Topic;
import org.omg.dds.pub.DataWriter;
import org.omg.dds.sub.DataReader;

public class App {
    public static void main(String[] args) throws Exception {
        var env = ServiceEnvironment.createInstance("org.zerodds.ServiceEnvironmentImpl");
        var factory = DomainParticipantFactory.getInstance(env);
        var participant = factory.createParticipant(0);

        var topic = participant.createTopic("Chatter", byte[].class);
        var writer = participant.createPublisher().createDataWriter(topic);
        var reader = participant.createSubscriber().createDataReader(topic);

        Thread.sleep(500);

        writer.write("hello".getBytes());
        Thread.sleep(200);

        for (var sample : reader.take()) {
            System.out.println("got: " + new String(sample.getData()));
        }
    }
}

▶ Runnable example: java-quickstart-bytes

3 · Run

mvn compile exec:java -Dexec.mainClass=com.example.App
# got: hello

Installation

Maven Central

<dependency>
    <groupId>org.zerodds</groupId>
    <artifactId>zerodds-java-omgdds</artifactId>
    <version>1.0.0-rc.3</version>
</dependency>

Gradle

implementation 'org.zerodds:zerodds-java-omgdds:1.0.0-rc.3'

From source

git clone https://github.com/zero-objects/zero-dds.git
cd zero-dds/crates/java-omgdds/java
mvn install

Prerequisites

  • JDK 17 or higher (21 for virtual-threads support).
  • No native build needed — a pure-Java implementation.
  • No JNI, no libzerodds.so.

Typed topics — idlc java

IDL (temperature.idl)

module sensor_msgs {
    module msg {
        struct Temperature {
            long celsius;
            string sensor_id;
        };
    };
};

Codegen + use

idlc java temperature.idl -o gen/
# produces gen/sensor_msgs/msg/Temperature.java (a JavaBean class)

// use it
var topic = participant.createTopic("Temp", Temperature.class);
var writer = participant.createPublisher().createDataWriter(topic);
var t = new Temperature();          // default constructor
t.setCelsius(23);
t.setSensor_id("A7");               // Bean setter, IDL field name kept
writer.write(t);

▶ Runnable example: java-typed-temperature

Generated struct class: public class Temperature { private int celsius; private String sensor_id; … getCelsius()/setCelsius() … } — a default constructor + Bean getters/setters, IDL field names kept. Unions, by contrast, are generated as a sealed interface + case records (Java 17). Vendor spec: zerodds-java-omgdds 1.0.

Java 8 compat mode

The standard is Java 17 (unions use sealed interface + record). For legacy systems on older JVMs there's an opt-in compat mode that brings everything down to Java 8 — no Java 9+ constructs.

Codegen

The idl-java codegen has a java8_compat switch (in JavaGenOptions). With it, unions are emitted as an abstract class with a private constructor (pseudo-sealing) + static final subclasses instead of a sealed interface + record:

// standard (Java 17)
public sealed interface U permits U.A, U.B {
    record A(int a) implements U {}
    record B(String b) implements U {}
}

// java8_compat (Java 8)
public abstract class U {
    private U() {}
    public static final class A extends U {
        private final int a;
        public A(int a) { this.a = a; }
        public int a() { return a; }
    }
    public static final class B extends U { /* ... */ }
}

▶ Runnable example: java-union-codegen-illustration

Structs, enums and typedefs are identical in both modes (Bean classes — already Java-8-capable).

Building the runtime JAR

# standard (Java 17)
mvn install

# Java 8 compat build
mvn -Pjava8 install

The runtime's hand-written code is var-free and uses only Java 8 features (lambdas, Consumer, default methods). The java8 profile sets source/target 8.

Multi-process via the gRPC bridge

Pure Java runs in-process. For cross-process / cross-vendor communication with C++/Rust/C# peers there's the gRPC bridge in v1.1: Java speaks gRPC to a libzerodds backend server that speaks the RTPS wire. Status: roadmap.

  • Today: single JVM (in-process, no multi-vendor).
  • v1.1: gRPC bridge to a native libzerodds server.
  • v2.0: pure-Java RTPS wire (stretch goal).

Roadmap: vendor spec §5 phase-2 plan