4
votes

My current application uses Logback for logging. I have used Apache Felix to deploy an OSGi framework that allows bundles to be dynamically registered at runtime. The Felix setup is as follows:

    ...

    //System.out.println("Building OSGi Framework");
    FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
    Map<String, String> config = new HashMap<>();

    // specify the class loader
    config.put(Constants.FRAMEWORK_BUNDLE_PARENT, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK);

    // specify the osgi cache directory
    config.put(Constants.FRAMEWORK_STORAGE, appConfig.getOsgiCacheDir());

    // make sure the cache is cleaned
    config.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);

    // expose api
    config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "list.of.packages.to.export");

    // more properties available at: http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html
    config.put("ds.showtrace", "false");
    config.put("ds.showerrors", "true");
    config.put("felix.fileinstall.dir", appConfig.getActiveOsgiExtDir());
    config.put("felix.fileinstall.tmpdir", appConfig.getTempOsgiExtDir());
    config.put("felix.fileinstall.bundles.startTransient","true");
    config.put("felix.fileinstall.poll","5000");
    config.put("felix.fileinstall.bundles.new.start", "true");

    LOG.debug("OSGi config: " + config.toString());

    framework = frameworkFactory.newFramework(config);

    try {
        framework.init();
        FrameworkEvent event;

        do {
            framework.start();
    ...

The only problem is that there seems to be no logging with Felix. When a bundle fails to load for some reason I can't see why! I know that I can use the following in the bundle to obtain the parent logger:

ServiceReference ref = bundleContext.getServiceReference(LogService.class.getName());
if (ref != null) {
    LogService log = (LogService) bundleContext.getService(ref);
    ...
   }

However, I don't understand how I can get felix to use logback as the logger in the first place.

1
You don't need logging to work out why a bundle doesn't start. Just start it explicitly from the shell and observe the error message there.Neil Bartlett
Your absolutely correct. However, I do generically need to be able to perform logging and for bundles to be able to pass their logging to the main application framework.tarka

1 Answers

4
votes

I guess you use Apache Felix Log to have a LogService in you OSGi container. Apache Felix Log implements the chapter "101 Log Service Specification" of OSGi Enterprise Specification.

The basic of LogService implementation stores the logged entries for a while but does not write them to anywhere. You can query the recorded entries via LogReaderService or LogListener.

On the other hand, you might use Logback in the way that you added slf4j-api and slf4j-logback to your OSGi container. By doing that, everything that is logged via slf4j-api classes will be logged by logback.

If my guesses were right, the osgi-loglistener-slf4j bundle could help you. This bundle does nothing else but registers a LogListener for every LogReaderService in the environment and forwards every log entries it catches to slf4j-api. The bundle is available on maven-central

If you do not want to use slf4j API, you can write a similar bundle that does the log forwarding from LogReaderService to Logback. If you check the source of the bundle I linked, you will see that it is implemented with only a few lines of code.