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

6

28

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?

Hennahane answered 15/8, 2013 at 22:46 Comment(1)
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.Hatchet
I
23

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).

Instrument answered 16/8, 2013 at 14:41 Comment(1)
+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.Sorbitol
C
3

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.

Cockade answered 16/8, 2013 at 5:52 Comment(0)
H
2

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.

Hennahane answered 17/8, 2013 at 19:30 Comment(0)
J
1

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.

Jenson answered 1/8, 2017 at 14:58 Comment(0)
K
0

In my case, I modified the answer from Stephen, so project.clj looks like so:

:profiles {:dev {:resource-paths ["test/resources"]}}  ; appended to default

and the new directory test/resources contains the logback.xml used for testing the library, but it is not propogated to users of the lib.

Note that, as per the comment, "test/resources" is appended to the default value of :resources-paths to create a final value of ["resources" "test/resources"]

Kilburn answered 28/8, 2019 at 17:45 Comment(0)
C
0

Long story short, I couldn't get away from this problem with how I built my jars. I instead found this in the doc:

-Dlogback.statusListenerClass=ch.qos.logback.core.status.NopStatusListener
Chintzy answered 10/3, 2023 at 3:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.