CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-kohlschutter-junixsocket--junixsocket-core

Java Unix Domain Socket implementation providing AF_UNIX, AF_TIPC, AF_VSOCK, and AF_SYSTEM socket support with traditional and NIO APIs

Pending
Overview
Eval results
Files

rmi.mddocs/

RMI Integration

Remote Method Invocation support over Unix Domain Sockets enabling efficient distributed computing within the same system, eliminating network overhead for local inter-process communication.

Capabilities

AFUNIXRMISocketFactory

RMI socket factory implementation for creating Unix Domain Socket connections for RMI communication.

/**
 * Unix Domain Socket RMI factory implementation
 */
public class AFUNIXRMISocketFactory extends AFRMISocketFactory {
    
    /**
     * Gets the singleton AFUNIXRMISocketFactory instance
     * @return AFUNIXRMISocketFactory instance
     * @throws IOException if factory creation fails
     */
    public static AFUNIXRMISocketFactory getInstance() throws IOException;
    
    /**
     * Creates AFUNIXRMISocketFactory with custom socket address
     * @param socketAddress The socket address for RMI communication
     * @return AFUNIXRMISocketFactory instance
     * @throws IOException if factory creation fails
     */
    public static AFUNIXRMISocketFactory getInstance(AFUNIXSocketAddress socketAddress) throws IOException;
    
    // RMISocketFactory implementation
    public Socket createSocket(String host, int port) throws IOException;
    public ServerSocket createServerSocket(int port) throws IOException;
    
    // Socket factory configuration
    public void setSocketAddress(AFUNIXSocketAddress socketAddress);
    public AFUNIXSocketAddress getSocketAddress();
}

Usage Examples:

import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.io.File;
import org.newsclub.net.unix.*;

// Define RMI service interface
public interface HelloService extends Remote {
    String sayHello(String name) throws RemoteException;
    int calculate(int a, int b) throws RemoteException;
}

// RMI server setup
public class RMIServer {
    public static void main(String[] args) throws Exception {
        // Create socket address for RMI
        File rmiSocket = new File("/tmp/rmi-server.sock");
        AFUNIXSocketAddress rmiAddress = AFUNIXSocketAddress.of(rmiSocket);
        
        // Configure RMI to use Unix Domain Sockets
        AFUNIXRMISocketFactory socketFactory = AFUNIXRMISocketFactory.getInstance(rmiAddress);
        System.setProperty("java.rmi.server.hostname", rmiAddress.toString());
        
        // Create and register service
        HelloService service = new HelloServiceImpl();
        HelloService stub = (HelloService) UnicastRemoteObject.exportObject(
            service, 0, socketFactory, socketFactory);
        
        // Bind service in registry (using file-based registry)
        AFUNIXRegistry registry = AFUNIXRegistry.createRegistry(rmiAddress);
        registry.bind("HelloService", stub);
        
        System.out.println("RMI Server ready on: " + rmiSocket);
        
        // Keep server running
        Thread.sleep(Long.MAX_VALUE);
    }
}

// RMI client
public class RMIClient {
    public static void main(String[] args) throws Exception {
        File rmiSocket = new File("/tmp/rmi-server.sock");
        AFUNIXSocketAddress rmiAddress = AFUNIXSocketAddress.of(rmiSocket);
        
        // Configure client to use Unix Domain Sockets
        AFUNIXRMISocketFactory socketFactory = AFUNIXRMISocketFactory.getInstance(rmiAddress);
        
        // Look up service
        AFUNIXRegistry registry = AFUNIXRegistry.getRegistry(rmiAddress);
        HelloService service = (HelloService) registry.lookup("HelloService");
        
        // Call remote methods
        String greeting = service.sayHello("World");
        System.out.println("Server says: " + greeting);
        
        int result = service.calculate(10, 20);
        System.out.println("Calculation result: " + result);
    }
}

AFRMIService

Base interface for RMI services providing Unix Domain Socket-specific functionality.

/**
 * RMI service interface for AF sockets
 */
public interface AFRMIService extends Remote {
    
    /**
     * Gets the socket address used by this RMI service
     * @return Socket address for the service
     * @throws RemoteException if operation fails
     */
    AFSocketAddress getServiceAddress() throws RemoteException;
    
    /**
     * Checks if the service is available
     * @return true if service is available
     * @throws RemoteException if operation fails
     */
    boolean isServiceAvailable() throws RemoteException;
    
    /**
     * Gets service metadata
     * @return Service information
     * @throws RemoteException if operation fails
     */
    String getServiceInfo() throws RemoteException;
}

Service Implementation Example:

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import org.newsclub.net.unix.*;

// Service implementation
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService, AFRMIService {
    private final AFUNIXSocketAddress serviceAddress;
    
    public HelloServiceImpl(AFUNIXSocketAddress address) throws RemoteException {
        super();
        this.serviceAddress = address;
    }
    
    @Override
    public String sayHello(String name) throws RemoteException {
        return "Hello, " + name + "! (via Unix Domain Socket RMI)";
    }
    
    @Override
    public int calculate(int a, int b) throws RemoteException {
        return a + b;
    }
    
    @Override
    public AFSocketAddress getServiceAddress() throws RemoteException {
        return serviceAddress;
    }
    
    @Override
    public boolean isServiceAvailable() throws RemoteException {
        return true;
    }
    
    @Override
    public String getServiceInfo() throws RemoteException {
        return "HelloService v1.0 - Unix Domain Socket RMI Implementation";
    }
}

AFUNIXRegistry

Unix Domain Socket-based RMI registry for service discovery and binding without network exposure.

/**
 * Unix Domain Socket RMI registry
 */
public class AFUNIXRegistry extends AFRegistry {
    
    /**
     * Creates a new registry bound to the specified address
     * @param address The socket address for the registry
     * @return AFUNIXRegistry instance
     * @throws RemoteException if registry creation fails
     */
    public static AFUNIXRegistry createRegistry(AFUNIXSocketAddress address) throws RemoteException;
    
    /**
     * Gets a reference to an existing registry
     * @param address The socket address of the registry
     * @return AFUNIXRegistry instance
     * @throws RemoteException if registry access fails
     */
    public static AFUNIXRegistry getRegistry(AFUNIXSocketAddress address) throws RemoteException;
    
    // Registry operations
    public void bind(String name, Remote obj) throws RemoteException, AlreadyBoundException;
    public void rebind(String name, Remote obj) throws RemoteException;
    public void unbind(String name) throws RemoteException, NotBoundException;
    public Remote lookup(String name) throws RemoteException, NotBoundException;
    public String[] list() throws RemoteException;
    
    // Registry properties
    public AFUNIXSocketAddress getRegistryAddress();
    public boolean isRegistryRunning();
}

Registry Usage Examples:

// Registry server
public class RegistryServer {
    public static void main(String[] args) throws Exception {
        File registrySocket = new File("/tmp/rmi-registry.sock");
        AFUNIXSocketAddress registryAddr = AFUNIXSocketAddress.of(registrySocket);
        
        // Create registry
        AFUNIXRegistry registry = AFUNIXRegistry.createRegistry(registryAddr);
        
        // Register multiple services
        HelloService helloService = new HelloServiceImpl(registryAddr);
        CalculatorService calcService = new CalculatorServiceImpl(registryAddr);
        
        registry.bind("HelloService", helloService);
        registry.bind("CalculatorService", calcService);
        
        System.out.println("Registry running with services:");
        String[] services = registry.list();
        for (String service : services) {
            System.out.println("  - " + service);
        }
        
        // Keep registry running
        Thread.sleep(Long.MAX_VALUE);
    }
}

// Service discovery client
public class ServiceDiscoveryClient {
    public static void main(String[] args) throws Exception {
        File registrySocket = new File("/tmp/rmi-registry.sock");
        AFUNIXSocketAddress registryAddr = AFUNIXSocketAddress.of(registrySocket);
        
        // Connect to registry
        AFUNIXRegistry registry = AFUNIXRegistry.getRegistry(registryAddr);
        
        // List available services
        System.out.println("Available services:");
        String[] services = registry.list();
        for (String serviceName : services) {
            System.out.println("  - " + serviceName);
            
            // Look up service details
            Remote service = registry.lookup(serviceName);
            if (service instanceof AFRMIService) {
                AFRMIService afService = (AFRMIService) service;
                System.out.println("    Info: " + afService.getServiceInfo());
                System.out.println("    Address: " + afService.getServiceAddress());
            }
        }
    }
}

Advanced RMI Features

Custom RMI Socket Factory

/**
 * Base class for AF RMI socket factories
 */
public abstract class AFRMISocketFactory implements RMIClientSocketFactory, RMIServerSocketFactory {
    
    // Factory configuration
    public abstract void setSocketAddress(AFSocketAddress address);
    public abstract AFSocketAddress getSocketAddress();
    
    // Socket creation with custom parameters
    public abstract Socket createSocket(String host, int port, SocketAddress localAddr, int timeout) throws IOException;
    public abstract ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException;
    
    // Factory management
    public static void setDefaultSocketFactory(AFRMISocketFactory factory);
    public static AFRMISocketFactory getDefaultSocketFactory();
}

Custom Factory Example:

// Custom RMI socket factory with connection pooling
public class PooledRMISocketFactory extends AFUNIXRMISocketFactory {
    private final ObjectPool<Socket> socketPool;
    private final int maxPoolSize;
    
    public PooledRMISocketFactory(AFUNIXSocketAddress address, int maxPoolSize) throws IOException {
        super(address);
        this.maxPoolSize = maxPoolSize;
        this.socketPool = new SocketPool(maxPoolSize);
    }
    
    @Override
    public Socket createSocket(String host, int port) throws IOException {
        Socket socket = socketPool.acquire();
        if (socket == null || socket.isClosed()) {
            socket = super.createSocket(host, port);
        }
        return new PooledSocket(socket, socketPool);
    }
    
    private static class SocketPool extends ObjectPool<Socket> {
        public SocketPool(int maxSize) {
            super(maxSize);
        }
        
        @Override
        protected Socket createObject() {
            return null; // Created externally
        }
        
        @Override
        protected boolean validateObject(Socket socket) {
            return socket != null && !socket.isClosed() && socket.isConnected();
        }
    }
    
    private static class PooledSocket extends Socket {
        private final Socket delegate;
        private final ObjectPool<Socket> pool;
        
        public PooledSocket(Socket delegate, ObjectPool<Socket> pool) {
            this.delegate = delegate;
            this.pool = pool;
        }
        
        @Override
        public void close() throws IOException {
            // Return to pool instead of closing
            pool.release(delegate);
        }
        
        // Delegate all other methods to the wrapped socket
        // ... delegation methods
    }
}

RMI Security and Configuration

// RMI security configuration for Unix Domain Sockets
public class RMISecurityConfig {
    
    public static void configureSecureRMI(AFUNIXSocketAddress address) throws Exception {
        // Set socket factory
        AFUNIXRMISocketFactory factory = AFUNIXRMISocketFactory.getInstance(address);
        
        // Configure RMI properties
        System.setProperty("java.rmi.server.hostname", address.toString());
        System.setProperty("java.rmi.server.randomIDs", "true");
        System.setProperty("java.rmi.dgc.leaseValue", "600000"); // 10 minutes
        
        // Install security manager if needed
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        
        // Set socket factory as default
        AFRMISocketFactory.setDefaultSocketFactory(factory);
    }
    
    public static void configurePeerCredentials(AFUNIXRMISocketFactory factory) throws IOException {
        // Enable peer credential checking
        factory.setSocketAddress(factory.getSocketAddress());
        
        // Custom socket creation with credential validation
        // Implementation would check peer credentials on connection
    }
}

Multi-Service RMI Management

// RMI service manager for multiple services
public class RMIServiceManager {
    private final AFUNIXRegistry registry;
    private final Map<String, Remote> services = new ConcurrentHashMap<>();
    private final AFUNIXRMISocketFactory socketFactory;
    
    public RMIServiceManager(AFUNIXSocketAddress registryAddress) throws Exception {
        this.socketFactory = AFUNIXRMISocketFactory.getInstance(registryAddress);
        this.registry = AFUNIXRegistry.createRegistry(registryAddress);
    }
    
    public void registerService(String name, Remote service) throws RemoteException {
        try {
            // Export service with Unix Domain Socket factory
            Remote stub = UnicastRemoteObject.exportObject(service, 0, socketFactory, socketFactory);
            
            // Bind in registry
            registry.bind(name, stub);
            services.put(name, service);
            
            System.out.println("Registered service: " + name);
        } catch (AlreadyBoundException e) {
            // Rebind if already exists
            registry.rebind(name, service);
            services.put(name, service);
            System.out.println("Re-registered service: " + name);
        }
    }
    
    public void unregisterService(String name) throws RemoteException, NotBoundException {
        registry.unbind(name);
        Remote service = services.remove(name);
        
        if (service != null) {
            try {
                UnicastRemoteObject.unexportObject(service, true);
            } catch (NoSuchObjectException e) {
                // Service already unexported
            }
        }
        
        System.out.println("Unregistered service: " + name);
    }
    
    public String[] listServices() throws RemoteException {
        return registry.list();
    }
    
    public void shutdown() throws RemoteException {
        // Unregister all services
        for (String serviceName : services.keySet()) {
            try {
                unregisterService(serviceName);
            } catch (Exception e) {
                System.err.println("Error unregistering " + serviceName + ": " + e.getMessage());
            }
        }
        
        // Shutdown registry (implementation specific)
        // registry.shutdown();
    }
}

Error Handling

RMI-specific exception handling patterns:

// RMI exceptions
public class RemoteException extends IOException;
public class NotBoundException extends Exception;
public class AlreadyBoundException extends Exception;
public class NoSuchObjectException extends RemoteException;
public class ConnectException extends RemoteException;
public class ServerException extends RemoteException;

Error Handling Examples:

try {
    AFUNIXRegistry registry = AFUNIXRegistry.getRegistry(registryAddress);
    HelloService service = (HelloService) registry.lookup("HelloService");
    
    String result = service.sayHello("Client");
    System.out.println("Result: " + result);
    
} catch (NotBoundException e) {
    System.err.println("Service not found in registry: " + e.getMessage());
} catch (ConnectException e) {
    System.err.println("Failed to connect to RMI service: " + e.getMessage());
} catch (ServerException e) {
    System.err.println("Server-side error: " + e.getMessage());
} catch (RemoteException e) {
    System.err.println("RMI communication error: " + e.getMessage());
} catch (ClassCastException e) {
    System.err.println("Service interface mismatch: " + e.getMessage());
}

// Registry binding error handling
try {
    registry.bind("MyService", serviceImpl);
} catch (AlreadyBoundException e) {
    System.out.println("Service already bound, rebinding...");
    registry.rebind("MyService", serviceImpl);
} catch (RemoteException e) {
    System.err.println("Failed to bind service: " + e.getMessage());
}

Performance Considerations

Connection Management

// Efficient RMI connection handling
public class OptimizedRMIClient {
    private final AFUNIXRegistry registry;
    private final Map<Class<?>, Remote> serviceCache = new ConcurrentHashMap<>();
    
    public OptimizedRMIClient(AFUNIXSocketAddress registryAddr) throws RemoteException {
        this.registry = AFUNIXRegistry.getRegistry(registryAddr);
    }
    
    @SuppressWarnings("unchecked")
    public <T extends Remote> T getService(String serviceName, Class<T> serviceInterface) throws RemoteException, NotBoundException {
        // Check cache first
        T service = (T) serviceCache.get(serviceInterface);
        if (service != null) {
            try {
                // Test connection
                if (service instanceof AFRMIService) {
                    ((AFRMIService) service).isServiceAvailable();
                }
                return service;
            } catch (RemoteException e) {
                // Service unavailable, remove from cache
                serviceCache.remove(serviceInterface);
            }
        }
        
        // Look up service
        service = (T) registry.lookup(serviceName);
        serviceCache.put(serviceInterface, service);
        return service;
    }
    
    public void clearCache() {
        serviceCache.clear();
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-kohlschutter-junixsocket--junixsocket-core

docs

addressing.md

capabilities.md

datagram-sockets.md

exceptions.md

file-descriptors.md

index.md

nio-channels.md

rmi.md

socket-pairs.md

unix-sockets.md

utilities.md

tile.json