Many libraries provide pluggable architectures via Service Provider Interfaces (SPI). Using such libraries usually requires some manual setup in the application package.
Libraries for pluggable frameworks rely on loading classes dynamically at runtime,
usually via Class.forName("…")
.
If the package of the class that is loaded is not imported by our user bundle,
this will result in the following error:
java.lang.ClassNotFoundException: com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi not found by my-bundle [29]
at
org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532)
The example above is from using the
Image I/O framework.
In this case, notice that the missing class is from a com.sun
package,
which is available in the SDK.
The ClassNotFoundException
means that the bundle is not importing the package.
The bundle-plugin will usually not have added an import
since the class is only referred to from a string in a Class.forName("…")
statement.
Hence, add an explicit importPackage
in the bundle's pom.xml:
<build>
<plugins>
<plugin>
<groupId>com.yahoo.vespa</groupId>
<artifactId>bundle-plugin</artifactId>
...
<configuration>
<importPackage>com.sun.imageio.plugins.jpeg</importPackage>
...
</configuration>
</plugin>
</plugins>
</build>
The importPackage
configuration option takes a comma-separated list of packages.
Adding multiple importPackage
elements in pom.xml means that only one of them will take effect.
As mentioned, the missing package in this example is part of the SDK.
In these cases, we must tell the Container to export the missing package.
When running in cluster mode,
this is done in services.xml
:
<container version="1.0"> <config name="search.config.qr-start"> <jdisc> <export_packages>com.sun.imageio.plugins.jpeg</export_packages> </jdisc> </config> ... </container>