0
# RMI Integration
1
2
Remote Method Invocation support over Unix Domain Sockets enabling efficient distributed computing within the same system, eliminating network overhead for local inter-process communication.
3
4
## Capabilities
5
6
### AFUNIXRMISocketFactory
7
8
RMI socket factory implementation for creating Unix Domain Socket connections for RMI communication.
9
10
```java { .api }
11
/**
12
* Unix Domain Socket RMI factory implementation
13
*/
14
public class AFUNIXRMISocketFactory extends AFRMISocketFactory {
15
16
/**
17
* Gets the singleton AFUNIXRMISocketFactory instance
18
* @return AFUNIXRMISocketFactory instance
19
* @throws IOException if factory creation fails
20
*/
21
public static AFUNIXRMISocketFactory getInstance() throws IOException;
22
23
/**
24
* Creates AFUNIXRMISocketFactory with custom socket address
25
* @param socketAddress The socket address for RMI communication
26
* @return AFUNIXRMISocketFactory instance
27
* @throws IOException if factory creation fails
28
*/
29
public static AFUNIXRMISocketFactory getInstance(AFUNIXSocketAddress socketAddress) throws IOException;
30
31
// RMISocketFactory implementation
32
public Socket createSocket(String host, int port) throws IOException;
33
public ServerSocket createServerSocket(int port) throws IOException;
34
35
// Socket factory configuration
36
public void setSocketAddress(AFUNIXSocketAddress socketAddress);
37
public AFUNIXSocketAddress getSocketAddress();
38
}
39
```
40
41
**Usage Examples:**
42
43
```java
44
import java.rmi.Naming;
45
import java.rmi.Remote;
46
import java.rmi.RemoteException;
47
import java.rmi.server.UnicastRemoteObject;
48
import java.io.File;
49
import org.newsclub.net.unix.*;
50
51
// Define RMI service interface
52
public interface HelloService extends Remote {
53
String sayHello(String name) throws RemoteException;
54
int calculate(int a, int b) throws RemoteException;
55
}
56
57
// RMI server setup
58
public class RMIServer {
59
public static void main(String[] args) throws Exception {
60
// Create socket address for RMI
61
File rmiSocket = new File("/tmp/rmi-server.sock");
62
AFUNIXSocketAddress rmiAddress = AFUNIXSocketAddress.of(rmiSocket);
63
64
// Configure RMI to use Unix Domain Sockets
65
AFUNIXRMISocketFactory socketFactory = AFUNIXRMISocketFactory.getInstance(rmiAddress);
66
System.setProperty("java.rmi.server.hostname", rmiAddress.toString());
67
68
// Create and register service
69
HelloService service = new HelloServiceImpl();
70
HelloService stub = (HelloService) UnicastRemoteObject.exportObject(
71
service, 0, socketFactory, socketFactory);
72
73
// Bind service in registry (using file-based registry)
74
AFUNIXRegistry registry = AFUNIXRegistry.createRegistry(rmiAddress);
75
registry.bind("HelloService", stub);
76
77
System.out.println("RMI Server ready on: " + rmiSocket);
78
79
// Keep server running
80
Thread.sleep(Long.MAX_VALUE);
81
}
82
}
83
84
// RMI client
85
public class RMIClient {
86
public static void main(String[] args) throws Exception {
87
File rmiSocket = new File("/tmp/rmi-server.sock");
88
AFUNIXSocketAddress rmiAddress = AFUNIXSocketAddress.of(rmiSocket);
89
90
// Configure client to use Unix Domain Sockets
91
AFUNIXRMISocketFactory socketFactory = AFUNIXRMISocketFactory.getInstance(rmiAddress);
92
93
// Look up service
94
AFUNIXRegistry registry = AFUNIXRegistry.getRegistry(rmiAddress);
95
HelloService service = (HelloService) registry.lookup("HelloService");
96
97
// Call remote methods
98
String greeting = service.sayHello("World");
99
System.out.println("Server says: " + greeting);
100
101
int result = service.calculate(10, 20);
102
System.out.println("Calculation result: " + result);
103
}
104
}
105
```
106
107
### AFRMIService
108
109
Base interface for RMI services providing Unix Domain Socket-specific functionality.
110
111
```java { .api }
112
/**
113
* RMI service interface for AF sockets
114
*/
115
public interface AFRMIService extends Remote {
116
117
/**
118
* Gets the socket address used by this RMI service
119
* @return Socket address for the service
120
* @throws RemoteException if operation fails
121
*/
122
AFSocketAddress getServiceAddress() throws RemoteException;
123
124
/**
125
* Checks if the service is available
126
* @return true if service is available
127
* @throws RemoteException if operation fails
128
*/
129
boolean isServiceAvailable() throws RemoteException;
130
131
/**
132
* Gets service metadata
133
* @return Service information
134
* @throws RemoteException if operation fails
135
*/
136
String getServiceInfo() throws RemoteException;
137
}
138
```
139
140
**Service Implementation Example:**
141
142
```java
143
import java.rmi.RemoteException;
144
import java.rmi.server.UnicastRemoteObject;
145
import org.newsclub.net.unix.*;
146
147
// Service implementation
148
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService, AFRMIService {
149
private final AFUNIXSocketAddress serviceAddress;
150
151
public HelloServiceImpl(AFUNIXSocketAddress address) throws RemoteException {
152
super();
153
this.serviceAddress = address;
154
}
155
156
@Override
157
public String sayHello(String name) throws RemoteException {
158
return "Hello, " + name + "! (via Unix Domain Socket RMI)";
159
}
160
161
@Override
162
public int calculate(int a, int b) throws RemoteException {
163
return a + b;
164
}
165
166
@Override
167
public AFSocketAddress getServiceAddress() throws RemoteException {
168
return serviceAddress;
169
}
170
171
@Override
172
public boolean isServiceAvailable() throws RemoteException {
173
return true;
174
}
175
176
@Override
177
public String getServiceInfo() throws RemoteException {
178
return "HelloService v1.0 - Unix Domain Socket RMI Implementation";
179
}
180
}
181
```
182
183
### AFUNIXRegistry
184
185
Unix Domain Socket-based RMI registry for service discovery and binding without network exposure.
186
187
```java { .api }
188
/**
189
* Unix Domain Socket RMI registry
190
*/
191
public class AFUNIXRegistry extends AFRegistry {
192
193
/**
194
* Creates a new registry bound to the specified address
195
* @param address The socket address for the registry
196
* @return AFUNIXRegistry instance
197
* @throws RemoteException if registry creation fails
198
*/
199
public static AFUNIXRegistry createRegistry(AFUNIXSocketAddress address) throws RemoteException;
200
201
/**
202
* Gets a reference to an existing registry
203
* @param address The socket address of the registry
204
* @return AFUNIXRegistry instance
205
* @throws RemoteException if registry access fails
206
*/
207
public static AFUNIXRegistry getRegistry(AFUNIXSocketAddress address) throws RemoteException;
208
209
// Registry operations
210
public void bind(String name, Remote obj) throws RemoteException, AlreadyBoundException;
211
public void rebind(String name, Remote obj) throws RemoteException;
212
public void unbind(String name) throws RemoteException, NotBoundException;
213
public Remote lookup(String name) throws RemoteException, NotBoundException;
214
public String[] list() throws RemoteException;
215
216
// Registry properties
217
public AFUNIXSocketAddress getRegistryAddress();
218
public boolean isRegistryRunning();
219
}
220
```
221
222
**Registry Usage Examples:**
223
224
```java
225
// Registry server
226
public class RegistryServer {
227
public static void main(String[] args) throws Exception {
228
File registrySocket = new File("/tmp/rmi-registry.sock");
229
AFUNIXSocketAddress registryAddr = AFUNIXSocketAddress.of(registrySocket);
230
231
// Create registry
232
AFUNIXRegistry registry = AFUNIXRegistry.createRegistry(registryAddr);
233
234
// Register multiple services
235
HelloService helloService = new HelloServiceImpl(registryAddr);
236
CalculatorService calcService = new CalculatorServiceImpl(registryAddr);
237
238
registry.bind("HelloService", helloService);
239
registry.bind("CalculatorService", calcService);
240
241
System.out.println("Registry running with services:");
242
String[] services = registry.list();
243
for (String service : services) {
244
System.out.println(" - " + service);
245
}
246
247
// Keep registry running
248
Thread.sleep(Long.MAX_VALUE);
249
}
250
}
251
252
// Service discovery client
253
public class ServiceDiscoveryClient {
254
public static void main(String[] args) throws Exception {
255
File registrySocket = new File("/tmp/rmi-registry.sock");
256
AFUNIXSocketAddress registryAddr = AFUNIXSocketAddress.of(registrySocket);
257
258
// Connect to registry
259
AFUNIXRegistry registry = AFUNIXRegistry.getRegistry(registryAddr);
260
261
// List available services
262
System.out.println("Available services:");
263
String[] services = registry.list();
264
for (String serviceName : services) {
265
System.out.println(" - " + serviceName);
266
267
// Look up service details
268
Remote service = registry.lookup(serviceName);
269
if (service instanceof AFRMIService) {
270
AFRMIService afService = (AFRMIService) service;
271
System.out.println(" Info: " + afService.getServiceInfo());
272
System.out.println(" Address: " + afService.getServiceAddress());
273
}
274
}
275
}
276
}
277
```
278
279
## Advanced RMI Features
280
281
### Custom RMI Socket Factory
282
283
```java { .api }
284
/**
285
* Base class for AF RMI socket factories
286
*/
287
public abstract class AFRMISocketFactory implements RMIClientSocketFactory, RMIServerSocketFactory {
288
289
// Factory configuration
290
public abstract void setSocketAddress(AFSocketAddress address);
291
public abstract AFSocketAddress getSocketAddress();
292
293
// Socket creation with custom parameters
294
public abstract Socket createSocket(String host, int port, SocketAddress localAddr, int timeout) throws IOException;
295
public abstract ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException;
296
297
// Factory management
298
public static void setDefaultSocketFactory(AFRMISocketFactory factory);
299
public static AFRMISocketFactory getDefaultSocketFactory();
300
}
301
```
302
303
**Custom Factory Example:**
304
305
```java
306
// Custom RMI socket factory with connection pooling
307
public class PooledRMISocketFactory extends AFUNIXRMISocketFactory {
308
private final ObjectPool<Socket> socketPool;
309
private final int maxPoolSize;
310
311
public PooledRMISocketFactory(AFUNIXSocketAddress address, int maxPoolSize) throws IOException {
312
super(address);
313
this.maxPoolSize = maxPoolSize;
314
this.socketPool = new SocketPool(maxPoolSize);
315
}
316
317
@Override
318
public Socket createSocket(String host, int port) throws IOException {
319
Socket socket = socketPool.acquire();
320
if (socket == null || socket.isClosed()) {
321
socket = super.createSocket(host, port);
322
}
323
return new PooledSocket(socket, socketPool);
324
}
325
326
private static class SocketPool extends ObjectPool<Socket> {
327
public SocketPool(int maxSize) {
328
super(maxSize);
329
}
330
331
@Override
332
protected Socket createObject() {
333
return null; // Created externally
334
}
335
336
@Override
337
protected boolean validateObject(Socket socket) {
338
return socket != null && !socket.isClosed() && socket.isConnected();
339
}
340
}
341
342
private static class PooledSocket extends Socket {
343
private final Socket delegate;
344
private final ObjectPool<Socket> pool;
345
346
public PooledSocket(Socket delegate, ObjectPool<Socket> pool) {
347
this.delegate = delegate;
348
this.pool = pool;
349
}
350
351
@Override
352
public void close() throws IOException {
353
// Return to pool instead of closing
354
pool.release(delegate);
355
}
356
357
// Delegate all other methods to the wrapped socket
358
// ... delegation methods
359
}
360
}
361
```
362
363
### RMI Security and Configuration
364
365
```java
366
// RMI security configuration for Unix Domain Sockets
367
public class RMISecurityConfig {
368
369
public static void configureSecureRMI(AFUNIXSocketAddress address) throws Exception {
370
// Set socket factory
371
AFUNIXRMISocketFactory factory = AFUNIXRMISocketFactory.getInstance(address);
372
373
// Configure RMI properties
374
System.setProperty("java.rmi.server.hostname", address.toString());
375
System.setProperty("java.rmi.server.randomIDs", "true");
376
System.setProperty("java.rmi.dgc.leaseValue", "600000"); // 10 minutes
377
378
// Install security manager if needed
379
if (System.getSecurityManager() == null) {
380
System.setSecurityManager(new SecurityManager());
381
}
382
383
// Set socket factory as default
384
AFRMISocketFactory.setDefaultSocketFactory(factory);
385
}
386
387
public static void configurePeerCredentials(AFUNIXRMISocketFactory factory) throws IOException {
388
// Enable peer credential checking
389
factory.setSocketAddress(factory.getSocketAddress());
390
391
// Custom socket creation with credential validation
392
// Implementation would check peer credentials on connection
393
}
394
}
395
```
396
397
### Multi-Service RMI Management
398
399
```java
400
// RMI service manager for multiple services
401
public class RMIServiceManager {
402
private final AFUNIXRegistry registry;
403
private final Map<String, Remote> services = new ConcurrentHashMap<>();
404
private final AFUNIXRMISocketFactory socketFactory;
405
406
public RMIServiceManager(AFUNIXSocketAddress registryAddress) throws Exception {
407
this.socketFactory = AFUNIXRMISocketFactory.getInstance(registryAddress);
408
this.registry = AFUNIXRegistry.createRegistry(registryAddress);
409
}
410
411
public void registerService(String name, Remote service) throws RemoteException {
412
try {
413
// Export service with Unix Domain Socket factory
414
Remote stub = UnicastRemoteObject.exportObject(service, 0, socketFactory, socketFactory);
415
416
// Bind in registry
417
registry.bind(name, stub);
418
services.put(name, service);
419
420
System.out.println("Registered service: " + name);
421
} catch (AlreadyBoundException e) {
422
// Rebind if already exists
423
registry.rebind(name, service);
424
services.put(name, service);
425
System.out.println("Re-registered service: " + name);
426
}
427
}
428
429
public void unregisterService(String name) throws RemoteException, NotBoundException {
430
registry.unbind(name);
431
Remote service = services.remove(name);
432
433
if (service != null) {
434
try {
435
UnicastRemoteObject.unexportObject(service, true);
436
} catch (NoSuchObjectException e) {
437
// Service already unexported
438
}
439
}
440
441
System.out.println("Unregistered service: " + name);
442
}
443
444
public String[] listServices() throws RemoteException {
445
return registry.list();
446
}
447
448
public void shutdown() throws RemoteException {
449
// Unregister all services
450
for (String serviceName : services.keySet()) {
451
try {
452
unregisterService(serviceName);
453
} catch (Exception e) {
454
System.err.println("Error unregistering " + serviceName + ": " + e.getMessage());
455
}
456
}
457
458
// Shutdown registry (implementation specific)
459
// registry.shutdown();
460
}
461
}
462
```
463
464
## Error Handling
465
466
RMI-specific exception handling patterns:
467
468
```java { .api }
469
// RMI exceptions
470
public class RemoteException extends IOException;
471
public class NotBoundException extends Exception;
472
public class AlreadyBoundException extends Exception;
473
public class NoSuchObjectException extends RemoteException;
474
public class ConnectException extends RemoteException;
475
public class ServerException extends RemoteException;
476
```
477
478
**Error Handling Examples:**
479
480
```java
481
try {
482
AFUNIXRegistry registry = AFUNIXRegistry.getRegistry(registryAddress);
483
HelloService service = (HelloService) registry.lookup("HelloService");
484
485
String result = service.sayHello("Client");
486
System.out.println("Result: " + result);
487
488
} catch (NotBoundException e) {
489
System.err.println("Service not found in registry: " + e.getMessage());
490
} catch (ConnectException e) {
491
System.err.println("Failed to connect to RMI service: " + e.getMessage());
492
} catch (ServerException e) {
493
System.err.println("Server-side error: " + e.getMessage());
494
} catch (RemoteException e) {
495
System.err.println("RMI communication error: " + e.getMessage());
496
} catch (ClassCastException e) {
497
System.err.println("Service interface mismatch: " + e.getMessage());
498
}
499
500
// Registry binding error handling
501
try {
502
registry.bind("MyService", serviceImpl);
503
} catch (AlreadyBoundException e) {
504
System.out.println("Service already bound, rebinding...");
505
registry.rebind("MyService", serviceImpl);
506
} catch (RemoteException e) {
507
System.err.println("Failed to bind service: " + e.getMessage());
508
}
509
```
510
511
## Performance Considerations
512
513
### Connection Management
514
515
```java
516
// Efficient RMI connection handling
517
public class OptimizedRMIClient {
518
private final AFUNIXRegistry registry;
519
private final Map<Class<?>, Remote> serviceCache = new ConcurrentHashMap<>();
520
521
public OptimizedRMIClient(AFUNIXSocketAddress registryAddr) throws RemoteException {
522
this.registry = AFUNIXRegistry.getRegistry(registryAddr);
523
}
524
525
@SuppressWarnings("unchecked")
526
public <T extends Remote> T getService(String serviceName, Class<T> serviceInterface) throws RemoteException, NotBoundException {
527
// Check cache first
528
T service = (T) serviceCache.get(serviceInterface);
529
if (service != null) {
530
try {
531
// Test connection
532
if (service instanceof AFRMIService) {
533
((AFRMIService) service).isServiceAvailable();
534
}
535
return service;
536
} catch (RemoteException e) {
537
// Service unavailable, remove from cache
538
serviceCache.remove(serviceInterface);
539
}
540
}
541
542
// Look up service
543
service = (T) registry.lookup(serviceName);
544
serviceCache.put(serviceInterface, service);
545
return service;
546
}
547
548
public void clearCache() {
549
serviceCache.clear();
550
}
551
}
552
```