You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Karl Pauls (JIRA)" <ji...@apache.org> on 2017/11/22 09:28:00 UTC

[jira] [Comment Edited] (FELIX-5749) Allow to use components that depend on optional imports

    [ https://issues.apache.org/jira/browse/FELIX-5749?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16262203#comment-16262203 ] 

Karl Pauls edited comment on FELIX-5749 at 11/22/17 9:27 AM:
-------------------------------------------------------------

I guess I might not understand the problem correctly but I don't even see why there is a problem at all. If you have an optional dependency on a service coupled with an optional dependency on the interface of that service you have to handle _both_ correctly (i.e., as _optional_). 

In the case of the service you have to check if it is there or not and in the case of the interface you have to do the same. I would assume that SCR supports this case already - so it really is just handling it correctly in the bundle, no?

In other words, I would assume the following to be supported by SCR (and I used that in the past so it must have been working at one point): 


{code:java}
@Reference(service=test.Foo.class)
private volatile Object optionalService;

@Activate
void doSomething() {
    try {
        if (copy != null) ((Foo) copy).bar();
    } catch (NoClassDefFoundError e) {// Ignore, package not around }
}
{code}



was (Author: karlpauls):
I guess I might not understand the problem correctly but I don't even see why there is a problem at all. If you have an optional dependency on a service coupled with an optional dependency on the interface of that service you have to handle _both_ correctly (i.e., as _optional_). 

In the case of the service you have to check if it is there or not and in the case of the interface you have to do the same. I would assume that SCR supports this case already - so it really is just handling it correctly in the bundle, no?

In other words, I would assume the following to be supported by SCR (and I used that in the past so it must have been working at one point): 

@Reference(service=test.Foo.class)
private volatile Object optionalService;

@Activate
void doSomething() {
    try {
        if (copy != null) ((Foo) copy).bar();
   } catch (NoClassDefFound e) {// Ignore, package not around }
}

> Allow to use components that depend on optional imports
> -------------------------------------------------------
>
>                 Key: FELIX-5749
>                 URL: https://issues.apache.org/jira/browse/FELIX-5749
>             Project: Felix
>          Issue Type: New Feature
>    Affects Versions: scr-2.0.12
>            Reporter: Christian Schneider
>
> When desigining the scope of a bundle you sometimes have an optional part that could be externalized into its own bundle but you decide to keep it in your bundle to limit the number of bundles. In this case you have to use an optional import and make sure the code that depends on this import only runs when this import is wired. This code is often quite awkward and often also buggy.
> We discussed on osgi-dev that you can make such code a lot simpler to write by using DS. 
> This is how the code would look like:
> You externalize the code that depends on the optional import into one or more components. These components offer a service interface that is not dependent on the optional import. Inside the component you can work freely with the optional packages. You have to make sure this component is disabled by default. Then you write a "starter" component that enables the component if the package is available.
> I think scr could support such "optional" components without the disabled trick. We could load the component class and if it fails disable the component. If it works we enable it. 
> So if the package is wired later and we get a refresh this approach would activate the component without any additional effort from the developer side.
> ----
> Below I am copying a snippet from Ray that details what they did.
> Given your component which has the optional import package (doesn't matter how it's used):
> import com.liferay.demo.foo.Foo; // The optional package
> @Component(
>     enabled = false // disable by default so DS ignores it
> )
> public class OptionalPackageConsumer implements Foo {...}
> Make sure the component is disabled by default. This will prevent SCR from classloading the component class.
> Second, you construct a "starter" component who's job it is to check for the available package:
> @Component
> public class OptionalPackageConsumerStarter {
>    @Activate
>     void activate(ComponentContext componentContext) {
>         try {
>             Class.forName(com.liferay.demo.foo.Foo.class.getName());
>             componentContext.enableComponent(OptionalPackageConsumer.class.getName());
>         }
>         catch (Throwable t) {
>             _log.warn("Could not find {}", t.getMessage());
>         }
>     }
> }



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)