Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Register Db2 resource bundle classes for reflection #46491

Merged
merged 1 commit into from
Feb 26, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package io.quarkus.jdbc.db2.deployment;

import java.util.ListResourceBundle;
import java.util.ResourceBundle;

import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;

import com.ibm.db2.jcc.resources.ResourceKeys;
import com.ibm.db2.jcc.resources.Resources;
import com.ibm.db2.jcc.resources.SqljResources;
Expand All @@ -21,13 +27,17 @@
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.AdditionalIndexedClassesBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
import io.quarkus.deployment.builditem.NativeImageEnableAllCharsetsBuildItem;
import io.quarkus.deployment.builditem.SslNativeConfigBuildItem;
import io.quarkus.deployment.builditem.nativeimage.JPMSExportBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageAllowIncompleteClasspathBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageConfigBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.jdbc.db2.runtime.DB2AgroalConnectionConfigurer;
Expand All @@ -36,12 +46,23 @@
public class JDBCDB2Processor {

private static final String DB2_DRIVER_CLASS = "com.ibm.db2.jcc.DB2Driver";
private static final DotName RESOURCE_BUNDLE_DOT_NAME = DotName.createSimple(ResourceBundle.class);
private static final DotName LIST_RESOURCE_BUNDLE_DOT_NAME = DotName.createSimple(ListResourceBundle.class);
private static final String DB2_DRIVER_ROOT_PACKAGE = "com.ibm.db2";

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(Feature.JDBC_DB2);
}

@BuildStep
void indexDriver(BuildProducer<IndexDependencyBuildItem> indexDependencies,
BuildProducer<AdditionalIndexedClassesBuildItem> additionalIndexedClasses) {
indexDependencies.produce(new IndexDependencyBuildItem("com.ibm.db2", "jcc"));
additionalIndexedClasses.produce(new AdditionalIndexedClassesBuildItem(RESOURCE_BUNDLE_DOT_NAME.toString(),
LIST_RESOURCE_BUNDLE_DOT_NAME.toString()));
}

@BuildStep
void registerDriver(BuildProducer<JdbcDriverBuildItem> jdbcDriver,
SslNativeConfigBuildItem sslNativeConfigBuildItem) {
Expand All @@ -67,8 +88,7 @@ void configureAgroalConnection(BuildProducer<AdditionalBeanBuildItem> additional
}

@BuildStep
void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<NativeImageResourceBuildItem> resource) {
void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
//Not strictly necessary when using Agroal, as it also registers
//any JDBC driver being configured explicitly through its configuration.
//We register it for the sake of people not using Agroal,
Expand All @@ -92,10 +112,25 @@ void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflectiveCla
.build());

reflectiveClass.produce(ReflectiveClassBuildItem.builder("com.ibm.pdq.cmx.client.DataSourceFactory")
.reason(getClass().getName() + " accessed reflectively by DB2 JDBC driver")
.reason(getClass().getName() + " accessed reflectively by Db2 JDBC driver")
.build());
}

@BuildStep
void registerResources(CombinedIndexBuildItem index,
BuildProducer<NativeImageResourceBuildItem> resource,
BuildProducer<NativeImageResourceBundleBuildItem> resourceBundle) {
resource.produce(new NativeImageResourceBuildItem("pdq.properties"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gsmet how did you come to the conclusion that this is not needed anymore?

I added this registration quite recently in #45527, without it Graal complains about a missing registration when using -H:ThrowMissingRegistrationErrors=

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, well, I had a look at the jar. But maybe they are actually checking for it as an app resource.

Will drop this commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirmed it's still needed:

com.oracle.svm.core.jdk.resources.MissingResourceRegistrationError: The program tried to access the resource at path

   pdq.properties

without it being registered as reachable. Add it to the resource metadata to solve this problem. See https://www.graalvm.org/latest/reference-manual/native-image/metadata/#resources-and-resource-bundles for help
  [email protected]/java.lang.ClassLoader.getResource(ClassLoader.java:1415)
  com.ibm.db2.jcc.am.ao.b(ao.java:3175)
  com.ibm.db2.jcc.DB2BaseDataSource.initializeDataSourceProxy(DB2BaseDataSource.java:14413)
  com.ibm.db2.jcc.DB2SimpleDataSource.<init>(DB2SimpleDataSource.java:178)
  com.ibm.db2.jcc.DB2Driver.getDataSource(DB2Driver.java:1049)
  com.ibm.db2.jcc.DB2Driver.connect(DB2Driver.java:435)
  com.ibm.db2.jcc.DB2Driver.connect(DB2Driver.java:117)
  io.agroal.pool.ConnectionFactory.createConnection(ConnectionFactory.java:225)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, well, I had a look at the jar. But maybe they are actually checking for it as an app resource.

Yes despite it not being present, if the code tries to access it we need to register it.

resource.produce(new NativeImageResourceBuildItem("com/ibm/db2/cmx/runtime/internal/resources/messages.properties"));

// we need to register for reflection all the classes of the driver that are ResourceBundles
for (ClassInfo bundle : index.getIndex().getAllKnownSubclasses(RESOURCE_BUNDLE_DOT_NAME)) {
if (!bundle.name().toString().startsWith(DB2_DRIVER_ROOT_PACKAGE)) {
continue;
}

resourceBundle.produce(new NativeImageResourceBundleBuildItem(bundle.name().toString()));
}
}

@BuildStep
Expand Down
Loading