1

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:

  • add the necessary logging jars to the bundle
  • adjust Manifest file by adding the jars to the classpath
  • use the SLF4JBridgeHandler for Payara Micro

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>

TheDentist
  • 103
  • 1
  • 7
  • It seems that the logging system is initialized before the JARs in the lib directory are loaded. I would create an issue on Payara github page. – OndroMih Mar 02 '20 at 08:40
  • Thank you for your reply, issue has been opened under https://github.com/payara/Payara/issues/4546. – TheDentist Mar 03 '20 at 16:58
  • I found a way how to run Payara with alternative logging libraries, see my answer here. – OndroMih Mar 05 '20 at 09:16

1 Answers1

2

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.

OndroMih
  • 7,280
  • 1
  • 26
  • 44
  • For users that don't use bundled jars, this would be the solution. However, as I am sticked to that approach, it doesn't solve the issue for my specific case. For those that have the same problem as me, please also check the issue I have opened on github (linked in my comment on my initial post). – TheDentist Mar 09 '20 at 07:50
  • For a bundled jar, you can shade the logging JARs into the bundled JAR so that the classes from the JAR are on the system classpath – OndroMih Mar 10 '20 at 21:13