Later versions of Liferay are using OSGi Core R7, and this can impact Java package imports...
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.
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.
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...
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.
2. Add a new directive to the bnd.bnd file...
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.
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.
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


