Unable to replace logger, ServiceLocator.instance() returns null

Java SDK 1.8.0_131

Liquibase 3.5.3
eclipse IDE Neon 3 (eclipse 4.6.3)

I am trying to replace the logger as outlined in Fixing liquibase logging (in Spring) with SLF4J and Log4J but so far I haven’t been successful.  

The reason seems to be because ServiceLocator.instance(), called from LogFactory.getLog(), returns a null, and the defaultLogger is returned instead.

Is there some obvious initialization code that may I have missed? (I have used examples found by googling, combined with trial and error).

I first tried replacing the logger by adding a maven dependency to Matt Bertolinis liquibase-slf4j, but that didn’t have any effect.

I then tried replacing the logger as simply as possible:
Created a package liquibase.ext.logging in the project where I’m calling Liquibase fromCreated a class “public class UkelonnLiquibaseLogger extends AbstractLogger” in this packageThe UkelonnLiquibaseLogger class at this time, just had empty methods.  I figured that if all of the Liquibase output went away, the class would have been found, and that I would see this as soon as I started running unit tests.

But the liquibase output continued to be written to the console, so the class wasn’t picked up.

When I debugged into the startup code I was able to hit code in the ServiceLocator constructor, called from the static initializer of the ServiceLocator class. Eclipse didn’t let me set any breakpoints inside the static initializer of ServiceLocator so I wasn’t able to see what was going on there. I wasn’t able to figure out if any exceptions were thrown from the constructor either.

However when I next hit the breakpoints in ServiceLocator.getInstance() the instance was null.

I had a breakpoint in ServiceLocator.setInstance() as well, but this breakpoint was never called.

This is how I create and use Liquibase:

- Steinar

Now I’ve succeeded in having the custom logger picked up when running in the unit tests.

What I did to fix this, was to ensure that the getPriority() method of my logger returned a high number:
 with the class loader set explicitly, finds the database changeset files both when running in unit tests and when running in OSGi.

Now I have liquibase logging to the karaf log instead of flooding the karaf console.

It wasn’t easy, but I got help: see this message on the karaf user mailing list

In short, what’s needed, is:

  1. A maven module that rebundles the liquibase-slf4j maven dependency into an OSGi bundle fragment that is connected to the org.liquibase.core OSGi bundle (ie. the liquibase-core maven dependency)
  2. A karaf feature that loads the rebundled liquibase-slf4j  OSGi fragment before it loads liquibase-core
This puts the liquibase.ext.logger.slf4j package into a place where the bundle classloader can find it.

Note. The classloader will not find the liquibase.ext.logger.slf4j package if it is made available as a package exported by an OSGi bundle. It has to be “included” into the org.liquibase.core bundle.

Here’s a karaf feature that will install liquibase-core and fix the log:  https://github.com/steinarb/liquibase-karaf-feature

To install:

  1. clone this project and build it with maven:
    mkdir -p ~/git cd ~/git git clone https://github.com/steinarb/liquibase-karaf-feature/ cd liquibase-karaf-feature mvn clean install 
  2. start karaf and give the following commands to the karaf console:
    feature:repo-add mvn:no.priv.bang.karaf/liquibase-core-karaf/LATEST/xml/features feature:install liquibase-core 

I have deployed the liquibase-core karaf feature https://github.com/steinarb/liquibase-karaf-feature to maven central.

The deployed feature has version 3.5.3 and will load liquibase 3.5.3 (and redirect the liquibase logs to the karaf logs).

To load the feature, type the following commands in the karaf console: https://github.com/steinarb/liquibase-karaf-feature#installing-the-liquibase-feature-in-karaf

To depend on the liquibase-core feature from a karaf feature file, reference the liquibase-core feature repository before referencing the liquibase-core feature: https://github.com/steinarb/liquibase-karaf-feature#using-liquibase-from-a-karaf-feature

Hi Steinar Bang,

can you please have a look at the upcoming changes to the Liquibase Logging for 3.6 and if it’s still possible to run Liquibase in Karaf with them applied?

see: http://forum.liquibase.org/#Topic/49382000001706025

now is the time the request changes if necessary.

kind regards


Hi, I never saw this post, but the karaf liquibase logging fix works for version 3.5.3 and for 3.8.0 (which is the last version I was able to create a working feature for), so I’m assuming it works for all versions in between.

Right now I have high hopes for the upcoming 3.10.2…:slight_smile: