javaservletslog4j

How to use slf4j-api > 2 in jersey servlet container


I have a Jersey servlet project, where I organize the depencies with maven. It runs in Tomcat.

Update of slf4j-api

Now I am trying to use <artifactId>slf4j-api</artifactId><version>2.0.17</version>.

But I am not able to figure the right implementation yet. The documentation states:

Most notably, slf4j-api now relies on the ServiceLoader mechanism to find its logging backend. SLF4J 1.7.x and earlier versions relied on the static binder mechanism which is no longer honored by slf4j-api version 2.0.x. More specifically, during its initialization, the LoggerFactory class will no longer search for the org.slf4j.impl.StaticLoggerBinder class on the class path.

Instead of "bindings" now org.slf4j.LoggerFactory searches for "providers". These ship for example with slf4j-nop-2.0.x.jar, slf4j-simple-2.0.x.jar or slf4j-jdk14-2.0.x.jar.

If I am right, I need the following dependencies (works with slf4j-api v1.7):

Provider

When I use <artifactId>log4j-slf4j2-impl</artifactId><version>2.25.1</version> I am getting the following information:

SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation

So no logging happens.

When I use <artifactId>log4j-slf4j-impl</artifactId><version>2.25.1</version> I am getting this:

SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J(W): Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.
SLF4J(W): Ignoring binding found at [jar:file:/path/to/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/quality-check/WEB-INF/lib/log4j-slf4j-impl-2.25.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]

I especially don't get the line Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.

Usage

I am using a logger factory in my classes, where I need to log something. Like org.slf4j.LoggerFactory.getLogger(MyClass.class);

Solution?

Did anybody see a similar problem and how can I solve this? I am going back to slf4j-api 1.7 for now, but I am pretty sure that there is a way for using the fresher version.


Solution

  • Create a Jersey 3.1.11 web application

    https://eclipse-ee4j.github.io/jersey/download.html

    If you want to create a Servlet container deployable Jersey 3.1.11 web application instead, use

    Linux:

    mvn archetype:generate \
      -DarchetypeGroupId=org.glassfish.jersey.archetypes \
      -DarchetypeArtifactId=jersey-quickstart-webapp \
      -DarchetypeVersion=3.1.11
    

    Windows:

    mvn archetype:generate ^
      -DarchetypeGroupId=org.glassfish.jersey.archetypes ^
      -DarchetypeArtifactId=jersey-quickstart-webapp ^
      -DarchetypeVersion=3.1.11
    

    input groupId and artifactId:

    Confirm properties configuration:
    groupId: com.example
    artifactId: hello-jersey
    version: 1.0-SNAPSHOT
    package: com.example
    

    Output

    hello-jersey
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── example
        │   │           └── MyResource.java
        │   └── webapp
        │       ├── index.jsp
        │       └── WEB-INF
        │           └── web.xml
        └── test
            └── java
                └── com
                    └── example
    

    Modify Example

    hello-jersey
    ├── pom.xml
    └── src
        └── main
            ├── java
            │   └── com
            │       └── example
            │           └── MyResource.java
            ├── resources
            │   └── log4j2.xml
            └── webapp
                ├── index.jsp
                └── WEB-INF
                    └── web.xml
    

    pom.xml

    <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://maven.apache.org/POM/4.0.0"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                                 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example</groupId>
        <artifactId>hello-jersey</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>hello-jersey</name>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <jakarta.servlet.version>6.0.0</jakarta.servlet.version>
            <slf4j.version>2.0.13</slf4j.version>
            <log4j2.version>2.23.1</log4j2.version>
            <jersey.version>3.1.11</jersey.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.glassfish.jersey</groupId>
                    <artifactId>jersey-bom</artifactId>
                    <version>${jersey.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey.containers</groupId>
                <artifactId>jersey-container-servlet-core</artifactId>
                <!-- use the following artifactId if you don't need servlet 2.x compatibility -->
                <!-- artifactId>jersey-container-servlet</artifactId -->
            </dependency>
            <dependency>
                <groupId>org.glassfish.jersey.inject</groupId>
                <artifactId>jersey-hk2</artifactId>
            </dependency>
            <!-- uncomment this to get JSON support
            <dependency>
                <groupId>org.glassfish.jersey.media</groupId>
                <artifactId>jersey-media-json-binding</artifactId>
            </dependency>
            -->
    
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-slf4j2-impl</artifactId>
                <version>${log4j2.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>${log4j2.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
                <version>${log4j2.version}</version>
            </dependency>
        </dependencies>
    
        <build>
            <finalName>hello-jersey</finalName>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.3.2</version>
                    <configuration>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    
    

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://jakarta.ee/xml/ns/jakartaee" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" id="WebApp_ID" version="6.0">
      <display-name>hello-jersey</display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
        <servlet>
            <servlet-name>Jersey Web Application</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>com.example</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Jersey Web Application</servlet-name>
            <url-pattern>/webapi/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    log4j2.xml

    ADD >>>> at PatternLayout pattern=

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <Appenders>
            <Console name="ConsoleAppender" target="SYSTEM_OUT">
                <PatternLayout pattern=">>>> [%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %c{1} - %msg%n"/>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="info">
                <AppenderRef ref="ConsoleAppender"/>
            </Root>
        </Loggers>
    </Configuration>
    

    MyResource.java

    ADD:

    package com.example;
    
    import jakarta.ws.rs.GET;
    import jakarta.ws.rs.Path;
    import jakarta.ws.rs.Produces;
    import jakarta.ws.rs.core.MediaType;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * Root resource (exposed at "myresource" path)
     */
    @Path("myresource")
    public class MyResource {
        private static final Logger logger = LoggerFactory.getLogger(MyResource.class);
    
        /**
         * Method handling HTTP GET requests. The returned object will be sent
         * to the client as "text/plain" media type.
         *
         * @return String that will be returned as a text/plain response.
         */
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String getIt() {
            logger.info("Got it!");
            return "Got it!";
        }
    }
    

    Build

    in hello-jersey directory:

    mvn clean package
    

    install into Tomcat

    cd tomcat/bin
    
    ./startup.sh
    

    Test

    Firefox open :

    then click link : Jersey resource

    get return: Got it!

    Open log

    tomcat/logs/catalina.out

    >>>> [2025-09-01 20:21:04] [INFO ] MyResource - Got it!
    >>>> [2025-09-01 20:35:53] [INFO ] MyResource - Got it!
    

    My Process

    Problem breakdown, your requirements:

    Forget about Jersey for now.

    Reorganized requirements:

    Create the first POC WAR

    So the first POC WAR requirement can be organized.

    Then you can create a hello.war using (1) SLF4J 2 and (2) LOG4J2, deployed to the Tomcat Server. It has nothing to do with Jersey.

    After you successfully test it, you will know which (1) SLF4J 2 and (2) LOG4J2 dependency jars and corresponding versions are needed.

    Create the second POC WAR(this answer)

    After that, the next step (the second POC WAR) will be to build a Jersey WAR example based on the official documentation.

    This example will simply integrate the SLF4J 2 and LOG4J2 dependencies and versions you discovered from the first POC WEB.