Hi,
not sure if this answers your question, but actually I thought of something
similar for the Eclipse Platform Runtime.
The issue I am seeing there is probably an incorrect bundle design where
service interfaces and default implementations of the services are in one
bundle. Well, it could be discussed if this is sometimes ok, but that should
not be part of this discussion. In the end it would not be an issue when the
services are referenced dynamic greedy so one could simple register a service
with a higher ranking to override the default.
The bad thing at the moment is that some of these service implementations are
dependent on Equinox, as they use classes from the org.eclipse.osgi.service.*
packages. With non-optional Import-Package statements that means the Eclipse
Platform Runtime needs Equinox OSGi to run. From my point of view that
dependency is too strict for that project and it should be possible to also
start it with another OSGi implementation.
Therefore I was thinking about making these imports optional, so the bundles at
least start without throwing wiring errors. It would of course mean on the
other hand that those default service implementations are not getting activated
because the required classes are not found. But that could be solved afterwards
by adaptors that want to run on a different OSGi implementation.
But even a simple test turned out that this is not working as intended. SCR
loads the XML and even activates the component. At execution time of the
service there is a NoClassDefFoundError. The expectation (even from BJ’s
answer) would be that SCR does not even activate the service implementation
because the class cannot be loaded.
I created the following test scenario:
Bundle: org.fipro.test.helper
Public Package: org.fipro.test.helper
Helper-Class:
public class SimpleHelper {
public static void doSomething() {
System.out.println("do something");
}
}
Bundle: org.fipro.test.service
Private Package: org.fipro.test.service
Import-Package: org.fipro.test.helper (optional)
public interface SimpleService {
String calculateSomething(String input);
}
@Component
public class SimpleServiceImpl implements SimpleService {
@Override
public String calculateSomething(String input) {
SimpleHelper.doSomething();
return "SimpleServiceImpl calculated something with " + input;
}
}
@Component
public class TestServiceImpl implements SimpleService {
@Override
public String calculateSomething(String input) {
return "TestServiceImpl calculated something with " + input;
}
}
@Component(
property= {
"osgi.command.scope:String=fipro",
"osgi.command.function:String=simple"
},
service=SimpleServiceCommand.class)
public class SimpleServiceCommand {
@Reference
List<SimpleService> services;
public void simple(String input) {
System.out.println("number of services: " + services.size());
services.forEach(s -> s.calculateSomething(input));
}
}
Start the test without the bundle org.fipro.test.helper. The startup is fine,
because the org.fipro.test.helper package import is optional. Calling the
command “simple test” does not execute because of the NoClassDefFoundError
underneath.
I also modified the example for service references. So I created a service
interface in org.fipro.test.helper
public interface OtherService {
}
Then I added a service reference to the SimpleServiceImpl
@Component
public class SimpleServiceImpl implements SimpleService {
@Reference
OtherService blubb;
@Override
public String calculateSomething(String input) {
SimpleHelper.doSomething();
return "SimpleServiceImpl calculated something with " + input;
}
}
This way SimpleServiceImpl is not started because it cannot be satisified. Fine
so far. But a strange effect is coming up when changing the reference to an
OPTIONAL cardinality. In that case a NullPointerException is thrown in
FieldHandler#validateField()
For the Eclipse Platform Runtime scenario one could argue that using
service.ranking and single service references are suitable and it should work.
Especially for mandatory service references it should be ok. But the optional
dependencies for services does not seem to be working as expected from the
initial question.
But I have to admit that I am not sure if my test scenario is itself a good one
because of the static helper.
Mit freundlichen Grüßen / Best regards
Dirk Fauth
Automotive Service Solutions, ESI application (AA-AS/EIS2-EU)
Robert Bosch GmbH | Postfach 11 29 | 73201 Plochingen | GERMANY |
www.bosch.com<http://www.bosch.com>
Tel. +49(7153)666-1155 | [email protected]<mailto:[email protected]>
Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000;
Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar
Denner,
Prof. Dr. Stefan Asenkerschbaumer, Dr. Rolf Bulander, Dr. Stefan Hartung, Dr.
Markus Heyn, Dr. Dirk Hoheisel,
Christoph Kübel, Uwe Raschke, Peter Tyroller
Von: [email protected] [mailto:[email protected]] Im
Auftrag von Felix Meschberger
Gesendet: Mittwoch, 26. April 2017 04:14
An: OSGi Developer Mail List <[email protected]>
Betreff: Re: [osgi-dev] handling optional/dynamic imports in DS
My understanding is as well that this is exactly how DS works.
But I think Rays question goes further into supporting situations in a way
that a component activates and registers dynamically depending on what service
interface is actually available.
I think this does not work with plain DS but requires additional logic to check
for wires and/or trying to load classes. The Apache Felix
ScrServiceServiceFactory does this being registered as a ServiceFactory by the
BundleActivator ScrConfiguration. The latter could be a component (here it is a
BundleActivator because this is the DS implementation itself).
Yet this is really a special case of a situation which is not covered by DS and
which probably is outside of the scope of DS' charter.
Regards
Felix
--
Creative typing support courtesy of my iPhone
Am 25.04.2017 um 15:47 schrieb BJ Hargrave
<[email protected]<mailto:[email protected]>>:
So why isn't this just the case already? SCR processes the XML, cannot load the
impl class and logs that in the log. End of story. When bundle resolves again
later and can access the class, when SCR processes the XML, it can load the
impl class and thus the component is good to go.
--
BJ Hargrave
Senior Technical Staff Member, IBM // office: +1 386 848 1781
OSGi Fellow and CTO of the OSGi Alliance // mobile: +1 386 848 3788
[email protected]<mailto:[email protected]>
----- Original message -----
From: Raymond Auge <[email protected]<mailto:[email protected]>>
Sent by: [email protected]<mailto:[email protected]>
To: OSGi Developer Mail List
<[email protected]<mailto:[email protected]>>
Cc:
Subject: Re: [osgi-dev] handling optional/dynamic imports in DS
Date: Tue, Apr 25, 2017 6:20 PM
On Tue, Apr 25, 2017 at 6:16 PM, Christian Schneider
<[email protected]<mailto:[email protected]>> wrote:
Not sure if that is possible...
I think it would be awesome if the DS runtime could try to load the component
class and if it fails because of an unwired package
it could simply choose to not instantiate the component. It could also report
this problem when you look into the components from the shell.
When the bundle is then refreshed later it could try the same again and maybe
succeed if the package is wired now.
The big advantage would be that the user would not have to code anything to
make this work.
Currently handling optional imports using an Activator is quite difficult and
error prone.
Does that make sense?
I totally agree!
- Ray
Christian
On 26.04.2017 00:06, Raymond Auge wrote:
You're not far off,
but clearly the component could not be implementing the missing package...
Let's say we have an API:
interface com.foo.Provider {
public void provide();
}
a bundle wants to provide an implementation of this API:
@Component
class FancyProviderImpl implements com.foo.Provider { ... }
However the goal of FancyProviderImpl is to deliver functionality by using
fancy-lib.jar which is a second bundle.
e.g.
import fancy.lib.Thing;
@Component
class FancyProviderImpl implements com.foo.Provider {
public void provide() {
new Thing().doSomethingFancy();
}
}
I'd like for the bundle containing FancyProviderImpl to have an optional import
on `fancy.lib`, and not blow up when `fancy-lib.jar` is not deployed. Exactly
the same scenario you mentioned with configAdmin, metatype and SCR.
I hope that makes sense,
- Ray
On Tue, Apr 25, 2017 at 5:51 PM, Felix Meschberger
<[email protected]<mailto:[email protected]>> wrote:
Hi Ray
I am not sure, I understand the question.
Are you asking that the component dynamically decides to register as a certain
service depending on the whether a certain package is wired ?
I think that does not work as the component implements an interface which is
the service name and the component class can only be loaded if the class object
representing the interface being implemented is accessible, otherwise a Linkage
error occurrs.
Or may I am on the wrong track alltogether.
Regards
Felix
Am 25.04.2017 um 14:46 schrieb Raymond Auge
<[email protected]<mailto:[email protected]>>:
Thank you Felix, I agree and understand all of what you are saying.
However, what I'm wondering though is if anyone has come up with a design
pattern where a DS component can determine programmatically whether it (or a
peer component it controls) should be provided as a service based on the check
for some optional package.
Sincerely,
- Ray
On Tue, Apr 25, 2017 at 5:33 PM, Felix Meschberger
<[email protected]<mailto:[email protected]>> wrote:
Hi
You mean dynamic imports due to optional dependencies ?
I think the key is to limit them. If I remember correctly I have (or had) some
of this in the Apache Felix SCR implementation around the Metatype and
Configuration Admin dependencies.
What I do is I hand-craft a DynamicImport-Package statement for the exact
package along with the packages import version range. Then, unless the service
is provided, the package may not be resolved.
I generally also have fields, but as long as I don’t access that field other
than checking for null, the dependency is not needed either.
This works great, but I try to reduce such uses to the absolute minimum because
it involves manual work.
Hope this helps
Regards
Felix
Am 25.04.2017 um 14:10 schrieb Raymond Auge
<[email protected]<mailto:[email protected]>>:
I'm wondering if there is a reasonable model for handling optional or dynamic
package imports in DS.
While optionality at the package level is not an ideal model, sometimes it
can't be avoided.
I'd like to know if others have come across a "reasonable" way to model this in
DS.
Sincerely,
--
Raymond Augé<http://www.liferay.com/web/raymond.auge/profile> (@rotty3000)
Senior Software Architect Liferay, Inc.<http://www.liferay.com/> (@Liferay)
Board Member & EEG Co-Chair, OSGi Alliance<http://osgi.org/> (@OSGiAlliance)
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
--
Raymond Augé<http://www.liferay.com/web/raymond.auge/profile> (@rotty3000)
Senior Software Architect Liferay, Inc.<http://www.liferay.com/> (@Liferay)
Board Member & EEG Co-Chair, OSGi Alliance<http://osgi.org/> (@OSGiAlliance)
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
--
Raymond Augé<http://www.liferay.com/web/raymond.auge/profile> (@rotty3000)
Senior Software Architect Liferay, Inc.<http://www.liferay.com> (@Liferay)
Board Member & EEG Co-Chair, OSGi Alliance<http://osgi.org> (@OSGiAlliance)
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
--
Christian Schneider
http://www.liquid-reality.de
Open Source Architect
http://www.talend.com
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
--
Raymond Augé<http://www.liferay.com/web/raymond.auge/profile> (@rotty3000)
Senior Software Architect Liferay, Inc.<http://www.liferay.com> (@Liferay)
Board Member & EEG Co-Chair, OSGi Alliance<http://osgi.org> (@OSGiAlliance)
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________
OSGi Developer Mail List
[email protected]<mailto:[email protected]>
https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev