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:
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.
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:-
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With