OSGI classloader issue

Attempting to run liquibase within an Eclipse RCP yeilds the following error in liquibase 2.0.1:

Could not find implementation of liquibase.logging.Logger

I'm assuming this is related to the disperate classloading - is there a strategy or workaround which allows the liquibase serviceLocator to locate classes within an osgi bundle?


I think the DefaultPackageScanResolver doesn’t work with OSGi. As far as I can see, the DefaultPackageScanResolver lists classes from either the filesystem or a jar file in order to find implementations. But it cannot do so for OSGi bundles (http://grepcode.com/file/repo1.maven.org/maven2/org.liquibase/liquibase-core/2.0.1/liquibase/servicelocator/DefaultPackageScanClassResolver.java#169).

Maybe one can create a compatible PackageScanClassResolver that doesnt scan packages but looks up services from the OSGi registry (or better to create a compatible ServiceLocator, so its newInstance() method can return the service directly from the registry). This way it’s possible to find implementations of interfaces (not subclasses of “normal” classes, though) – and one would have to register every implementation to the registry – which are quite a few…  A BundleActivator can then just instantiate either the new ServiceLocator or set the osgi-enabled class resolver. 

I just gave it a quick try  with a very simple changelog that only creates a table and inserts a row. But I don’t know liquibase code well enough, maybe this won’t work in real world.  I have no idea for a “simple” workaround.



I haven’t dealt with OSGi much. Does anyone with more experience have an idea of the problem?


Yes, you will have to create a new ClassResolver. Using the extension system (liquibase.org/extensions) you should be able to have the new resolver picked up without needing to rebuild or modify liquibase, although I haven’t tested that particular extension point much.


I just ran in to the same problem with 2.0.1 and Equinox.  Could you expand more on how to create a new ClassResolver?  Looking at the source, it appears the ServiceLocator directly instantiates the DefaultPackageScanResolver.



You can set your own instance of a ServiceLocator via ServiceLocator.setInstance(new CustomResolverServiceLocator(…))