TheDentist
TheDentist

Reputation: 103

Payara Micro: How to log with slf4j (or log4j2)?

I'm using Payara Micro (bundled ueberjar) for a recent project, but I have difficulties with logging. Seems like Payara Micro uses JUL by default, which does not suit my needs. I'd like to use Log4J 2 instead, preferably through slf4j. Unfortunately, I couldn't find much information. To start with, I'd like refer to the following link...

https://blog.payara.fish/the-basics-of-logging-in-payara-server

... which says: "Payara Micro can also be adjusted to use other logging frameworks like Logback and Log4J2." Sounds great, but the only source that deals with that matter seems to be the following example project: https://github.com/hei1233212000/payara-micro-log4j2. Yet it is from 2017 and seems to be outdated as it doesn't use the payara micro maven plugin. Still, I guess the point is:

I tried my luck adding the jars as customJars via the payara micro maven plugin, which indeed resulted in a bundled jar containing those libs under MICRO-INF/lib. From what I read, the jars should also be on classpath, though they don't appear in the Manifest file. Also, I added the logging.properties tih the following simple content under src/main/resources:

handlers=org.slf4j.bridge.SLF4JBridgeHandler

Now, if I run the bundled jar, it says Can't load log handler "org.slf4j.bridge.SLF4JBridgeHandler", followed by an ugly stacktrace. Yet the class org.slf4j.bridge.SLF4JBridgeHandler is in one of the jars I added. I already experimented with the groovy script from the example I linked above to edit the Manifest file, but I couldn't figure out how to set it up properly. I mean, the script worked and I get an edited Manifest file, but it is not added to the bundled jar - I guess my timing is bad. Not to mention that this is kind of hackish as the author of the example said.

Interestingly, if I don't add the logging.properties to the jar, thus leaving Payara Micros logging setup untouched, I can reroute logging output from 3rd party libraries (such as hibernate) coming with Payara Micro while its own logs are logged to the console. Yet that's not my goal as I am more interested in the latter logs.

So, I'd be thankful if someone could give me a hand. Thanks for reading. For completeness, here is my pom.xml (I am using the package profile, the other is for cucumber tests only):

<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">
<modelVersion>4.0.0</modelVersion>
<groupId>de.kepes.payara-micro</groupId>
<artifactId>payara-micro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <failOnMissingWebXml>false</failOnMissingWebXml>

    <skipTests>true</skipTests>

    <payara-micro.version>5.194</payara-micro.version>
    <payara-micro.plugin.version>1.0.6</payara-micro.plugin.version>
    <jakarta.version>8.0.0</jakarta.version>
    <maven-failsafe.plugin.version>2.22.2</maven-failsafe.plugin.version>
    <cucumber.version>5.4.0</cucumber.version>
    <websocket.version>1.4.0</websocket.version>

    <log4j.version>2.13.0</log4j.version>
    <slf4j.version>1.7.30</slf4j.version>
</properties>

<profiles>
    <profile>
        <id>package</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>fish.payara.maven.plugins</groupId>
                    <artifactId>payara-micro-maven-plugin</artifactId>
                    <version>${payara-micro.plugin.version}</version>
                    <executions>
                        <execution>
                            <id>bundle</id>
                            <phase>package</phase>
                            <goals>
                                <goal>bundle</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>start</id>
                            <goals>
                                <goal>start</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <useUberJar>true</useUberJar>
                        <deployWar>true</deployWar>
                        <payaraVersion>${payara-micro.version}</payaraVersion>
                        <customJars>
                            <customJar>
                                <groupId>org.slf4j</groupId>
                                <artifactId>jul-to-slf4j</artifactId>
                                <version>${slf4j.version}</version>
                            </customJar>
                            <customJar>
                                <groupId>org.slf4j</groupId>
                                <artifactId>slf4j-api</artifactId>
                                <version>${slf4j.version}</version>
                            </customJar>
                            <customJar>
                                <groupId>org.apache.logging.log4j</groupId>
                                <artifactId>log4j-slf4j-impl</artifactId>
                                <version>${log4j.version}</version>
                            </customJar>
                            <customJar>
                                <groupId>org.apache.logging.log4j</groupId>
                                <artifactId>log4j-api</artifactId>
                                <version>${log4j.version}</version>
                            </customJar>
                            <customJar>
                                <groupId>org.apache.logging.log4j</groupId>
                                <artifactId>log4j-core</artifactId>
                                <version>${log4j.version}</version>
                            </customJar>
                        </customJars>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>test</id>

        <properties>
            <skipTests>false</skipTests>
        </properties>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>${maven-failsafe.plugin.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>integration-test</goal>
                                <goal>verify</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <skip>false</skip>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>fish.payara.maven.plugins</groupId>
                    <artifactId>payara-micro-maven-plugin</artifactId>
                    <version>${payara-micro.plugin.version}</version>
                    <executions>
                        <execution>
                            <id>pre-integration-payara</id>
                            <phase>pre-integration-test</phase>
                            <goals>
                                <goal>start</goal>
                            </goals>
                            <configuration>
                                <daemon>true</daemon>
                            </configuration>
                        </execution>
                        <execution>
                            <id>post-integration-payara</id>
                            <phase>post-integration-test</phase>
                            <goals>
                                <goal>stop</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <payaraVersion>${payara-micro.version}</payaraVersion>
                        <deployWar>true</deployWar>
                        <contextRoot>/</contextRoot>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

<dependencies>
    <dependency>
        <groupId>jakarta.platform</groupId>
        <artifactId>jakarta.jakartaee-api</artifactId>
        <version>${jakarta.version}</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.java-websocket</groupId>
        <artifactId>Java-WebSocket</artifactId>
        <version>${websocket.version}</version>
        <scope>test</scope>
    </dependency>

</dependencies>

Upvotes: 1

Views: 3213

Answers (1)

Ondro Mih&#225;lyi
Ondro Mih&#225;lyi

Reputation: 7760

this isn't possible just by adding logging libraries as custom JARs as logging is initialized before those libraries are loaded.

However, there's a solution how to use alternative logging libraries. You need to run Payara Micro in a different way. If you put it on the classpath and run the Payara Micro main class directly, you can put custom logging libraries on the classpath too and they will be picked up at boot time, before logging is initialized. If you have payara-micro.jar, slf4j.jar, log4j.jar and jul-to-slf4j.jar in the current directory, you can launch Payara Micro like this:

java -cp ./payara-micro.jar:slf4j.jar:log4j2.jar:jul-to-slf4j.jar fish.payara.micro.PayaraMicro some.war

Alternatively, you can move those logging JARs to a subdirectory lib and shorten the command line:

java -cp "./payara-micro.jar:lib/*" fish.payara.micro.PayaraMicro some.war

You can pass the same arguments to the PayaraMicro class which are accepted by the Payara Micro JAR.

Upvotes: 2

Related Questions