Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Change log4j Configuration When Packaging

Tags:

java

maven

log4j

I have a fairly simple Java application that is being distributed out to users as an executable JAR file. In order to track usage and assist in diagnostics, I want to add logging capability to the application but, from one execution to the next, I can never be sure where the users are going to be running this application.

In order to make this work, I have configured my application to use a log4j socket appender - no matter where the user is running this application, messages are sent to the socket and properly logged, which is perfect.

What I'm running into now, though, it that I would prefer to use different log4j configurations when I am running locally vs. when I deploy this application into production. When running locally (from my IDE, IntelliJ), I would prefer to use a console appender for a couple reasons:

  1. It's trivial to see what is happening.
  2. Should I be developing without an Internet connection, I don't want to hang up on not being able to connect.
  3. I don't want to clutter the production logs with what I am doing during development.

When I package the application and distribute it, however, I would like it to use the socket appender, rather than the console appender.

Is there any easy way to accomplish what I want? I am using Maven to build my application, but I am not horribly skilled with it.

like image 769
McGlone Avatar asked Dec 21 '22 13:12

McGlone


2 Answers

Here's a simpler approach to your problem...

Put two log4j.properties files under src/main/resources directory, like this:-

src/main/resources
|- log4j.properties 
|- log4j_dev.properties 

log4j.properties contains the production configuration, and by default, Log4J will automatically pick this file up because you are using the standard file name.

log4j_dev.properties contains the development configuration. To ensure IntelliJ picks this up during development, you will overwrite the log configuration using -Dlog4j.configuration=<configuration-file> VM option. I attached a screenshot on how you might configure this using IntelliJ:-

enter image description here

like image 198
limc Avatar answered Dec 23 '22 03:12

limc


This turned out to be simpler than I originally expected - and Vikdor's comment led me to the right answer. I had started digging into having multiple profiles (one for dev and one for prod) but later realized I didn't really need to have two. When working locally, I wasn't really going through the Maven build process - I was just executing the Java classes. The only time I went through the Maven build process was when I wanted to package my application for deployment. As such, I simply added a section to my POM file that uses the maven-antrun-plugin. My final code ended up looking like this:

File: log4j.properties:

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

File: log4j_production.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A2

log4j.appender.A2=org.apache.log4j.net.SocketAppender
log4j.appender.A2.remoteHost=my.server.com
log4j.appender.A2.port=6000
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

File: POM.xml

...
<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <tasks>
                            <delete file="${project.build.outputDirectory}/log4j.properties"/>
                            <copy file="src/main/resources/log4j_production.properties"
                                  toFile="${project.build.outputDirectory}/log4j.properties"/>
                        </tasks>
                    </configuration>
                </execution>
            </executions>
        </plugin>
...

That seemed to do the trick. When I run locally, I load log4j.properties, which gives me a console appender. When I package for a production distribution, Maven will replace the default log4j.properties file with the alternate one, which uses a socket appender.

Thanks!

like image 33
McGlone Avatar answered Dec 23 '22 02:12

McGlone