Logback and conditional processing of configuration files in an OSGi environment
Programming Estimated reading time: ~2 minutes
Recently I had to make use of conditional processing in logback’s config files. Because the application runs in an OSGi environment I had to spend some time in order to get everything working as intended.
Problem analysis
As stated in the Logback documentation conditional processing in configuration files requires the Janino library. When running in an OSGi environment (e.g. an Eclipse RCP application) simply placing commons-compiler.jar and janino.jar on your application’s class path is not sufficient enough. You will get the following exception:
<...>
12:50:47,754 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
12:50:47,755 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [stdout] to Logger[ROOT]
12:50:47,755 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [file] to Logger[ROOT]
12:50:47,810 |-ERROR in ch.qos.logback.core.joran.conditional.IfAction -
Failed to parse condition [property("xxx.instance").equals("SIM_LOCAL")] org.codehaus.janino.JaninoRuntimeException:
Cannot load class 'ch.qos.logback.core.joran.conditional.PropertyWrapperForScripts' through the parent loader
at org.codehaus.janino.JaninoRuntimeException
<...>
This exception occurs because in an OSGi environment the class loader of the org.codehaus.janino bundle can not load classes from the ch.qos.logback.core bundle. See here and here for a primer on OSGi class loading.
Solution
The org.codehaus.janino bundle would need a “Require-Bundle: ch.qos.logback.core” directive in it’s manifest file in order for the bundle class loader to be able to load classes from the ch.qos.logback.core bundle. This can be achieved by extending the org.codehaus.janino bundle via a fragment (e.g. ch.qos.logback.core.janino.fragment). Below is the manifest of the fragment:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Janino Fragment (needed to uses Janino together with logback
in an OSGi environment)
Bundle-SymbolicName: ch.qos.logback.core.janino.fragment
Bundle-Version: 1.0.0
Fragment-Host: org.cohehaus.janino
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: ch.qos.logback.core
Bundle-Vendor: Danube Development
The bundle name org.cohehaus.janino
in the bundle fragment directive is a typo
in the upstream project. I am currently evaluating if it’s possible to push
such a fragment to the logback upstream project.
Update #1 (10. Apr. 2016)
My Pull Request over at
GitHub has been accepted. The logback-janino-fragment
is now part of the
ch.qos.logback.contrib
project. You can download the artifact / fragment
e.g. here.
A note about Netcup (advertisement)
Netcup is a German hosting company. Netcup offers inexpensive, yet powerfull web hosting packages, KVM-based root servers or dedicated servers for example. Using a coupon code from my Netcup coupon code web app you can even save more money (6$ on your first purchase, 30% off any KVM-based root server, ...).