Binding · Java

Java — in 5 Minuten zum ersten Sample

Pure-Java, kein JNI, kein libzerodds.so nötig, mit eigenem RTPS-Stack in Java (org.zerodds.rtps). OMG DDS-Java-PSM-konforme org.omg.dds.*-Interface-Surface. IDL→Java-Codegen via zerodds-idlc generate --lang java.

JDK: 17+ · Java 8 mit Profil java8 Install: Maven / Gradle Spec: Vendor-Spec

5-Minuten-Quickstart

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

1 · Projekt + Java-Binding

Das Binding ist das Maven-Artefakt org.zerodds:omgdds. Pure Java, kein JNI: Es gibt keine native Bibliothek zu installieren.

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

pom.xml Dep:

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

2 · Pub/Sub-Roundtrip (src/main/java/com/example/App.java)

package com.example;

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

public class App {
    public static void main(String[] args) throws Exception {
        // DDS-Java-PSM 1.0 §7.3.1: the implementation class is named by a system property
        System.setProperty(ServiceEnvironment.IMPLEMENTATION_CLASS_NAME_PROPERTY,
                "org.zerodds.ServiceEnvironmentImpl");
        ServiceEnvironment env = ServiceEnvironment.createInstance(App.class.getClassLoader());
        DomainParticipant participant =
                DomainParticipantFactory.getInstance(env).createParticipant(0);

        Topic<byte[]> topic = participant.createTopic("Chatter", byte[].class);
        DataWriter<byte[]> writer = participant.createPublisher().createDataWriter(topic);
        DataReader<byte[]> reader = participant.createSubscriber().createDataReader(topic);

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

        try (Sample.Iterator<byte[]> samples = reader.take()) {
            while (samples.hasNext()) {
                System.out.println("got: " + new String(samples.next().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>omgdds</artifactId>
    <version>1.0.0-rc.7</version>
</dependency>

Gradle

implementation 'org.zerodds:omgdds:1.0.0-rc.7'

Aus dem Source

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

Voraussetzungen

  • JDK 17 oder höher; mit dem Profil java8 baut das Hauptartefakt für Java 8 (siehe unten).
  • Kein nativer Build nötig — Pure-Java-Implementation.
  • Kein JNI, kein libzerodds.so.

Typisierte Topics — zerodds-idlc generate --lang java

IDL (temperature.idl)

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

Codegen + Nutzen

zerodds-idlc generate --lang java --out gen/ temperature.idl
# schreibt gen/ZdTypes.java, gen/ZdCodec.java und gen/ZdTypeSupports.java

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

▶ Runnable example: java-typed-temperature

Jedes IDL-Modul wird eine verschachtelte Klasse in ZdTypes. Temperature ist eine public static final class mit privaten Feldern, einem Konstruktor ohne Argumente und Bean-Zugriffsmethoden (getCelsius()/setCelsius(), getSensor_id()/setSensor_id()). Eine Union wird ebenso eine Klasse: Der Diskriminator ist die Property discriminator, dazu kommt ein Feld je Fall. Das ist Klausel 9 von DDS-Java-PSM 1.0 und der Default; --java-mapping omg erzeugt stattdessen öffentliche Felder und T[] für jede Sequenz. createDataWriter(topic) findet die erzeugte ZdTypeSupports-Klasse selbst; der Codec ruft org.zerodds.wire, das im JAR org.zerodds:omgdds enthalten ist. Vendor-Spec: zerodds-java-omgdds 1.0.

Java 8

Das JAR baut standardmäßig für Java 17. Das Maven-Profil java8 baut das Hauptartefakt für Java 8 (release 8); die Tests bleiben bei Java 17.

Runtime-JAR bauen

# Standard (Java 17)
mvn install

# Java 8
mvn -Pjava8 install

Der Hand-Code der Runtime ist var-frei und nutzt nur Java-8-Features (Lambdas, Consumer, default-Methoden). Der Code, den zerodds-idlc generate --lang java schreibt, ist ebenfalls Java 8; einen eigenen Codegen-Modus dafür gibt es nicht. Unions sind in jedem Fall Klassen (siehe oben).

Mehrere Prozesse

Ohne weitere Einstellung laufen Writer und Reader über einen Bus in derselben JVM (InProcessBus). Über Prozessgrenzen gibt es zwei Wege:

  • RTPS in Java: org.zerodds.rtps ist ein eigener RTPS-Stack in Java (SPDP, SEDP und DATA über UDP). Er ist abgeschaltet, bis -Dzerodds.rtps.enable=true oder die Umgebungsvariable ZERODDS_RTPS=1 gesetzt ist; dann teilen sich alle Writer und Reader einer JVM einen RTPS-Participant je Domain.
  • gRPC-Bridge: org.zerodds.bridge.GrpcBridgeClient spricht HTTP/2 mit dem Daemon zerodds-grpc-bridged, der auf der DDS-Seite publiziert und abonniert. Den Ablauf zeigt crates/java-omgdds/run_grpc_bridge_e2e.sh.

Vendor-Spec: §4 Multi-Process / Cross-Vendor

Binding · Java

Java — first sample in 5 minutes

Pure Java, no JNI, no libzerodds.so needed, with an RTPS stack of its own in Java (org.zerodds.rtps). An OMG DDS-Java-PSM-conformant org.omg.dds.* interface surface. IDL→Java codegen via zerodds-idlc generate --lang java.

JDK: 17+ · Java 8 with profile java8 Install: Maven / Gradle Spec: vendor spec

5-minute quickstart

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

1 · Project + Java binding

The binding is the Maven artifact org.zerodds:omgdds. Pure Java, no JNI: there is no native library to install.

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

pom.xml dep:

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

2 · Pub/sub roundtrip (src/main/java/com/example/App.java)

package com.example;

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

public class App {
    public static void main(String[] args) throws Exception {
        // DDS-Java-PSM 1.0 §7.3.1: the implementation class is named by a system property
        System.setProperty(ServiceEnvironment.IMPLEMENTATION_CLASS_NAME_PROPERTY,
                "org.zerodds.ServiceEnvironmentImpl");
        ServiceEnvironment env = ServiceEnvironment.createInstance(App.class.getClassLoader());
        DomainParticipant participant =
                DomainParticipantFactory.getInstance(env).createParticipant(0);

        Topic<byte[]> topic = participant.createTopic("Chatter", byte[].class);
        DataWriter<byte[]> writer = participant.createPublisher().createDataWriter(topic);
        DataReader<byte[]> reader = participant.createSubscriber().createDataReader(topic);

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

        try (Sample.Iterator<byte[]> samples = reader.take()) {
            while (samples.hasNext()) {
                System.out.println("got: " + new String(samples.next().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>omgdds</artifactId>
    <version>1.0.0-rc.7</version>
</dependency>

Gradle

implementation 'org.zerodds:omgdds:1.0.0-rc.7'

From source

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

Prerequisites

  • JDK 17 or higher; the java8 profile builds the main artifact for Java 8 (see below).
  • No native build needed — a pure-Java implementation.
  • No JNI, no libzerodds.so.

Typed topics — zerodds-idlc generate --lang java

IDL (temperature.idl)

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

Codegen + use

zerodds-idlc generate --lang java --out gen/ temperature.idl
# writes gen/ZdTypes.java, gen/ZdCodec.java and gen/ZdTypeSupports.java

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

▶ Runnable example: java-typed-temperature

Every IDL module becomes a nested class in ZdTypes. Temperature is a public static final class with private fields, a no-argument constructor and Bean accessors (getCelsius()/setCelsius(), getSensor_id()/setSensor_id()). A union becomes a class of the same kind: its discriminator is the property discriminator, plus one field per case. That is Clause 9 of DDS-Java-PSM 1.0 and the default; --java-mapping omg gives public fields and T[] for every sequence instead. createDataWriter(topic) finds the generated ZdTypeSupports class by itself; the codec calls org.zerodds.wire, which the org.zerodds:omgdds JAR contains. Vendor spec: zerodds-java-omgdds 1.0.

Java 8

The JAR builds for Java 17 by default. The Maven profile java8 builds the main artifact for Java 8 (release 8); the tests stay on Java 17.

Building the runtime JAR

# standard (Java 17)
mvn install

# Java 8
mvn -Pjava8 install

The runtime's hand-written code is var-free and uses only Java 8 features (lambdas, Consumer, default methods). The code zerodds-idlc generate --lang java writes is Java 8 as well; there is no separate codegen mode for it. Unions are classes either way (see above).

Multiple processes

Without further settings, writers and readers run over a bus inside one JVM (InProcessBus). Across processes there are two paths:

  • RTPS in Java: org.zerodds.rtps is an RTPS stack of its own, in Java (SPDP, SEDP and DATA over UDP). It is off until -Dzerodds.rtps.enable=true or the environment variable ZERODDS_RTPS=1 is set; then all writers and readers of one JVM share one RTPS participant per domain.
  • gRPC bridge: org.zerodds.bridge.GrpcBridgeClient speaks HTTP/2 to the zerodds-grpc-bridged daemon, which publishes and subscribes on the DDS side. crates/java-omgdds/run_grpc_bridge_e2e.sh shows the sequence.

Vendor spec: §4 multi-process / cross-vendor