5
votes

When I test my application with JUnit, it is printing the log as specified by layout pattern in log4j2.xml, but when I deploy my application in WildFly 9, I am no more getting the same format. Even the log level in Log4j2 is also not reflecting while deployed in server.

JUnit log example:

2016-02-15 11:14:16,314 DEBUG [main] b.t.r.c.XAPool - a connection's state changed to IN_POOL, notifying a thread eventually waiting for a connection

Server log example:

11:11:33,796 INFO [org.quartz.core.QuartzScheduler] (ServerService Thread Pool -- 89) Scheduler quartzScheduler_$_anindya-ubuntu1455514892022 started.

Log4j2.xml:

<Configuration status="WARN" name="myapp" monitorInterval="5">
    <Appenders>
        <RollingFile name="RollingFile" fileName="${myapp.log-dir}/myapp.log"
                     filePattern="${myapp.log-dir}/$${date:yyyy-MM}/myapp-%d{MM-dd-yyyy}-%i.log">
            <PatternLayout>
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <OnStartupTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="25 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="100">
                <Delete basePath="${myapp.log-dir}" maxDepth="2">
                    <IfFileName glob="*/myapp-*.log">
                        <IfLastModified age="7d">
                            <IfAny>
                                <IfAccumulatedFileSize exceeds="1 GB" />
                                <IfAccumulatedFileCount exceeds="1" />
                            </IfAny>
                        </IfLastModified>
                    </IfFileName>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Logger name="com.company.myapp" level="trace" additivity="false">
            <AppenderRef ref="RollingFile"/>
        </Logger>
        <Root level="info">
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>
</Configuration>

While starting the server, I am providing below starup properties as JAVA_OPTS:

export JAVA_OPTS="$JAVA_OPTS -Dspring.profiles.active='qa' -Dlog4j.configurationFile=/home/anindya/1.0/log4j2.xml -myapp.log-dir=/home/anindya/log -Dorg.jboss.logging.provider=log4j"

I have no specific setup in web.xml as it is Servlet 3.1 container. But I have a jboss-deployment-structure.xml in my WEB-INF as below:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
        <!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
        <exclusions>
            <module name="org.apache.logging.log4j" />
        </exclusions>
    </deployment> 
</jboss-deployment-structure>

And finally, here are my classpath dependencies (only the relevant parts are mentioned here):

  • hibernate-5.0.7.Final dependencies
  • jbpm-6.3.0.Final dependencies
  • spring-4.2.4.RELEASE dependencies
  • commons-logging-1.2.jar
  • log4j-1.2-api-2.5.jar
  • log4j-api-2.5.jar
  • log4j-core-2.5.jar
  • log4j-jcl-2.5.jar
  • log4j-slf4j-impl-2.5.jar
  • log4j-web-2.5.jar
  • jboss-logging-3.3.0.Final.jar

With all of the above setup, I am still not able to configure Log4j2 in WildFly environment according to my log4j2.xml. Can someone please help?

NOTE: I am running WildFly in standalone mode and I would like to avoid using jboss-cli.

4
does wildfly work properly with log4j2? i have some difficulty: it creates the log file but it s emptyAlex

4 Answers

6
votes

I managed to get it working by using the below jboss-deployment-structure.xml.

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
        <exclusions>
            <module name="org.apache.logging.log4j" />
        </exclusions>
        <exclude-subsystems>
            <subsystem name="logging"/>
        </exclude-subsystems>
    </deployment>
</jboss-deployment-structure>

All I had to do is to exclude the logging subsystem.

4
votes

Late to the game but I needed support for log4j2 in Wildfly and thought I would share some details for anyone else facing this. This solution will let you configure logging through standalone.xml, that is no log4j2.xml will be used/picked up. The solution I chose is to bridge log4j2 to slf4j. Wildfly supports slf4j out-of-the-box. For the advanced users the solution in one sentence is 'Create a Wildfly module and use it', for others like me the solution follows a bit more detailed below...

First create a wildfly module, I will not give all the details how this is done, but my module.xml ended up looking like this

<module xmlns="urn:jboss:module:1.1" name="org.apache.logging.log4j2">
<resources>
    <resource-root path="log4j-api-2.11.1.jar"/>
    <resource-root path="log4j-to-slf4j-2.11.1.jar"/>
</resources>

<dependencies>
    <module name="org.slf4j" />
</dependencies>
</module>

(Basically make sure this xml is in your module path, typically you would add it at $JBOSS_MODULEPATH/org/apache/logging/log4j2/main/module.xml, and add the referenced jar-files in the same directly as well)

Next step is to add a dependency to this module from my application. This is accomplished using a jboss-deployment-structure.xml. If you are not familiar with this file please look it up. Add a line like this

<module name="org.apache.logging.log4j2" export="true" />

You might also need to exclude log4j-api-2.11.1.jar from your application deployment, I am not 100% sure it is needed but I always do when I create a module.

After this you should be able to see log4j2 messages in your server.log

I hope this can help someone out there!

1
votes

There is no module org.apache.logging.log4j. The module name you should be using is org.apache.log4j.

I'm not sure why you don't want to use CLI, but you could also set the add-logging-api-dependencies to false.

/subsystem=logging:write-attribute(name=add-logging-api-dependencies, value=false)
0
votes

I want to offer to have a look at the problem from another side.

You can in your code, use log4j2 interfaces, as a logging bridge. For instance you can use MDC, Suppliers, ClosableThreadContext. The features which are not availble in slf4j/logback at the moment:

import org.apache.logging.log4j.CloseableThreadContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


  private static final Logger logger = LogManager.getLogger(SomeClass.class.getName());

  public void doLog() {
    try (final CloseableThreadContext.Instance ctc =
           CloseableThreadContext.put("user", UUID.randomUUID().toString())) {
      String note = "(originally, log4j2 war)";
      logger.info(() -> "This is an info message, via supplier, " + note);      // == INFO
      logger.error("This is an error message, {}", note);   // == ERROR
      logger.warn("This is a warning message, {}", note); // == WARNING
      logger.debug("Here is a debug message, {}", note);      // == DEBUG
      logger.info(logger.getClass().getName());
    }
  }

But you add a dependency to delegate all log4j2 calls to slf4j:

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-to-slf4j</artifactId>
  <version>2.14.0</version>
</dependency>

You do not need any other hacks. It works fine (checked on Wildfly 10).

The main advantages:

  1. you have modern API for logging and some great features. Slf4j is going to support those features, but they are not yet included into the last final version.
  2. which is more important, when you work with WildFly, you can adopt logging configuration via WildFly at runtime with CLI. It is very important possibility for production. Delivering a config file, like Log4j2.xml is a bad alternative. You need literally to change the content of this file. Most oftern, it means to rebuild the project, cause the logging config file is usually part of the resources. And it also means you need to redeploy the application.

With WildFly CLI I can temporary enable DEBUG mode for a certain package.