Declaring Optional Import Package Requirements

When developing modules, you can declare optional dependencies. An optional dependency is one your module can use if available, but can still function without it.

If you decide that your module requires an optional dependency, follow these steps to add it:

  1. In your module’s bnd.bnd file, declare the package your module optionally depends on:

    Import-Package: com.liferay.demo.foo;resolution:="optional"
    

    Note that you can use either an optional or dynamic import. The differences are explained here.

  2. Create a component to use the optional package:

    import com.liferay.demo.foo.Foo; // A class from the optional package
    
    @Component(
        enabled = false // instruct declarative services to ignore this component by default
    )
    public class OptionalPackageConsumer implements Foo {...}
    
  3. Create a second component to be a controller for the first. The second component checks the classloader for the optional class on the classpath. If it’s not there, this means you must catch any ClassNotFoundException. For example:

    @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()); // Could use _log.info instead
            }
        }
    }
    

If the classloader check in the controller component is successful, the client component is enabled. This check is automatically performed whenever there are any wiring changes to the module containing these components (Declarative Services components are always restarted when there are wiring changes).

If you install the module when the optional dependency is missing from Liferay Portal’s OSGi runtime, your controller component catches a ClassNotFoundException and logs a warning or info message (or takes whatever other action you implement to handle this case). If you install the optional dependency, refreshing your module triggers the OSGi bundle lifecycle events that trigger your controller’s activate method and the check for the optional dependency. Since the dependency exists, your client component uses it.

Note that you can refresh a bundle from Gogo shell with this command:

equinox:refresh [bundle ID] 

Related Topics

Configuring Dependencies

0 (0 Votes)
Implementing Logging Previous