When developing Liferay DXP modules, you can declare optional dependencies. An optional dependency is one your module can use if it’s available, but can still function without it.
If you decide that your module requires an optional dependency, follow these steps to add it:
-
Declare the package that your module optionally requires as an optional dependency in your module’s
bnd.bnd
file:Import-Package: com.liferay.demo.foo;resolution:="optional"
Note that you can use either an optional or dynamic import. The differences are explained in this blog post.
-
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 act as a controller of the first component. The second component checks the classloader for the optional class on the classpath. It handles both cases appropriately. 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).
As above, 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 Liferay DXP’s Gogo shell with this command:
equinox:refresh [bundle ID]
For more information about optional dependencies, see OSGi Enroute’s documentation.