how do I suppress a inherited projects logback.xml file (2 logback.xml in a single project)?

12,714

Solution 1

As far as I'm concerned, you should never package a logging config file (logback.xml, log4j.properties, or what have you) inside a JAR file. The whole point of even having a logging config file is to make it easy for the end-user to adjust logging levels by editing the file. Burying it in an archive defeats the purpose of that, because to change the logging level your user has to expand the archive, edit the file, and then re-package the archive.

Here's my preferred layout for a deployed application. It's a little bit more work to set up, but IMO is worth the trouble because it gives you the flexibility and ease of configuration that an uberjar doesn't.

my-app/
  bin/
    run-app.sh
  config/
    logback.xml
  lib/
    my-lib.jar
    my-app.jar

Your run-app.sh script would look something like:

BIN=`dirname "$0"`
BASE=$BIN/..
java -cp "$BASE/config:$BASE/lib/*" my-app.main

This has the advantage that, by putting the config directory at the front of the classpath, any logging config file found there should take precedence over anything that might be found in one of the JARs (e.g. included by a third-party library that you have no control over).

Solution 2

In case the base is a library it should not come with a logback.xml. Why is a library concerned about logging? In case it is an application, you should probably extract the common part into a library – base-common – and a small application – base-app. Then base-common does not contain any logback configuration. base-app and derive both depend on base-common. They can specify their logback configuration without conflict.

Solution 3

I wanted to answer my own question because I was specifically asking in the context of Clojure (although I completely failed to mention that in originating question, genius).

I fixed the problem by doing as Alex (accepted answer) suggest, and putting my logback.xml in its own special directory dev-config. I then use clojure's project.clj file to specify that dev-config should only be loaded when the development profile is run, as follows:

;; project.clj
(defproject com.samedhi/base.app "0.0.1-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.5.1"]]
  :profiles {:dev {:source-paths ["dev", "dev-config"]}}
  :min-lein-version "2.0.0"
  :source-paths ["app/src" "app/templates"]
  :resource-paths ["config"]
  :target-path "out/"
  :compiler-options {:externs ["app/externs/base.js"]}
  :aliases {"dumbrepl" ["trampoline" "run" "-m" "clojure.main/main"]})

The only important point is that :profiles => :dev => :source-paths has had "dev-config" added to its vector. This directory is picked up when I am doing local development, but is not part of created jar files, and as such does not show up in other projects that import this project. So, the logging shows up when doing development on this project, but does not show up when this project is used by other projects. Excellent.

Solution 4

I found the Alex strategy to be effective. I would like to add a small hint: you can create a common-config project with the editable common configuration files put inside (e.g. logback.xml etc.) Add the resulting artifact as a dependency in all your projects, with the scope provided.

This will allow you to use the logback.xml at compile/test time (from Eclipse or whatever IDE), but will exclude the common-config jar from the dependencies available for inheritance. At runtime you will provide the proper file (depending on the dev/test/prod environment) as Alex shows.

Share:
12,714

Related videos on Youtube

Stephen Cagle
Author by

Stephen Cagle

I like fried peanut butter and banana sandwiches; doused in honey. SOreadytohelp

Updated on August 29, 2020

Comments

  • Stephen Cagle
    Stephen Cagle over 3 years

    I have project com.samedhi/base that has a logback.xml file and project com.samedhi/derive that also has a logback.xml file. Project 'derive' has a dependency on 'base'. When I "lein trampoline repl" on 'derive', I get the following warning.

    ....
    15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
    15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
    15:34:30,066 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/home/stephen/Work/com.samedhi/derive/client/config/logback.xml]
    15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the classpath.
    15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [jar:file:/home/stephen/.m2/repository/com/samedhi/base.app/0.0.1-SNAPSHOT/base.app-0.0.1-SNAPSHOT.jar!/logback.xml]
    15:34:30,067 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [file:/home/stephen/Work/com.samedhi/derive/client/config/logback.xml]
    15:34:30,129 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
    ....
    

    So, the problem appears to be that I have two logback.xml's in my classpath. What am I supposed to do to "surpress" the logback.xml from project 'base' when I lein repl from the 'derive' project?

    • Catfish
      Catfish over 7 years
      In my case I want to create a general logging library that my team uses in all projects so I want my logback.xml buried in our logging util dependency.
  • amaidment
    amaidment over 8 years
    +1 for the general recommendation to not package a logging config file in a jar. The only times that we do package the logging file are when creating an executable jar or java webstart release. However, as we use maven, we have to do a subsequent mvn clean install to remove the jar with the logging configuration from the local repository.