2

Let assume I have a jar file called myApp.jar. The jar file is a comprised of 4 applications. All four applications within the jar file use the same code within the jar file and the only difference is how data is extracted and transformed. The packages within the jar file look something like this

com.myapp
    |-App1Main.java
    |-App2Main.java
    |-App3Main.java
    |-App4Main.java
com.myapp.transform
    |-App1Transform
    |-App2Transform
    |-App3Transform
com.myapp.service
    |-MyAppService.java
com.myapp.model
    |-{ModelClasses}
com.myapp.dao
    |-MyAppDAO

The only difference is that each application uses a different set of algrithms to transform/convert data from different sources. Once the data is converted, the service, dao, model classes are all shared between the different applications. The applications are run using a command similar to this one

$JAVA_HOME/java -cp myApp.jar com.myApp.App1Main.java

The jar file contains a log4j.propeties file that is used by all three applications.

log4j.rootLogger=WARN, stdout, myAppLogger
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.myAppLogger.File=/myapp/logs/myapp.log
log4j.appender.myAppLogger.layout=org.apache.log4j.PatternLayout
log4j.appender.myAppLogger.DatePattern=.dd-MM-yyyy
log4j.appender.myAppLogger.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.appender.myAppLogger=org.apache.log4j.DailyRollingFileAppender

At the moment, the above configuration means that each of the 3 applications within the jar file all write to the same log file - i.e. /myapp/logs/myapp.log I would like to change this so that each application writes to its own log file.

One solution i have found is to change the log file configuration to this:

log4j.appender.myAppLogger.File=/myapp/logs/${logfile.name}

Then just call each application using a different logfile name as a system property as shown below:

$JAVA_HOME/java -cp myApp.jar com.myApp.App1Main.java -Dlogfile.name=myApp1Log.log
$JAVA_HOME/java -cp myApp.jar com.myApp.App1Main.java -Dlogfile.name=myApp2Log.log
$JAVA_HOME/java -cp myApp.jar com.myApp.App1Main.java -Dlogfile.name=myApp3Log.log
$JAVA_HOME/java -cp myApp.jar com.myApp.App1Main.java -Dlogfile.name=myApp4Log.log

The above will probably work but i am not so keen on using system properties. Is there a way of achieving the same thing using multiple loggers?

I know that i can setup up multiple loggers and call the relevant logger within the application but the issue i have is i have no way of knowing which application is currently running on some of the classes. For example..

Setup multiple loggers

log4j.rootLogger=WARN, stdout,MyApp1, MyApp2, MyApp3, MyApp4 
# setup MyApp1
log4j.appender.myAppLogger=org.apache.log4j.RollingFileAppender
log4j.appender.myAppLogger.File=/myapp/logs/myapp1.log
...
...
# setup MyApp4
log4j.appender.LoudAppender=org.apache.log4j.RollingFileAppender
log4j.appender.myAppLogger.File=/myapp/logs/myapp4.log
...

log4j.logger.com.yourpackage.yourclazz=TRACE

the MyAppService and MyAppDAO classes are used by all 4 applications. If i want to write to the log file while in MyAppService or MyAppDAO i will have to do something like:

- import all 4 loggers in MyAppservice
- if the application is myapp1 use myapp1 logger
- if the application is myapp2 use myapp2 logger
- if the application is myapp3 use myapp3 logger
- if the application is myapp4 use myapp4 logger

The above will also probably work but having multiple if statements in several places within the code is not very clean.

I am looking for a better cleaner more generic approach that does not require having IF statements or passing around the name of the application within methods etc. Any better suggestions?

2
  • can't you setup the logger in your AppMain classes and then pass it to the shared classes?
    – redDevil
    Commented Apr 12, 2013 at 14:04
  • you can change the log4j system property even inside your code
    – Alepac
    Commented Apr 12, 2013 at 14:07

2 Answers 2

2

You want that every classes log into the same file, but the name of the file should depend on the entry point. In each each Main class you can :

  • programatically set up and add the appender to the root logger.
  • or load a different property file
  • or set the system property containing the file name (instead of setting it on the command line)
1

I like the idea of using multiple loggers. As I see you have problem of using loggers in common classes like MyAppService and MyAppDAO classes. I'd say when instantiating these objects, pass logger object to the constructor. If you use static logger objects then you may want to pass as an argument to methods you are calling on these objects. This way you don't need to have if-else conditional checking for loggers.

Not the answer you're looking for? Browse other questions tagged or ask your own question.