= Java RELP Server Library (rlp_03)
rlp_03 implements RELP server in Java
== License AGPLv3 with link:https://github.com/teragrep/rlp_03/blob/master/LICENSE#L665-L670[additional permissions] granted in the license.
== Features Current
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
NOTE: See https://github.com/teragrep/rlp_01[rlp_01] for relp relpClient
NOTE: See https://github.com/teragrep/rlo_06[rlo_06] for syslog decoding
=== Examples
Dependencies for examples
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
Server with shared handler for all connections. See ExampleRelpClient.java for relpClient.
package com.teragrep.rlp_03.readme;
import com.teragrep.net_01.eventloop.EventLoop; import com.teragrep.net_01.eventloop.EventLoopFactory; import com.teragrep.rlp_03.frame.delegate.DefaultFrameDelegate; import com.teragrep.rlp_03.frame.delegate.FrameContext; import com.teragrep.rlp_03.frame.delegate.FrameDelegate; import com.teragrep.net_01.server.ServerFactory; import com.teragrep.net_01.channel.socket.PlainFactory; import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.UncheckedIOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Consumer; import java.util.function.Supplier;
/**
For use cases in the README.adoc */ public class ReadmeTest {
@Test public void testServerSetup() { int listenPort = 10601; int threads = 1; // processing threads shared across the connections ExecutorService executorService = Executors.newFixedThreadPool(threads);
/*
* System.out.println is used to print the frame payload
*/
Consumer<FrameContext> syslogConsumer = new Consumer<FrameContext>() {
// NOTE: synchronized because frameDelegateSupplier returns this instance for all the parallel connections
@Override
public synchronized void accept(FrameContext frameContext) {
System.out.println(frameContext.relpFrame().payload().toString());
}
};
/*
* New instance of the frameDelegate is provided for every connection
*/
Supplier<FrameDelegate> frameDelegateSupplier = new Supplier<FrameDelegate>() {
@Override
public FrameDelegate get() {
System.out.println("Providing frameDelegate for a connection");
return new DefaultFrameDelegate(syslogConsumer);
}
};
/*
* EventLoop is used to notice any events from the connections
*/
EventLoopFactory eventLoopFactory = new EventLoopFactory();
EventLoop eventLoop;
try {
eventLoop = eventLoopFactory.create();
}
catch (IOException e) {
throw new RuntimeException(e);
}
Thread eventLoopThread = new Thread(eventLoop);
/*
* eventLoopThread must run, otherwise nothing will be processed
*/
eventLoopThread.start();
/*
* ServerFactory is used to create server instances
*/
ServerFactory serverFactory = new ServerFactory(
eventLoop,
executorService,
new PlainFactory(),
new FrameDelegationClockFactory(frameDelegateSupplier)
);
try {
serverFactory.create(listenPort);
System.out.println("server started at port <" + listenPort + ">");
}
catch (IOException ioException) {
throw new UncheckedIOException(ioException);
}
/*
* Send Hello, World! via rlp_01
*/
new ExampleRelpClient(listenPort).send("Hello, World!");
new ExampleRelpClient(listenPort).send("Hello, World again!");
/*
* Stop eventLoop
*/
eventLoop.stop();
/*
* Wait for stop to complete
*/
try {
eventLoopThread.join();
}
catch (InterruptedException interruptedException) {
throw new RuntimeException(interruptedException);
}
System.out.println("server stopped at port <" + listenPort + ">");
executorService.shutdown();
If a separate handler is required for each connection which doesn’t need to be a thread-safe, create a new FrameDelegate in the Supplier
Supplier<FrameDelegate> frameDelegateSupplier = () -> {
System.out.println("Providing frameDelegate for a connection");
return new DefaultFrameDelegate(frameContext -> System.out.println(frameContext.relpFrame().payload().toString()));
};
If a deferred handler is required for command processing, pass custom RelpEvent implementation to DefaultFrameDelegate via the Map<String, RelpEvent> constructor. See ReadmeDeferredTest.java for an example.
== Contributing
// Change the repository name in the issues link to match with your project's name
You can involve yourself with our project by https://github.com/teragrep/rlp_03/issues/new/choose[opening an issue] or submitting a pull request.
Contribution requirements:
. All changes must be accompanied by a new or changed test. If you think testing is not required in your pull request, include a sufficient explanation as why you think so. . Security checks must pass . Pull requests must align with the principles and http://www.extremeprogramming.org/values.html[values] of extreme programming. . Pull requests must follow the principles of Object Thinking and Elegant Objects (EO).
Read more in our https://github.com/teragrep/teragrep/blob/main/contributing.adoc[Contributing Guideline].
=== Contributor License Agreement
Contributors must sign https://github.com/teragrep/teragrep/blob/main/cla.adoc[Teragrep Contributor License Agreement] before a pull request is accepted to organization's repositories.
You need to submit the CLA only once. After submitting the CLA you can contribute to all Teragrep's repositories.