Just a quick one today...
A community member reported getting an exception during module deployment:
ERROR [fileinstall-directory-watcher][DirectoryWatcher:1195] Unable to start bundle:
org.osgi.framework.BundleException: Could not resolve module:
Unresolved requirement: Import-Package: java.util.Map_ [Sanitized]
Although a lot is in this error, the important part is
the Unresolved requirement: Import-Package:
Unresolved requirement: Import-Package:
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