How to use the Quarkus Runtime Class Loader - runtime

I need to dynamically load class or jar files into our Quarkus project at runtime. We are using GraalVM and native images in our project.
I have found the Runtime Class Loader implementation. But I didn't find any example or detailed information about how to use this.
How to use this class loader and load jars/class files at runtime (within Quarkus + native images)? Or is there any documentation about it somewhere?

Related

Quarkus Extension - Remove a class from dependent library or replace part of a class

Within a custom Quarkus extension I would like to integrate an existing java library that currently is not compatible to Quarkus.
Are there any examples for the following use cases:
remove a java class from a dependency library (library is referenced as maven-dependency)- In this case I'll provide a compatible implementation within the runtime-module.
replace specific parts of an existing class form a dependency library (e.g. a default implementation of an interface)
Thanks, Thomas
For the first case, you can use a io.quarkus.deployment.builditem.RemovedResourceBuildItem to have Quarkus essentially remove a class from a dependency.
For the second case, you'll likely need to use a io.quarkus.deployment.builditem.BytecodeTransformerBuildItem which lets you declare an ASM class transformer which can change a class in arbitrary ways.
If you are only looking to change the class for native mode, it's much easier to instead use com.oracle.svm.core.annotate.TargetClass and com.oracle.svm.core.annotate.Substitute.

How do I include components, scanned from a Spring library, into the main application consuming that library?

We are building a Spring-based Java library that has several #Autowired assignments, which pick up #Bean instances from the library path, detected at runtime.
That works great when we test the application directly (with an #SpringBootApplication in the library)
However when we include the library as a dependency in other projects, it does not do the component scan of the library classes, and so the #Autowired injections never happen.
Of course we could tell the application developers to add the library path to their component scan, but that would lead to questions, errors, and frustration.
How can we tell Spring to do a component scan of the library classes, without explicitly including the scan base in the consumer applications?
You could create a configuration in your library which defines the components the library needs. This answer shows something like that.
Another way would be to create your own autoconfiguration. This article in the spring documentation describes how it is working.

external dependencies need an extension?

It's not clear for me if I'd like to add some jars to my projects should I make an extension for each one ?
Just read https://itnext.io/should-you-switch-to-quarkus-4b89eedfe5fe and it says gson is slower cause there's no extension and I guess maybe it was not compiled to native as it uses reflection
You can use any dependencies inside your application as with other frameworks, an extension allow a technology to be integrated into Quarkus (injection via CDI bean, configuration via application.properties, native image support, ...) but it's not mandatory.
Or course, if you use a dependency not integrated as an extension, you cannot be sure that it will works in native, so be careful if you deploy your application as a native image some steps would need to be done.
In the article you cited, the issue is on native executables, and it shows that JSON-B outperforme GSON in this situation on this particular test, not that it uses a custom serialization (not the serialization provided by Quarkus via its extensions).
You can also note that the exemple didn't reuse the Gson object so it may be the cause of the slowness, by creating a Gson object on each request it will allocate a lot and the GC included inside SubstraatVM is not the same as the one in JVM mode (as with other optimizaton).
My point of view is that an extension will not impact the runtime performance of a dependency.

Can java.util.ServiceLoader find the new jars added to the classpath without restart?

I have a java application which is implemented to find providers of an interface using java.util.serviceLoader. When I a add a new provider jar at runtime to the classpath of the application the application is not finding it. If I restart the application the application finds the provider jar. Are there any options for java application to find the provider jar at runtime as I think that is what java serviceLoader is supposed to do.
I am following the instructions in this page.
http://cr.openjdk.java.net/~mr/jigsaw/spec/api/java/util/ServiceLoader.html
Deploying service providers on the class path
Explanation can be found here Creating Extensible Applications (at the end of the tutorial):
Limitations of the ServiceLoader API
The ServiceLoader API is useful, but it has limitations. For example, it is impossible to derive a class from the ServiceLoader class, so you cannot modify its behavior. You can use custom ClassLoader subclasses to change how classes are found, but ServiceLoader itself cannot be extended. Also, the current ServiceLoader class cannot tell your application when new providers are available at runtime. Additionally, you cannot add change-listeners to the loader to find out whether a new provider was placed into an application-specific extension directory.
Seems to apply to Java 8. Don't know if this has changed in the later editions.

ActiveJDBC Instrumentation: Unable to instrument the model classes which are in Jar

I am using activejdbc 1.4.9. I created one jar (using maven) which has two ActiveJDBC Model Classes. I added the jar to the application. Application has three more model classes. When I compile and try to run the application (gradle based), activejdbc is instrumenting only 3 classes which are in application but not instrumenting the classes which are in jar. When I try to write the data into the two models which are in jar, It is throwing exception as
org.javalite.activejdbc.DBException: Failed to retrieve metadata from DB. Are you sure table exists in DB ?
Now I have certain doubts. Please help me to resolve and understand few things.
How instrumentation happens ?
When we create a jar, will it include instrumented classes ?
Why it is throwing this error ?
It is throwing this error in case classes have not been instrumented. This means that before placing your model classes into a jar file, you need to instrument them. Does not matter which build method you use though. This http://javalite.io/instrumentation explains what is instrumentation and how to do it. Instrumentation does not create jars, it merely adds some byte code into your classes. In all scenarios you need:
Write code :)
Compile
Instrument
after this, you can do any of the following:
run app using class files in the file system
package class files into jar file and use that on your classpath
package jar file into a larger app (WAR, EAR, RAR, etc.) and deploy your app
making sense?

Resources