Home >Java >After updating to 2.x, using 'slf4j.api' in an OSGi bundle requires the extension 'osgi.serviceloader.processor'

After updating to 2.x, using 'slf4j.api' in an OSGi bundle requires the extension 'osgi.serviceloader.processor'

王林
王林forward
2024-02-10 21:12:081056browse

After introducing the latest update to version 2.x, the php editor Apple found that using "slf4j.api" in the OSGi package requires the extension "osgi.serviceloader.processor". This update is an important change for developers using this extension, as it provides more flexibility and convenience. The purpose of this update is to help developers better use and manage slf4j.api to improve program performance and stability. Developers can look forward to more updates and improvements to meet their evolving needs.

Question content

I created a small reproducer project on github: slf4j-experiment

Basically what I need is an osgi package with some code using slf4j-api.

Example:

import org.osgi.service.component.annotations.activate;
import org.osgi.service.component.annotations.component;
import org.osgi.service.component.annotations.deactivate;
import org.slf4j.logger;
import org.slf4j.loggerfactory;

@component(service = someservice.class)
public class someserviceimpl implements someservice {
    private static final logger log = loggerfactory.getlogger(someserviceimpl.class);

    @override
    public string doit(string first, string second) {
        log.info("someserviceimpl: doit(..)");
        return operation(first, second);
    }

    static string operation(string first, string second) {
        return first + second;
    }

    @activate
    public void activate() {
        log.info("someserviceimpl: activate");
    }

    @deactivate
    public void deactivate() {
        log.info("someserviceimpl: deactivate");
    }
}

In my build.gradle I have:

dependencies {
    compileonly 'org.osgi:osgi.annotation:7.0.0'
    compileonly 'org.osgi:org.osgi.service.component.annotations:1.3.0'

    implementation 'org.slf4j:slf4j-api:2.0.11'
    runtimeonly 'org.slf4j:slf4j-simple:2.0.11'
    
    // ...
}

This works as expected with slf4j 1.7.36

Now using the 2.0.11 version of slf4j, due to the use of service providers, there are new constraints modeled in the osgi metadata and now I'm stuck:

Resolution failed. Capabilities satisfying the following requirements could not be found:
    [<<INITIAL>>]
      ⇒ osgi.identity: (osgi.identity=slf4j.simple)
          ⇒ [slf4j.simple version=2.0.11]
              ⇒ osgi.wiring.package: (&(osgi.wiring.package=org.slf4j)(version>=2.0.0)(!(version>=3.0.0)))
                  ⇒ [slf4j.api version=2.0.11]
                      ⇒ osgi.extender: (&(osgi.extender=osgi.serviceloader.processor)(version>=1.0.0)(!(version>=2.0.0)))

Looks like I need an extra bundle, probably provided by spi fly, but I don't understand how...

Workaround

YourExample Statement:

slf4j.api;version='[1.7.36,1.7.37)',\
slf4j.simple;version='[1.7.36,1.7.37)'

(I'm not a fan of gradle osgi bnd) resolves to slf4j-api-1.7.36.jar from maven central.

This is the correct osgi bundle:

import-package: org.slf4j.impl;version=1.6.0
export-package: org.slf4j;version=1.7.36, org.slf4j.spi;version=1.7.36
 , org.slf4j.helpers;version=1.7.36, org.slf4j.event;version=1.7.36

But slf4j-api-2.0.11.jar has:

require-capability: osgi.extender;filter:="(&(osgi.extender=osgi.service
 loader.processor)(version>=1.0.0)(!(version>=2.0.0)))"

In fact - it satisfies aries spi-fly:

Provide-Capability: osgi.extender;osgi.extender="osgi.serviceloader.re
 gistrar";version:Version="1.0",osgi.extender;osgi.extender="osgi.serv
 iceloader.processor";version:Version="1.0";uses:="org.apache.aries.sp
 ifly"

slf4j got these headers (required) in this commit. p>

spi-fly is osgi's take on the java service loader, dynamically transforming the bundle's code so that the correct thread context classloader is set.

This is actually a proper requirement for slf4j api 2 as they switch from the static binding of the logger implementation to /meta-inf/services/ org's service discovery.slf4j.spi.slf4jserviceprovider service.

However, osgi is a tenacious beast. For logging, I recommend the pax logging project, which not only exports the correct org.slf4j package, but also allows you to dynamically configure the logging backend and configure it using osgi configuration management.

The above is the detailed content of After updating to 2.x, using 'slf4j.api' in an OSGi bundle requires the extension 'osgi.serviceloader.processor'. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete
Previous article:Spring API controllerNext article:Spring API controller