javaspringspring-bootloggingfilenet-content-engine

ClassNotFoundException: org.apache.log4j.Priority when using Filenet APIs


I am using Spring Boot 2.7.2 to create a rest API that communicate with Filenet Content Engine using Filenet APIs and my pom file as follows :

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.test</groupId>
    <artifactId>storage</artifactId>
    <version>0.0.1</version>
    <name>storage</name>
    <description>Storage API</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.9</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Filenet Jars -->

        <dependency>
            <groupId>Jace</groupId>
            <artifactId>Jace</artifactId>
            <version>5.2.1</version>
        </dependency>

        <dependency>
            <groupId>stax-api</groupId>
            <artifactId>stax-api</artifactId>
            <version>5.2.1</version>
        </dependency>

        <dependency>
            <groupId>xlxpScanner</groupId>
            <artifactId>xlxpScanner</artifactId>
            <version>5.2.1</version>
        </dependency>

        <dependency>
            <groupId>xlxpScannerUtils</groupId>
            <artifactId>xlxpScannerUtils</artifactId>
            <version>5.2.1</version>
        </dependency>

        <!-- End Of Filenet Jars -->

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!--
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        -->

    </dependencies>

    <build>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>

        <repository>
            <id>MCI-maven</id>
            <url>http://myhost/repository/maven-public/</url>
        </repository>

    </repositories>

</project>

The project compiles and starts up fine, but when trying to execute any filenet API I get a log4j error:

ClassNotFoundException: org.apache.log4j.Priority

That is because filenet APIs is using log4j1 classes.

The class is : com.filenet.apiimpl.util.BaseLogger.

The class imports are:

import com.filenet.api.exception.EngineRuntimeException;
import com.filenet.api.exception.ErrorLoggingLevel;
import com.filenet.api.util.UserContext;
import com.filenet.apiimpl.exception.ExceptionContext;
import java.util.Enumeration;
import org.apache.log4j.Category;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

The current solution is to add log4j 1.2.17 in pom file

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

When adding this the runtime exception disappears and everything works fine. But I only get the following warning on first time invoking filenet API:

log4j:WARN No appenders could be found for logger (filenet_error.api.com.filenet.apiimpl.util.ConfigValueLookup).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[Perf Log] perflog.dir=null not found, auditor disabled 
[Perf Log] No interval found. Auditor disabled.

Is there any better solution to this scenario rather than adding old log4j dependency ?


Solution

  • According to your actual pom.xml file, following the transitive dependencies spring-boot-starter-web and spring-boot-starter, you will end using spring-boot-starter-logging and its different dependent libraries, mainly based on logback and slf4j.

    As you indicated, the Filenet APIs use Log4j 1.x.

    The support for that version of Log4j was removed with the release of Spring Boot 2.x.

    As a consequence, by default, the library will not give you support for that logging library.

    That is the reason why you are facing the ClassNotFoundException: org.apache.log4j.Priority error.

    In my opinion the solution you applied based on the inclusion of the log4j dependency itself is not a bad solution. A word of caution though:

    As an alternative, you could use the Log4j 1.x bridge provided by Slf4j:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
    </dependency>
    

    You can use the version 1.7.36 although it is managed by Spring Boot Starter Parent as well, so you don't need to provide a specific version for it.

    Maybe there can be some caveats, some functionally used by the Filenet logger not implemented, but at first glance it seems to provide all the required stuff used by com.filenet.apiimpl.util.BaseLogger.

    If that's the case, it will give you a better solution than using the log4j library, for the reasons explained, especially because it will allow you to integrate the Filenet loggers with your existing Spring Boot logging configuration and infrastructure.