This website uses cookies to ensure you get the best experience. Learn More.
Just a quick one today...
A community member reported getting an exception during module deployment:
INFO [com.liferay.portal.kernel.deploy.auto.AutoDeployScanner][AutoDeployDir:238] Processing com.liferay.report.jar ERROR [fileinstall-directory-watcher][DirectoryWatcher:1195] Unable to start bundle: file:/D:/worksp/liferay-ce-portal-7.4.3.8-ga8/osgi/modules/com.liferay.report.jar com.liferay.portal.kernel.log.LogSanitizerException: org.osgi.framework.BundleException: Could not resolve module: com.liferay.report [1555]_ Unresolved requirement: Import-Package: java.util.Map_ [Sanitized] at org.eclipse.osgi.container.Module.start(Module.java:444) ~[org.eclipse.osgi.jar:?] at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:428) ~[org.eclipse.osgi.jar:?] at com.liferay.portal.file.install.internal.DirectoryWatcher. _startBundle(DirectoryWatcher.java:1178) [bundleFile:?] at com.liferay.portal.file.install.internal.DirectoryWatcher. _startBundles(DirectoryWatcher.java:1211) [bundleFile:?] at com.liferay.portal.file.install.internal.DirectoryWatcher. _startAllBundles(DirectoryWatcher.java:1156) [bundleFile:?] at com.liferay.portal.file.install.internal.DirectoryWatcher. _process(DirectoryWatcher.java:1068) [bundleFile:?] at com.liferay.portal.file.install.internal.DirectoryWatcher. run(DirectoryWatcher.java:250) [bundleFile:?]
Although a lot is in this error, the important part is the Unresolved requirement: Import-Package: java.util.Map portion.
Unresolved requirement: Import-Package: java.util.Map
Kind of weird, right? The module is failing because it cannot find the java.util.Map package. Obviously, because Map is a class, not a package.
java.util.Map
Map
So the question was how was the code referencing Map such that BND was considering it to be a package?
Long story short, they were importing java.util.Map.Entry in a JSP file. In this form, BND was interpreting Map as part of the package and Entry was the class...
java.util.Map.Entry
Entry
So there were two solutions to this problem:
1. Change the import. When you import java.util.Map, you will automatically get the Entry class, although in some cases you may need to refer to it as Map.Entry. Not a big deal, super easy to change and use in this way.
Map.Entry
2. Add a new directive to the bnd.bnd file...
bnd.bnd
So this second option I didn't know about until I talked to my friend Ray Auge...
In later versions of Liferay, OSGi Core R7 is used, and there was a change to BND to start including Java packages in the Import-Package declaration. This change would allow for identifying cases where a Java package is being used but maybe not available in the Java runtime. Consider, for example, a Java 11 module that uses classes from the java.lang.module package; by adding java.lang.module to the Import-Package declaration, the module would be flagged by OSGi in an environment where the java.lang.module package was not available.
Import-Package
java.lang.module
So while this might be good generally, it is probably not a problem that we as Liferay developers will contend with...
And besides, if importing java.util.Map.Entry causes us some deployment headaches, this feature may not be worth it...
Fortunately for us, there is a new BND directive that you can add into your bnd.bnd file: -noimportjava: true This directive will have BND exclude any java.* imports in the Import-Package declaration.
-noimportjava: true
java.*
By adding this directive, the community member can continue to import java.util.Map.Entry and leave the rest of the code unchanged (may be necessary in cases where you might not be able to change the code for one reason or another).
In fact, there is no harm to adding the -noimportjava: true directive to all of your bnd.bnd files, so feel free to do so.
You can read more about the -noimportjava directive here: https://bnd.bndtools.org/instructions/noimportjava.html
-noimportjava