Skip to content

psylsph/cyclonedds-java

Repository files navigation

CycloneDDS Java Wrapper

This project provides a Java JNI (Java Native Interface) wrapper around the Eclipse CycloneDDS C library, enabling Java developers to use DDS (Data Distribution Service) functionality in their applications.

Prerequisites

  • Java 8 or later
  • Maven 3.6 or later
  • CMake 3.10 or later
  • C++ compiler (GCC 7+, Clang 6+, or MSVC 2017+)
  • CycloneDDS installed in /opt/CycloneDDS (Linux/macOS) or C:\CycloneDDS (Windows)

Building the Project

Linux/macOS

  1. Set environment variables:

    export JAVA_HOME=/path/to/java
    export CYCLONEDDS_HOME=/path/to/cyclonedds  # Optional, defaults to /opt/CycloneDDS
  2. Build the project:

    chmod +x build.sh
    ./build.sh
    mvn clean compile
  3. Run tests:

    mvn test

Windows

  1. Set environment variables:

    set JAVA_HOME=C:\path\to\java
    set CYCLONEDDS_HOME=C:\path\to\cyclonedds  # Optional, defaults to C:\CycloneDDS
  2. Build the project:

    build.bat
    mvn clean compile
  3. Run tests:

    mvn test

Testing

For detailed information about testing, see the TESTING.md file.

Test Categories

  1. Unit Tests - Tests for individual classes and components that don't require the native library
  2. Mock Tests - Tests that verify behavior when the native library is not available
  3. Integration Tests - Tests that require the native library to be built and loaded

Running Tests

To run all tests:

mvn test

To run only unit tests that don't require the native library:

mvn test -Dtest=EntityTest,DurationTest,SampleInfoTest

Troubleshooting

If you encounter build or test issues, please refer to the TROUBLESHOOTING.md file for common problems and solutions.

Usage Example

Publisher Example

import org.eclipse.cyclonedds.core.*;
import org.eclipse.cyclonedds.types.*;
import org.eclipse.cyclonedds.internal.NativeLibrary;

public class HelloWorldPublisher {
    public static void main(String[] args) {
        // Initialize the native library
        NativeLibrary.initialize();
        
        try {
            // Create a domain participant
            DomainParticipant participant = new DomainParticipant(0);
            
            // Create a type support for HelloWorld
            HelloWorldTypeSupport typeSupport = new HelloWorldTypeSupport();
            typeSupport.registerType(participant);
            
            // Create a topic
            Topic<HelloWorld> topic = participant.createTopic(
                typeSupport, "HelloWorldTopic");
            
            // Create a publisher and data writer
            Publisher publisher = participant.createPublisher();
            DataWriter<HelloWorld> writer = publisher.createDataWriter(topic);
            
            // Create and write a sample
            HelloWorld sample = new HelloWorld();
            sample.message = "Hello from Java!";
            sample.id = 1;
            
            writer.write(sample);
            System.out.println("Sent: " + sample.message);
            
            // Clean up
            participant.delete();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Shutdown the native library
            NativeLibrary.shutdown();
        }
    }
    
    public static class HelloWorld {
        public String message;
        public int id;
    }
    
    public static class HelloWorldTypeSupport extends TypeSupport<HelloWorld> {
        public HelloWorldTypeSupport() {
            super(HelloWorld.class);
        }
        
        @Override
        protected long nativeCreateTypeSupport(String typeName) {
            return nativeCreateHelloWorldTypeSupport(typeName);
        }
        
        private static native long nativeCreateHelloWorldTypeSupport(String typeName);
    }
}

Subscriber Example

import org.eclipse.cyclonedds.core.*;
import org.eclipse.cyclonedds.types.*;
import org.eclipse.cyclonedds.internal.NativeLibrary;

import java.util.List;

public class HelloWorldSubscriber {
    public static void main(String[] args) {
        // Initialize the native library
        NativeLibrary.initialize();
        
        try {
            // Create a domain participant
            DomainParticipant participant = new DomainParticipant(0);
            
            // Create a type support for HelloWorld
            HelloWorldTypeSupport typeSupport = new HelloWorldTypeSupport();
            typeSupport.registerType(participant);
            
            // Create a topic
            Topic<HelloWorld> topic = participant.createTopic(
                typeSupport, "HelloWorldTopic");
            
            // Create a subscriber and data reader
            Subscriber subscriber = participant.createSubscriber();
            DataReader<HelloWorld> reader = subscriber.createDataReader(topic);
            
            // Wait for data
            while (true) {
                List<Sample<HelloWorld>> samples = reader.take();
                if (!samples.isEmpty()) {
                    for (Sample<HelloWorld> sample : samples) {
                        if (sample.isValidData()) {
                            HelloWorld data = sample.getData();
                            System.out.println("Received: " + data.message);
                        }
                    }
                }
                
                Thread.sleep(100);
            }
            
            // Clean up
            participant.delete();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Shutdown the native library
            NativeLibrary.shutdown();
        }
    }
    
    public static class HelloWorld {
        public String message;
        public int id;
    }
    
    public static class HelloWorldTypeSupport extends TypeSupport<HelloWorld> {
        public HelloWorldTypeSupport() {
            super(HelloWorld.class);
        }
        
        @Override
        protected long nativeCreateTypeSupport(String typeName) {
            return nativeCreateHelloWorldTypeSupport(typeName);
        }
        
        private static native long nativeCreateHelloWorldTypeSupport(String typeName);
    }
}

Running the Examples

To run the examples, you need to include the native library in the library path:

# Linux/macOS
java -Djava.library.path=target/native -cp target/classes:target/dependency/*:... HelloWorldPublisher

# Windows
java -Djava.library.path=target\native -cp target\classes;target\dependency\*;... HelloWorldPublisher

Features

  • Idiomatic Java API for DDS functionality
  • Type-safe operations for user-defined data types
  • Comprehensive QoS policy support
  • Robust memory management with automatic cleanup
  • Multi-platform support (Linux, macOS, Windows)
  • High performance with minimal JNI overhead
  • Comprehensive test suite with mock tests for environments without native library

Implementation Status

For a detailed list of implemented features and what's planned, see IMPLEMENTATION.md.

Documentation

For more detailed documentation, see the Javadoc generated with mvn javadoc:javadoc.

Contributing

When contributing to this project:

  1. Follow the existing code style
  2. Add tests for new functionality
  3. Update documentation
  4. Ensure all tests pass before submitting

License

This project is licensed under the Eclipse Public License v. 2.0 or the BSD 3-Clause License.

About

A JNI based Java Wrapper around CycloneDDS

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published