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
GenerateSqlObject in graalvm got NullPointerException #2474
Comments
Hi @esotericman , no, there should not be special settings needed to make this work. This looks like a bug either in Jdbi or in Graal (probably jdbi until indicated otherwise). What version of Graal do you use? Is it easy to set up a self contained test case to show the problem? I have prepared a branch with additional diagnostics: Could you run your test against a jdbi snapshot with these changes, and report back with the error message? |
Thanks @stevenschlansker , I tried your snapshot. {
"name":"org.flmelody.dao.ShortUrlRepository",
"queryAllPublicConstructors":true,
"queryAllDeclaredMethods" : true,
"queryAllPublicMethods" : true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"org.flmelody.dao.ShortUrlRepositoryImpl",
"queryAllPublicConstructors":true,
"queryAllDeclaredMethods" : true,
"queryAllPublicMethods" : true,
"methods":[{"name":"<init>","parameterTypes":["org.jdbi.v3.core.extension.ExtensionMetadata","org.jdbi.v3.core.extension.HandleSupplier","org.jdbi.v3.core.config.ConfigRegistry"] }]
} And another method return a List about ShortUrl, I also add this {
"name":"org.flmelody.model.ShortUrl",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Integer","java.lang.String","java.lang.String"] }]
} In addition, This Class is also needed {
"name":"org.jdbi.v3.sqlobject.config.internal.RegisterConstructorMapperImpl",
"methods":[{"name":"<init>","parameterTypes":["java.lang.annotation.Annotation"] }]
} After add those lines ,It works now. But a bit complex if there are too many repositories |
Ok, so this sounds similar to #2475. Would it work if the SqlObject generator that writes the implementation class, also writes out a |
Yes |
We can try to implement this, but have to fix 2475 first. |
The point of the generator is to not require this. If it does, I broke something during the refactoring and it needs to be fixed. Would it be possible to slim down the reflect-config.json above? It would be great to know exactly what is needed. It looks to me it might some sort of constructor lookup. |
I see two problems:
Changing getGeneratedClass and getOnDemandClass in private static MethodHandleHolder<?> getGeneratedClass(Class<?> extensionType) {
try {
var generatedClass = Class.forName(getGeneratedClassName(extensionType)); // dynamic lookup of implementation class
var classConstructor = generatedClass.getDeclaredConstructor(EXTENSION_TYPES); // create instance using the class found.
var methodHandle = MethodHandles.lookup().unreflectConstructor(classConstructor);
var constructorHandle = methodHandle.asType(methodHandle.type().changeReturnType(Object.class));
return invoker -> {
try {
return invoker.createInstance(constructorHandle);
} catch (Throwable t) {
throw throwAnyway(t);
}
};
} catch (Throwable t) {
throw new UnableToCreateSqlObjectException(t);
}
}
private static MethodHandleHolder<?> getOnDemandClass(Class<?> extensionType) {
try {
var generatedClass = Class.forName(getOnDemandClassName(extensionType));
var classConstructor = generatedClass.getDeclaredConstructor(ON_DEMAND_TYPES);
var methodHandle = MethodHandles.lookup().unreflectConstructor(classConstructor);
var constructorHandle = methodHandle.asType(methodHandle.type().changeReturnType(Object.class));
return invoker -> {
try {
return invoker.createInstance(constructorHandle);
} catch (Throwable t) {
throw throwAnyway(t);
}
};
} catch (Throwable t) {
throw new UnableToCreateSqlObjectException(t);
}
} The first two lines in each method are most likely the problem. If you have a test project that works running under the regular JVM and crashes when compiled natively, I would be interested to try that out. Maybe we can pin this down further. |
If the reflective lookup of classes with non-constant names is a problem, we could evaluate other ways of discovering these like a |
that may work but it creates a lot of ceremony. Users now have to create a serviceloader entry with the right file name (which is currently hidden away from them) and they also need to add this in the future to their module-info.java |
so spending a bit of time on this issue, it seems that this is a bit more fundamental. Any native app must declare all of its pieces where it needs reflection so that it ultimately creates a reflection-config.json. e.g. in the example above, there are notes needed for the dao, its implementation but also for the data object itself and when we are using some of the mappers. Other systems such as quarkus use an annotation for that and have a build step processor that collects the information from the build and writes the config files. see https://quarkus.io/guides/writing-native-applications-tips for an example. I don't think that any generic "this is how we declare reflection needed for native" framework exists yet. We could roll our own annotation and then provide meta-annotation processors e.g. for quarkus, spring-aot or other frameworks. as dropwizard as one of the primary consumers of Jdbi has no real ambition to move to native (dropwizard/dropwizard#2974), we may be stuck rolling our own thing for now and provide glue. |
I was of course imagining the annotation processor would generate the necessary service loader configuration. Or, it could generate the needed reflection-config.json. No need for a generic solution; we're already writing a code generator. |
I use jdbi with version 3.40.0,As the document says:
Jdbi provides an annotation processor that creates java implementations of extension types. In addition, it provides an extension factory which does not use proxy objects and returns these as extension type implementations. Calling a method on the extension type will invoke the methods on the generated classes directly.
Here is the generated code
While executing like this
error occurs
With java -jar file ,It works without any problems.May I missed special settings?
The text was updated successfully, but these errors were encountered: