Adding an @Activate to a DS bundle causes the bundle not to load

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Adding an @Activate to a DS bundle causes the bundle not to load

Steinar Bang
Platform: Java 1.8, karaf 4.1.3

I have the following DS component that exposes a Servlet to the Pax Web
Whiteboard Extender:
 https://github.com/steinarb/sonar-collector/blob/master/sonar-collector-webhook/src/main/java/no/priv/bang/sonar/collector/webhook/SonarCollectorServlet.java#L55

The component starts fine, and exposes a Servlet service that is picked
up by the whiteboard extender, and as far as I can tell, it does what it
is expected to do (receive POSTs from SonarQube/SonarCloud and store
build statistics in a PostgreSQL database).

However, if I add an empty activate method, like so:
 @Component(service={Servlet.class}, property={"alias=/sonar-collector"} )
 public class SonarCollectorServlet extends HttpServlet {
     ...
     @Activate
     public void activate(Map<String, Object> config) {
     }
     ...
 }

then the component fails to load, because of missing dependencies:
 karaf@root()> feature:repo-add mvn:no.priv.bang.sonar.sonar-collector/sonar-collector-webhook/LATEST/xml/features
 Adding feature url mvn:no.priv.bang.sonar.sonar-collector/sonar-collector-webhook/LATEST/xml/features
 karaf@root()> feature:install sonar-collector-webhook
 Error executing command: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=sonar-collector-webhook; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=sonar-collector-webhook)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.sonar.sonar-collector-webhook; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.service; effective:=ac
 tive; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)"]]
 karaf@root()>

If remove the "@Activate" annotation, the component loads again.

Does anyone know what might cause this?

What's strange about this, that the missing depenency the error message
complains about, ie. org.osgi.service.jdbc.DataSourceFactory, is
essential to the servlet's operation.  Without a DataSourceFactory, no
database can be contacted and no data can be saved (and data _is_ saved).

Is the error message because the bundle can't find the type
org.osgi.service.jdbc.DataSourceFactory? Or is the message about not
getting an instance of org.osgi.service.jdbc.DataSourceFactory?

The full error message from karaf.log below.

Thanks!


- Steinar

Error message from karaf.log follows:

2017-12-04T20:28:57,555 | ERROR | Karaf local console user karaf | ShellUtil                        | 42 - org.apache.karaf.shell.core - 4.1.3 | Exception caught while executing command
org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=sonar-collector-webhook; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=sonar-collector-webhook)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.sonar.sonar-collector-webhook; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.s
 ervice; effective:=active; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)"]]
        at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42) ~[?:?]
        at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:391) ~[?:?]
        at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:377) ~[?:?]
        at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:349) ~[?:?]
        at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:218) ~[?:?]
        at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:291) ~[?:?]
        at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1248) ~[?:?]
        at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$1(FeaturesServiceImpl.java:1147) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
        at java.lang.Thread.run(Thread.java:748) [?:?]



Reply | Threaded
Open this post in threaded view
|

Re: Adding an @Activate to a DS bundle causes the bundle not to load

Tim Ward-2
My educated guess...

By adding the activate method you have increased the required version of DS detected by bnd. This, in turn, has probably added a Require-Capability for the service that you import. This has no effect at runtime (due to the value of its effective directive) but if the service exporter does not have a corresponding Provide-Capability then it may have broken the Karaf feature resolver, which would stop your feature from deploying with the error that you see

In bnd you can fix this using repository augments (as it’s only a resolve-time issue). I don’t know whether Karaf has a similar feature.

The other fix is to make sure that your Postgres driver correctly advertises its service capabilities using Provide-Capability.

Tim

Sent from my iPhone

> On 4 Dec 2017, at 22:15, Steinar Bang <[hidden email]> wrote:
>
> Platform: Java 1.8, karaf 4.1.3
>
> I have the following DS component that exposes a Servlet to the Pax Web
> Whiteboard Extender:
> https://github.com/steinarb/sonar-collector/blob/master/sonar-collector-webhook/src/main/java/no/priv/bang/sonar/collector/webhook/SonarCollectorServlet.java#L55
>
> The component starts fine, and exposes a Servlet service that is picked
> up by the whiteboard extender, and as far as I can tell, it does what it
> is expected to do (receive POSTs from SonarQube/SonarCloud and store
> build statistics in a PostgreSQL database).
>
> However, if I add an empty activate method, like so:
> @Component(service={Servlet.class}, property={"alias=/sonar-collector"} )
> public class SonarCollectorServlet extends HttpServlet {
>     ...
>     @Activate
>     public void activate(Map<String, Object> config) {
>     }
>     ...
> }
>
> then the component fails to load, because of missing dependencies:
> karaf@root()> feature:repo-add mvn:no.priv.bang.sonar.sonar-collector/sonar-collector-webhook/LATEST/xml/features
> Adding feature url mvn:no.priv.bang.sonar.sonar-collector/sonar-collector-webhook/LATEST/xml/features
> karaf@root()> feature:install sonar-collector-webhook
> Error executing command: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=sonar-collector-webhook; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=sonar-collector-webhook)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.sonar.sonar-collector-webhook; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.service; effective:=ac
> tive; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)"]]
> karaf@root()>
>
> If remove the "@Activate" annotation, the component loads again.
>
> Does anyone know what might cause this?
>
> What's strange about this, that the missing depenency the error message
> complains about, ie. org.osgi.service.jdbc.DataSourceFactory, is
> essential to the servlet's operation.  Without a DataSourceFactory, no
> database can be contacted and no data can be saved (and data _is_ saved).
>
> Is the error message because the bundle can't find the type
> org.osgi.service.jdbc.DataSourceFactory? Or is the message about not
> getting an instance of org.osgi.service.jdbc.DataSourceFactory?
>
> The full error message from karaf.log below.
>
> Thanks!
>
>
> - Steinar
>
> Error message from karaf.log follows:
>
> 2017-12-04T20:28:57,555 | ERROR | Karaf local console user karaf | ShellUtil                        | 42 - org.apache.karaf.shell.core - 4.1.3 | Exception caught while executing command
> org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=sonar-collector-webhook; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=sonar-collector-webhook)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.sonar.sonar-collector-webhook; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.s
> ervice; effective:=active; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)"]]
>    at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42) ~[?:?]
>    at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:391) ~[?:?]
>    at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:377) ~[?:?]
>    at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:349) ~[?:?]
>    at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:218) ~[?:?]
>    at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:291) ~[?:?]
>    at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1248) ~[?:?]
>    at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$1(FeaturesServiceImpl.java:1147) ~[?:?]
>    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
>    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
>    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
>    at java.lang.Thread.run(Thread.java:748) [?:?]
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Adding an @Activate to a DS bundle causes the bundle not to load

cschneider
The requirement 
osgi.service; effective:=ac
 tive; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)
expresses that your bundle needs a service of this type. The resolver then checks if any other bundle in your feature:install provides the capabiltiy. It is not actually checking if the service is created. It just works on requirement / capability level.

In karaf you can define the Provide-Capability in a feature. If you do this in your own feature then you can kind of negate the requirement that is added to your bundle.
The better way to handle this is to make the bundle that provides the DataSourceFactory provide the capability or to let the feature that loads this bundle provide the capability.

Christian


2017-12-05 0:01 GMT+01:00 Tim Ward <[hidden email]>:
My educated guess...

By adding the activate method you have increased the required version of DS detected by bnd. This, in turn, has probably added a Require-Capability for the service that you import. This has no effect at runtime (due to the value of its effective directive) but if the service exporter does not have a corresponding Provide-Capability then it may have broken the Karaf feature resolver, which would stop your feature from deploying with the error that you see

In bnd you can fix this using repository augments (as it’s only a resolve-time issue). I don’t know whether Karaf has a similar feature.

The other fix is to make sure that your Postgres driver correctly advertises its service capabilities using Provide-Capability.

Tim

Sent from my iPhone

> On 4 Dec 2017, at 22:15, Steinar Bang <[hidden email]> wrote:
>
> Platform: Java 1.8, karaf 4.1.3
>
> I have the following DS component that exposes a Servlet to the Pax Web
> Whiteboard Extender:
> https://github.com/steinarb/sonar-collector/blob/master/sonar-collector-webhook/src/main/java/no/priv/bang/sonar/collector/webhook/SonarCollectorServlet.java#L55
>
> The component starts fine, and exposes a Servlet service that is picked
> up by the whiteboard extender, and as far as I can tell, it does what it
> is expected to do (receive POSTs from SonarQube/SonarCloud and store
> build statistics in a PostgreSQL database).
>
> However, if I add an empty activate method, like so:
> @Component(service={Servlet.class}, property={"alias=/sonar-collector"} )
> public class SonarCollectorServlet extends HttpServlet {
>     ...
>     @Activate
>     public void activate(Map<String, Object> config) {
>     }
>     ...
> }
>
> then the component fails to load, because of missing dependencies:
> karaf@root()> feature:repo-add mvn:no.priv.bang.sonar.sonar-collector/sonar-collector-webhook/LATEST/xml/features
> Adding feature url mvn:no.priv.bang.sonar.sonar-collector/sonar-collector-webhook/LATEST/xml/features
> karaf@root()> feature:install sonar-collector-webhook
> Error executing command: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=sonar-collector-webhook; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=sonar-collector-webhook)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.sonar.sonar-collector-webhook; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.service; effective:=ac
> tive; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)"]]
> karaf@root()>
>
> If remove the "@Activate" annotation, the component loads again.
>
> Does anyone know what might cause this?
>
> What's strange about this, that the missing depenency the error message
> complains about, ie. org.osgi.service.jdbc.DataSourceFactory, is
> essential to the servlet's operation.  Without a DataSourceFactory, no
> database can be contacted and no data can be saved (and data _is_ saved).
>
> Is the error message because the bundle can't find the type
> org.osgi.service.jdbc.DataSourceFactory? Or is the message about not
> getting an instance of org.osgi.service.jdbc.DataSourceFactory?
>
> The full error message from karaf.log below.
>
> Thanks!
>
>
> - Steinar
>
> Error message from karaf.log follows:
>
> 2017-12-04T20:28:57,555 | ERROR | Karaf local console user karaf | ShellUtil                        | 42 - org.apache.karaf.shell.core - 4.1.3 | Exception caught while executing command
> org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=sonar-collector-webhook; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=sonar-collector-webhook)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.sonar.sonar-collector-webhook; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.sonar.sonar-collector-webhook/1.0.0.SNAPSHOT] osgi.s
> ervice; effective:=active; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)"]]
>    at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42) ~[?:?]
>    at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:391) ~[?:?]
>    at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:377) ~[?:?]
>    at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:349) ~[?:?]
>    at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:218) ~[?:?]
>    at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:291) ~[?:?]
>    at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1248) ~[?:?]
>    at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$1(FeaturesServiceImpl.java:1147) ~[?:?]
>    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:?]
>    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:?]
>    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:?]
>    at java.lang.Thread.run(Thread.java:748) [?:?]
>
>
>



--
--
Christian Schneider

http://www.liquid-reality.de

Computer Scientist

Reply | Threaded
Open this post in threaded view
|

Re: Adding an @Activate to a DS bundle causes the bundle not to load

Steinar Bang
>>>>> Christian Schneider <[hidden email]>:

> The requirement
> osgi.service; effective:=active; filter:="(objectClass=org.osgi.service.jdbc.DataSourceFactory)
> expresses that your bundle needs a service of this type. The resolver
> then checks if any other bundle in your feature:install provides the
> capabiltiy.  It is not actually checking if the service is created. It
> just works on requirement / capability level.

> In karaf you can define the Provide-Capability in a feature. If you do
> this in your own feature then you can kind of negate the requirement
> that is added to your bundle.

> The better way to handle this is to make the bundle that provides the
> DataSourceFactory provide the capability or to let the feature that
> loads this bundle provide the capability.

Thanks!

I've looked at the manifest.mf of both my current version of the
PostgreSQL JDBC driver and tne newest version on maven central[1]
and neither of them contains the text "provide".

(side note: for why the version number suddenly changed from "9" to "42", see[2])

So for now I have the following plan:
 1. Add the workaround stuff to my feature so that it will work with the
    current version of the PostgreSQL JDBC driver
 2. Open an issue for the the missing header in the PostgreSQL JDBC
    driver issue tracker[3]
 3. Create a pull request with the appropriate maven-bundle-plugin
    changes and send that to the maintainers


References:
[1] <https://mvnrepository.com/artifact/org.postgresql/postgresql/42.1.4>
[2] <https://jdbc.postgresql.org/documentation/faq.html#versioning>
[3] <https://github.com/pgjdbc/pgjdbc/issues>


Reply | Threaded
Open this post in threaded view
|

Re: Adding an @Activate to a DS bundle causes the bundle not to load

Steinar Bang
>>>>> Steinar Bang <[hidden email]>:

> So for now I have the following plan:
>  1. Add the workaround stuff to my feature so that it will work with the
>     current version of the PostgreSQL JDBC driver
>  2. Open an issue for the the missing header in the PostgreSQL JDBC
>     driver issue tracker[3]

The issue is now in place:
 https://github.com/pgjdbc/pgjdbc/issues/1029

Reply | Threaded
Open this post in threaded view
|

Re: Adding an @Activate to a DS bundle causes the bundle not to load

Steinar Bang
>>>>> Steinar Bang <[hidden email]>:

>> So for now I have the following plan:
>> 1. Add the workaround stuff to my feature so that it will work with the
>>    current version of the PostgreSQL JDBC driver

This is now in place, and works:
 https://github.com/steinarb/sonar-collector/commit/ceac58f468c11b4c86f516d1184c31f06c65e2bd

Ie. the activate() method is called, and once I started using the fully
qualified class name of the component as the configuration PID, the
activate() method started receiving the correct configuration:
 https://github.com/steinarb/sonar-collector#using-a-database-running-on-a-different-host

>> 2. Open an issue for the the missing header in the PostgreSQL JDBC
>>    driver issue tracker[3]

> The issue is now in place:
>  https://github.com/pgjdbc/pgjdbc/issues/1029

>> 3. Create a pull request with the appropriate maven-bundle-plugin
>>    changes and send that to the maintainers

This is still left to do.

Reply | Threaded
Open this post in threaded view
|

Re: Adding an @Activate to a DS bundle causes the bundle not to load

Steinar Bang
>>>>> Steinar Bang <[hidden email]>:

>>> So for now I have the following plan:
>>> 1. Add the workaround stuff to my feature so that it will work with the
>>>    current version of the PostgreSQL JDBC driver

> This is now in place, and works:
>  https://github.com/steinarb/sonar-collector/commit/ceac58f468c11b4c86f516d1184c31f06c65e2bd

> Ie. the activate() method is called, and once I started using the fully
> qualified class name of the component as the configuration PID, the
> activate() method started receiving the correct configuration:
>  https://github.com/steinarb/sonar-collector#using-a-database-running-on-a-different-host

>>> 2. Open an issue for the the missing header in the PostgreSQL JDBC
>>>    driver issue tracker[3]

>> The issue is now in place:
>> https://github.com/pgjdbc/pgjdbc/issues/1029

>>> 3. Create a pull request with the appropriate maven-bundle-plugin
>>>    changes and send that to the maintainers

> This is still left to do.

The pull request is here:
 https://github.com/pgjdbc/pgjdbc-parent-poms/pull/10

Since the pull request was in a different github project than the one I
had opened an issue on, I also made a comment about the pull request on
the issue:
 https://github.com/pgjdbc/pgjdbc/issues/1029#issuecomment-350584909