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:
-
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.
-
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 {...}
-
Create a second component to be a controller for the first. The second component checks the class loader 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 class loader 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 DXP’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]