1

I found many link that helped me building the logger. Some here in SO and others in other pages.

This answer here: https://stackoverflow.com/questions/7624895/how-to-use-log4j-with-multiple-classes#= is the best that I have found. It is already some years old thought and some things now are different.

My goal is to have one single logger shared among all of the java classes that print messages to the log, both console and file.

I am using LOG4J2: http://logging.apache.org/log4j/2.x/manual/configuration.html

main():

import org.apache.logging.log4j.Logger;

public class App {
    private static final Logger LOGGER = Logger.getLogger("GLOBAL");
    public static void main(){
        ...calling other classes
  }
}

anyOtherClass:

import org.apache.logging.log4j.Logger;
public class secondClass {
    private final Logger LOGGER = Logger.getLogger("GLOBAL");
    public void writeLog(){
      LOGGER.log(Level.INFO, "A simple string");
  }
}

log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <Properties>
        <Property name="basePath">/var/log</Property>
    </Properties>

    <Appenders>
        <RollingFile name="fileLogger" fileName="${basePath}/myApp.log" filePattern="${basePath}/myApp-%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>

       <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="java.util.logging.Logger" level="ALL" additivity="true">
            <appender-ref ref="fileLogger" level="ALL" />
        </Logger>
        <Root level="ALL" additivity="false">
            <appender-ref ref="console" />
        </Root>
    </Loggers>
</Configuration>

I (more or less) know that I should use LogManager, truth is I should call it as:

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

or, in the main(), probably like this:

private static Logger LOGGER = null;

@BeforeClass
public static void setLogger() {
    System.setProperty("log4j.configurationFile","log4j.xml");
    LOGGER = LogManager.getLogger();
}

Because, I believe, using LogManager I can point the Log to the xml file for its settings. But when I build it and run it, the CLI rage quits at the first ever LOG, reporting: Exception in thread "main" java.lang.NullPointerException at myapp.modules.Database.<init>(Database.java:67)

Expected Result: All I want to do is being able to have the log on all of my classes and that this is written to a file. I just can't get this working. And when I do not use LogManager, I only see the logs on console but no file is created. I'm using both Windows and Linux (that's why /var/log/ but I change it to C:\ too).

Other website I used: https://howtodoinjava.com/log4j2/configure-log4j2-for-junit/

Log4J loggers for different classes <-- did not help me

..And many other search results are more than 6 years old.

POM.xml:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.10.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.10.0</version>
</dependency>
aPugLife
  • 989
  • 2
  • 14
  • 25
  • When using Log4j2, most of your imports for logging should reference classes in this package `org.apache.logging.log4j`. I think the problem lies there. – neomega Dec 05 '17 at 14:49
  • @neomega sorry I forgot to copy it, I'm using it already. Netbeans warns me when I miss something. I'm using `import java.util.logging.Logger;` and the POM is edited to to use log4j-api and log4j-core -> 2.10.0 – aPugLife Dec 05 '17 at 14:52
  • @neomega I understood it now what you meant! I'm checking if my mistake is here. Thanks! – aPugLife Dec 05 '17 at 15:01

1 Answers1

3

You're wrong on several levels: you're mixing JDK's logger with Log4j2's Logger, you're not logging to several appenders, etc.

Here's what you should do:

/pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>log4j2test</artifactId>
    <version>0.1</version>
    <packaging>jar</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>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.10.0</version>
        </dependency>
    </dependencies>
</project>

This is basically the only place where you have no error.

/src/main/java/so47656300/App.java

package so47656300;

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

public class App {

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

  public static void main(String[] args) {
    logger.info("App.main - starting");
    new SecondClass();
    logger.info("App.main - ending");
  }
}

Here, your error was to use java.util.logger.Logger instead of org.apache.logging.log4j.Logger.

/src/main/java/so47656300/SecondClass.java

package so47656300;

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

public class SecondClass {

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

  public SecondClass() {
    logger.info("SecondClass - starting");
    logger.info("SecondClass - ending");
  }
}

Here, your error was also to use the wrong Logger class. Use only classes from org.apache.logging.log4j.*.

/src/main/resources/log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Properties>
        <Property name="basePath">/var/log</Property>
    </Properties>
    <Appenders>
        <RollingFile name="fileLogger" fileName="${basePath}/myApp.log" filePattern="${basePath}/myApp-%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>

        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="console"/>
            <AppenderRef ref="fileLogger"/>
        </Root>
    </Loggers>
</Configuration>

Here, your errors are the following:

  1. Wrong file name: Log4J 2 requires a name log4j2.xml. For your tests, create a file /src/test/resources/log4j2-test.xml.
  2. You want only one logger, so use only one: the root one. You created several, but you don't need them.
  3. Add appenders to the logger (the Root-one)

Output

Console

[INFO ] 2017-12-05 16:52:32.218 [main] App - App.main - starting
[INFO ] 2017-12-05 16:52:32.221 [main] SecondClass - SecondClass - starting
[INFO ] 2017-12-05 16:52:32.222 [main] SecondClass - SecondClass - ending
[INFO ] 2017-12-05 16:52:32.222 [main] App - App.main - ending

/var/log/myApp.log

[INFO ] 2017-12-05 16:52:32.218 [main] App - App.main - starting
[INFO ] 2017-12-05 16:52:32.221 [main] SecondClass - SecondClass - starting
[INFO ] 2017-12-05 16:52:32.222 [main] SecondClass - SecondClass - ending
[INFO ] 2017-12-05 16:52:32.222 [main] App - App.main - ending
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • I have done literally everything you said, before you wrote it! I realized my errors thanks to the comment below my question. I wish to thank you for taking the time to reply! this is so kind and I appreciate it a lot! You helped me to rename the log4j.xml to log4j2.xml because I totally forgot to do it, this application had log4j 1,2 before and I am converting it. Anyway, since 10 minutes I'm stuck here: `ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console. 'log4j2.debug' to show Log4j2 internal initialization logging.` – aPugLife Dec 05 '17 at 15:55
  • @Nihvel I do not have that issue in my project. Try coming from the bases: put the `log4j2.xml` file in the `src/main/resources` folder. Copy it as `log4j2-test.xml` in the `src/test/resources` folder and edit that one for the tests you wish to perform. – Olivier Grégoire Dec 05 '17 at 16:00
  • It can not find the configuration file. But the file was renamed and the POM too: `src/main/resources${project.build.directory}log4j2.xml` so it should be all good! I just opened your answer. Yes, exactly what I did! Ok, I will try to read the codes better! thanks again! – aPugLife Dec 05 '17 at 16:02
  • I know it is correct what I have but it still can't find the file. StackOverflow is filled with question about this same topic, they say all the same: to put into src/main/resources; and it is what I did. But still nothing ... I accept your answer because the problem I asked was solved following these directives, but I'm still working on having the property file seen! – aPugLife Dec 05 '17 at 16:17
  • Found the "problem". My POM contains the directive for building both the tiny jar file with external lib/classes/etc.. and the fat-jar (all in one, weight ~16MB). The first is able to read the properties file and writes the log succesfully. The second not. I must find a way to let the fat-jar read the external properties file, like here: [LINK](https://stackoverflow.com/questions/8775303/read-properties-file-outside-jar-file) but just tried and does not work.. (: damn. – aPugLife Dec 06 '17 at 09:39
  • FIXED and used version 3.1.0 of maven shade plugin: [FIX HERE](http://www.codepreference.com/2017/02/how-to-fix-log4j2-problem-with-maven-shade-plugin.html) – aPugLife Dec 06 '17 at 10:10
  • Good job on finishing this! – Olivier Grégoire Dec 06 '17 at 10:33