Package com.lucimber.dbus.message


package com.lucimber.dbus.message
D-Bus message types and structures for method calls, returns, signals, and errors.

This package provides the core message abstractions for D-Bus communication. All D-Bus interactions are based on four fundamental message types, each with specific purposes and structures.

Getting Started

For first-time users: Start with OutboundMethodCall.Builder to create method calls, and learn to handle InboundMethodReturn and InboundError responses. For event-driven programming, explore OutboundSignal and InboundSignal.

Message Types

Method Calls (OutboundMethodCall)

Request messages sent to invoke methods on remote D-Bus objects:

  • Contains target object path, interface, and method name
  • Carries typed arguments for the method invocation
  • Can optionally expect a reply message
  • Includes caller authentication information

Method Returns (InboundMethodReturn)

Success response messages returned from method calls:

  • Contains the return values from the method execution
  • Matches the original method call via serial number
  • Provides type-safe access to return data
  • Indicates successful method completion

Error Messages (InboundError)

Failure response messages indicating method call errors:

  • Contains error name and optional error message
  • Matches the failed method call via serial number
  • Provides structured error information
  • Follows D-Bus error naming conventions

Signal Messages (InboundSignal)

Broadcast messages for event notification:

  • Emitted by services to notify interested clients
  • Contains event data and context information
  • Can be filtered by interface, member, or sender
  • Supports event-driven programming patterns

Usage Examples

Creating Method Calls


 // Create a method call to get system information
 OutboundMethodCall call = OutboundMethodCall.Builder
     .create()
     .withPath(DBusObjectPath.valueOf("/org/freedesktop/hostname1"))
     .withInterface(DBusString.valueOf("org.freedesktop.hostname1"))
     .withMember(DBusString.valueOf("GetHostname"))
     .withDestination(DBusString.valueOf("org.freedesktop.hostname1"))
     .withReplyExpected(true)
     .build();

 // Send the call and handle the response
 CompletableFuture<InboundMessage> response = connection.sendRequest(call);
 response.thenAccept(reply -> {
     if (reply instanceof InboundMethodReturn) {
         InboundMethodReturn returnMsg = (InboundMethodReturn) reply;
         List<DBusType> returnValues = returnMsg.getBody();
         if (!returnValues.isEmpty()) {
             DBusString hostname = (DBusString) returnValues.get(0);
             System.out.println("Hostname: " + hostname.toString());
         }
     } else if (reply instanceof InboundError) {
         InboundError error = (InboundError) reply;
         System.err.println("Error: " + error.getErrorName());
     }
 });
 

Method Call with Arguments


 // Create a method call with typed arguments
 OutboundMethodCall setProperty = OutboundMethodCall.Builder
     .create()
     .withPath(DBusObjectPath.valueOf("/org/example/Object"))
     .withInterface(DBusString.valueOf("org.freedesktop.DBus.Properties"))
     .withMember(DBusString.valueOf("Set"))
     .withDestination(DBusString.valueOf("org.example.Service"))
     .withBody(Arrays.asList(
         DBusString.valueOf("org.example.Interface"),
         DBusString.valueOf("PropertyName"),
         DBusVariant.valueOf(DBusString.valueOf("PropertyValue"))
     ))
     .withReplyExpected(true)
     .build();
 

Handling Signals


 // Install a signal handler in the pipeline
 connection.getPipeline().addLast("signal-handler", new AbstractInboundHandler() {
     @Override
     public void handleInboundMessage(Context ctx, InboundMessage msg) {
         if (msg instanceof InboundSignal) {
             InboundSignal signal = (InboundSignal) msg;

             // Check signal details
             String interfaceName = signal.getInterfaceName()
                 .map(DBusString::toString)
                 .orElse("unknown");
             String memberName = signal.getMember().toString();

             System.out.println("Signal: " + interfaceName + "." + memberName);

             // Process signal arguments
             List<DBusType> arguments = signal.getBody();
             for (int i = 0; i < arguments.size(); i++) {
                 System.out.println("  arg" + i + ": " + arguments.get(i));
             }
         }

         ctx.propagateInboundMessage(msg);
     }
 });
 

Error Handling


 // Handle different types of errors
 private void handleMethodResponse(InboundMessage response) {
     if (response instanceof InboundMethodReturn) {
         InboundMethodReturn returnMsg = (InboundMethodReturn) response;
         processSuccessfulResponse(returnMsg);

     } else if (response instanceof InboundError) {
         InboundError error = (InboundError) response;
         String errorName = error.getErrorName().toString();

         // Handle specific error types
         switch (errorName) {
             case "org.freedesktop.DBus.Error.ServiceUnknown":
                 System.err.println("Service not available");
                 break;
             case "org.freedesktop.DBus.Error.AccessDenied":
                 System.err.println("Access denied");
                 break;
             default:
                 System.err.println("Method failed: " + errorName);
                 if (!error.getBody().isEmpty()) {
                     System.err.println("Error details: " + error.getBody().get(0));
                 }
         }
     }
 }
 

Message Structure

All D-Bus messages share a common structure:

  • Header: Contains message type, flags, and routing information
  • Body: Contains typed arguments or return values
  • Serial: Unique identifier for request/response matching
  • Sender: Unique connection name of the message sender

Message Routing

D-Bus messages are routed based on several key fields:

  • Destination: Target service name (for method calls)
  • Object Path: Target object within the service
  • Interface: Specific interface on the object
  • Member: Method name or signal name

Asynchronous Processing

All message operations are asynchronous and return CompletionStage:

  • Method calls return futures that complete with method returns or errors
  • Signal handling is event-driven through the handler pipeline
  • Message processing never blocks the calling thread
  • Timeouts and cancellation are supported through CompletionStage

Type Safety

Message bodies use the type-safe D-Bus type system:

  • All arguments and return values are strongly typed
  • Type mismatches are caught at compile time when possible
  • Runtime validation ensures D-Bus specification compliance
  • Automatic marshalling/unmarshalling of complex types
Since:
1.0
See Also: