I'm trying to set up a log4j2 SecureTcpSocketServer that will receive logs from a remote application (logging with log4j2). I've already prototyped this using the TcpSocketServer, which can be run from the command line by providing a port number and configuration file. The SecureTcpSocketServer however requires additional information to construct, such as a 'LogEventBridge' object and a 'SslConfiguration' object. I don't see how I could provide these objects to the command line so I decided to write a Java program to initialize and run the server. Here is my code:
public class log4j2SocketServer {
public static void main(String[] args) {
KeyStoreConfiguration keyStoreConf = null;
TrustStoreConfiguration trustStoreConf = null;
SecureTcpSocketServer<ObjectInputStream> myServer = null;
try {
keyStoreConf = new KeyStoreConfiguration("keystore.jks", "password", null, null);
} catch (StoreConfigurationException e) {
e.printStackTrace();
}
try {
trustStoreConf = new TrustStoreConfiguration("keystore.jks", "password", null, null);
} catch (StoreConfigurationException e) {
e.printStackTrace();
}
SslConfiguration sslConf = SslConfiguration.createSSLConfiguration("SSL", keyStoreConf, trustStoreConf);
try {
myServer = new SecureTcpSocketServer<ObjectInputStream>(5514,new ObjectInputStreamLogEventBridge(),sslConf);
} catch (IOException e) {
e.printStackTrace();
}
while(true){}
}
}
Using this code, the server seems to start up and listen on port 5514 (I used netstat to verify). On the client side, my log4j2 application seems to connect, but I don't see any of the logs coming through. Here is my client code:
Xml Configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="remoteLogging" packages="">
<Appenders>
<Socket name="socket" host="xx.xx.xx.xx" port="5514">
<SerializedLayout />
<SSL>
<KeyStore location="keystore.jks" password="password"/>
<TrustStore location="keystore.jks" password="password"/>
</SSL>
</Socket>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="socket"/>
</Root>
</Loggers>
</Configuration>
Here is my Java code:
public class remoteLogging {
static final Logger log = LogManager.getLogger(remoteLogging.class.getName());
public static void main(String[] args) {
log.debug("Hello this is a debug message");
log.info("Hello this is an info message");
log.warn("Hello this is a warn message");
log.error("Hello this is a error message");
}
}
My primary concern is the way I wrote my server code. When I started writing the code, I figured all I'd need to do is instantiate a SecureTcpSocketServer. I did this, and then (obviously) the program ran, and then...ended, and garbage collected my server. So then I decided to put a infinite loop in right afterwards, to keep the server alive. I seriously doubt this is the proper way to do this, but I'm fairly new to coding and I'm not sure what the best approach is. My question is, is this implementation okay? I mean there's obviously something going wrong, since I'm not receiving logs...Is this loop causing problems? Or is there something else wrong that I haven't considered?
One more thing: I would expect my client application to run, connect to the server and send its logs, and then terminate. Right now, it seems to connect, but no logs seem to be sent, and then it just hangs until I manually terminate it. This makes me think the server-side infinite loop is interfering somehow?
Looking at the source for
SecureTcpSocketServer
and its superclassTcpSocketServer
, I think just constructing an instance is not enough to start the server. You need to call itsrun()
method to get it to start accepting connections.In your
log4j2SocketServer
class, replacewhile(true){}
withmyServer.run();
. This method will block untilactive
is set tofalse
or until the serverSocket is closed.