Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

697 Commits

Repository files navigation

RLib

A modular Java utility library providing common utilities for classpath scanning, runtime compilation, logging, networking, mail, collections, concurrency, and more.

Build Status

Requirements

  • Java 21+
  • Gradle 9.1+ (wrapper included)
  • Docker (for running Testcontainers-based tests)

Modules

ModuleDescription
rlib-commonCore utilities and common functionality
rlib-collectionsExtended collection implementations
rlib-compilerRuntime Java source compilation API
rlib-concurrentConcurrency utilities and helpers
rlib-eventbusTyped low-overhead event bus API
rlib-classpathClasspath scanning and class discovery
rlib-functionsFunctional interfaces and utilities
rlib-geometryGeometry utilities
rlib-ioI/O utilities
rlib-referenceReference utilities
rlib-reusableObject pooling and reusable resources
rlib-logger-apiLogging API
rlib-logger-implDefault logger implementation
rlib-logger-slf4jSLF4J logger bridge
rlib-networkReactive network API (client/server)
rlib-mailEmail sending utilities
rlib-testcontainersTest utilities including Fake SMTP container
rlib-fxJavaFX utilities
rlib-plugin-systemPlugin system framework

Installation

Gradle

repositories {
maven {
url "https://gitlab.com/api/v4/projects/37512056/packages/maven"
}
}
ext {
rlibVersion ="10.0.alpha17"
}
dependencies {
implementation "javasabr.rlib:rlib-common:$rlibVersion"
implementation "javasabr.rlib:rlib-collections:$rlibVersion"
implementation "javasabr.rlib:rlib-compiler:$rlibVersion"
implementation "javasabr.rlib:rlib-concurrent:$rlibVersion"
implementation "javasabr.rlib:rlib-eventbus:$rlibVersion"
implementation "javasabr.rlib:rlib-geometry:$rlibVersion"
implementation "javasabr.rlib:rlib-logger-api:$rlibVersion"
implementation "javasabr.rlib:rlib-logger-slf4j:$rlibVersion"
implementation "javasabr.rlib:rlib-plugin-system:$rlibVersion"
implementation "javasabr.rlib:rlib-reference:$rlibVersion"
implementation "javasabr.rlib:rlib-reusable:$rlibVersion"
implementation "javasabr.rlib:rlib-eventbus:$rlibVersion"
implementation "javasabr.rlib:rlib-fx:$rlibVersion"
implementation "javasabr.rlib:rlib-network:$rlibVersion"
implementation "javasabr.rlib:rlib-mail:$rlibVersion"
implementation "javasabr.rlib:rlib-testcontainers:$rlibVersion"
}

Usage Examples

Classpath Scanner API

Scan classpath to discover classes implementing interfaces or extending base classes:

varscanner = ClassPathScannerFactory.newDefaultScanner();
scanner.setUseSystemClasspath(true);
scanner.scan();
varimplementations = scanner.findImplements(Collection.class);
varinherited = scanner.findInherited(AbstractArray.class);

Compiler API

Compile Java source code at runtime:

varjavaSource = getClass().getResource("/java/source/TestCompileJavaSource.java");
varcompiler = CompilerFactory.newDefaultCompiler();
varcompiled = compiler.compile(javaSource.toURI());
varinstance = ClassUtils.newInstance(compiled[0]);
varmethod = instance.getClass().getMethod("makeString");
varresult = method.invoke(instance);

Logger API

Flexible logging with lazy evaluation and configurable log levels:

// getting logger by class/namevarlogger = LoggerManager.getLogger(getClass());
// global enable/disable debug levelLoggerLevel.DEBUG.setEnabled(true);
logger.debug("Simple message");
logger.debug(5, (val) -> "Lazy message with 5: " + val);
logger.debug(5, "Lazy message with 5:%d"::formatted);
logger.debug(5, 10D, (val1, val2) -> "Lazy message with 5: " + val1 + " and 10: " + val2);
logger.debug(5, 10D, "Lazy message with 5:%d and 10:%d"::formatted);
// global disable debug levelLoggerLevel.DEBUG.setEnabled(false);
// local enable debug level only for this logger instancelogger.setEnabled(LoggerLevel.DEBUG, true);

EventBus API

Type-safe event publishing and subscription with low dispatch overhead:

interfaceAppEventsextendsEventBus.TypeIdSet {}
recordUserCreatedEvent(
StringuserId,
EventBus.TypeId<AppEvents, UserCreatedEvent> typeId
) implementsEventBus.Event<AppEvents> {}
vartypeIdFactory = EventBusFactory.createTypeIdFactory(AppEvents.class);
vareventBus = EventBusFactory.createEventBus(typeIdFactory);
varuserCreatedTypeId = typeIdFactory.typeIdOf(UserCreatedEvent.class);
eventBus.subscribe(userCreatedTypeId, event ->
System.out.println("User created: " + event.userId()));
eventBus.send(newUserCreatedEvent("user-42", userCreatedTypeId));
eventBus.sendInBackground(newUserCreatedEvent("user-43", userCreatedTypeId));

Mail Sender

Send emails synchronously or asynchronously:

varconfig = MailSenderConfig
.builder()
.from("from@test.com")
.host("smtp.test.com")
.port(smtpPort)
.password(smtpPassword)
.username(smtpUser)
.useAuth(true)
.enableTtls(true)
.sslHost("smtp.test.com")
.build();
varjavaxConfig = JavaxMailSender.JavaxMailSenderConfig
.builder()
.executorKeepAlive(120)
.executorMaxThreads(20)
.executorMinThreads(1)
.build();
varsender = newJavaxMailSender(config, javaxConfig);
sender.send("to@test.com", "Test Subject", "Content");
sender
.sendAsync("to@test.com", "Test Subject", "Content")
.thenAccept(aVoid -> System.out.println("done!"));

Network API

Reactive network communication with simple client/server setup:

varserverNetwork = NetworkFactory.newStringDataServerNetwork();
varserverAddress = serverNetwork.start();
serverNetwork
.accepted()
.flatMap(Connection::receivedEvents)
.subscribe(event -> {
varmessage = event.packet.getData();
System.out.println("Received from client: " + message);
event.connection.send(newStringWritablePacket("Echo: " + message));
});
varclientNetwork = NetworkFactory.newStringDataClientNetwork();
clientNetwork
.connected(serverAddress)
.doOnNext(connection -> IntStream
.range(10, 100)
.forEach(length -> connection.send(newStringWritablePacket(StringUtils.generate(length)))))
.flatMapMany(Connection::receivedEvents)
.subscribe(event -> System.out.println("Received from server: " + event.packet.getData()));

Fake SMTP Server (for testing)

Use a containerized fake SMTP server for integration tests:

varcontainer = newFakeSMTPTestContainer()
.withSmtpPassword("pwd")
.withSmtpUser("test_user");
container.start();
container.waitForReadyState();
// sending emails to this server// checking APIvarcount = container.getEmailCountFrom("from@test.com");
// clearing APIcontainer.deleteEmails();

Collections API

Extended collections with dictionaries (maps) and arrays optimized for specific use cases:

// Mutable dictionary (map) with object keysvardictionary = DictionaryFactory.mutableRefToRefDictionary();
dictionary.put("key1", "value1");
dictionary.put("key2", "value2");
varvalue = dictionary.get("key1");
// Thread-safe dictionary with stamped lockvarlockableDictionary = DictionaryFactory.stampedLockBasedRefToRefDictionary();
varstamp = lockableDictionary.writeLock();
try {
lockableDictionary.put("key", "value");
} finally {
lockableDictionary.writeUnlock(stamp);
}
// Primitive key dictionaries (no boxing overhead)varintToRefDictionary = DictionaryFactory.mutableIntToRefDictionary();
intToRefDictionary.put(1, "value1");
varlongToRefDictionary = DictionaryFactory.mutableLongToRefDictionary();
longToRefDictionary.put(100L, "value2");
// Mutable arrays with type safetyvararray = ArrayFactory.mutableArray(String.class);
array.add("element1");
array.add("element2");
// Thread-safe copy-on-write arrayvarcowArray = ArrayFactory.copyOnModifyArray(String.class);
// Stamped lock based thread-safe arrayvarlockableArray = ArrayFactory.stampedLockBasedArray(String.class);

Object Pooling

Reusable object pools for reducing GC pressure:

// Create a pool for reusable objectsvarpool = PoolFactory.newReusablePool(MyReusableObject.class);
// Take an object from pool (or create new if empty)varobj = pool.take();
// Use the object...// Return to pool for reusepool.put(obj);
// Thread-safe poolvarlockablePool = PoolFactory.newLockBasePool(MyObject.class);

Plugin System

Dynamic plugin loading and management:

varpluginSystem = PluginSystemFactory.newBasePluginSystem();
pluginSystem.configureAppVersion(newVersion("1.0.0"));
pluginSystem.configureEmbeddedPluginPath(Paths.get("plugins/"));
// Async plugin loadingpluginSystem
.preLoad(ForkJoinPool.commonPool())
.thenCompose(system -> system.initialize(ForkJoinPool.commonPool()))
.toCompletableFuture()
.join();
// Access extension pointsvarextensionPoint = pluginSystem
.extensionPointManager()
.getExtensionPoint(MyExtension.class);

Building

# Full build with tests
./gradlew clean build
# Build specific module
./gradlew :rlib-common:build
# Run tests only
./gradlew test# Skip tests
./gradlew clean build -x test

License

Please see the file called LICENSE.