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.
Related
I am working on creating an internal library/starter for my team that will add support for creating native images, providing all of the hints that our currently unsupported dependencies will need. I really like providing the metadata via code (using RuntimeHintsRegistrar), but there are also certain classes that need to be initialized at build time for whatever reason.
Right now I'm passing the --initialize-at-build-time and the classes to the Spring Boot Maven Plugin via the BP_NATIVE_IMAGE_BUILD_ARGUMENTS, but ideally I'd like to avoid each consuming app having to include this in their own POM's plugin configuration.
I also understand that I can go more low-level and provide the argument inside of the META-INF/native-image directory in a native-image.properties file, but I'm not sure whether that will play nice with the Spring-provided RuntimeHintsRegistrar effectively creating that underneath the covers.
What is the best way to tell native-image the classes that should be initialized at build time without each consuming app having to pass it in their own POM? Also, if I use the GraalVM tracing agent to generate hints, will those hints play nicely with the ones that RuntimeHintsRegistrar generates?
Thanks in advance!
I am creating a library using spring-boot (v2.1.6.RELEASE) as a starter project that will facilitate as base extension jar responsible for configuring and starting up some of the components based on client project properties file.
The issue I am facing is that if the client project's SpringBoot Application class contains the same package path as library everything works like charm! but when client project contains different package path and includes ComponentScan, it is not able to load or start components from the library.
Did anyone encounter this issue? how to make client application to auto-configure some of the components from library jar?
Note: I am following the library creation example from here: https://www.baeldung.com/spring-boot-custom-starter
There are many things that can go wrong here, without seeing relevant parts of actual code its hard to tell something concrete. Out of my head, here are a couple of points for consideration that can hopefully lead to the solution:
Since we use starters in our applications (and sometimes people use explicit component scanning in there spring applications) and this obviously works, probably the issue is with the starter module itself. Don't think that the fact that the component scan is used alone prevents the starter from being loaded ;)
Make sure the starter is a: regular library and not packaged as a spring boot application (read you don't use spring boot plugin) and have <packaging>jar</packaging> in your pom.xml or whatever you use to build.
Make sure you have: src/main/resources/META-INF/spring.factories file
(case sensitive and everything)
Make sure that this spring.factories file indeed contains a valid reference on your configuration (java class annotated with #Configuration). If you use component scanning in the same package, it will find and load this configuration even without spring factories, in this case, its just kind of another portion of your code just packaged as a separate jar. So this looks especially "suspicious" to me.
Make sure that #Configuration doesn't have #Conditional-something - maybe this condition is not obeyed and the configuration doesn't start. For debugging purposes maybe you even should remove these #Conditional annotations just to ensure that the Configuration starts. You can also provide some logging inside the #Configuration class, like: "loading my cool library".
I created my project by using S/4HANA SDK (spring boot archetype), now I need the functionality to provision some ODATA services so I also introduce the dependency com.sap.cloud.servicesdk.provodatav4 to my project and then create metadata file and odata service implementation class. However, after packaging my project into jar file and run it, I get null pointer exception from the class com.sap.cloud.sdk.service.prov.v4.rt.core.web.ODataApplicationInitializer. After seeing the source code of this class, it seems it use "File" object to get metadata file from classpath, but this way doesn't work in a jar file. My question is: does it mean I have to change the packaging way to "war" in order to use this SDK for odata service development? Thanks very much.
The unfortunate answer is that, as of today, the Service SDK (not the S/4HANA Cloud SDK) is only compatible with pure Tomcat environments and assumes the Servlet standard as well as surrounding mechanisms as the default mean. The reasons for this is that the Service SDK is an integral part (the runtime) of the SAP Cloud Application Programming Model which is self-contained and may not be combined with arbitrary frameworks such as Spring Boot.
Adding to Philipp's answer that this is not supported, you may be able to use the traditional deployment here. However, since this is likely not supported officially, I would encourage to consider an alternative approach.
My project has a set of custom defined annotations that could be present in any bundle deployed in the OSGi 4.3 framework. I want to find any class with these annotations in the classpath. I tried using BundleWiring.listResources(...) and Bundle.loadClass(...) for each class found. I have done some tests with an small set of bundles and it needs almost 200MB of Permanent Generation JVM memory space because all classes are loaded.
Is there a way to free loaded classes PermGen memory space when the program realizes that they does not have these annotations?
Is there a better way to look for annotated classes in an OSGi framework?
I think you should not do annotation scanning as it slows down startup and needs a lot of memory. JEE application servers do annotation scanning at startup to make lazy programmers happy and the result is very annoying (e.g. scan for JPA or EJB annotations).
I guess you are implementing a technology where you can define the rules. I suggest that you should define rules that are similar to these:
Annotate your class
Have a MANIFEST header where the annotated class must be listed.
An even better solution can be to use a custom capability namespace with specified attributes. E.g.:
Provide-Capability: myNamespace;classes=com.foo.myClass1,com.foo.myClass2
In your technology, you should write a BundleTracker that calls:
BundleWiring.getCapabilities("myNamespace");
If the namespace is present, you can find the classes that should be processed.
If you implemented the technology, you can consider an extension to Bnd to fill that MANIFEST header automatically. That extension can be used than when bnd is started from the command line or from build tools like maven.
Btw.: You can use ASM to parse the class bytecode or use the built in possibility of Java to build up AST. Although those could work to solve the memory issue, I still think that you should define the list of classes directly in the MANIFEST header as it makes things much more clear. You can read the MANIFEST headers, you can check the capabilities on webconsole but you cannot do the same with bytecode.
Usually, classpath scanning for annotations is a bad idea in an OSGi context, as the classpath is more like a graph. However, there are situations where this can be useful. Hence, OSGi encourages the usage of the Whiteboard Pattern.
What you could possibly do is register each of these classes as services in the OSGi registry. Then, create a separate bundle that just tracks these services and transforms/manipulates them in some way. For example, this project scans for all classes annotated with #Path and #Provider annotations, and transforms them into Jersey REST APIs.
Grails has amazing validation; is it possible to use it independent of the Grails framework?
We have a Java/Groovy Camel-based web application we can't convert to a Grails application. I'd love to use the Grails-style validation with the declarative constraints but have been unable to successfully configure the application to work with Grails libraries without converting the whole thing.
The validation provided by Grails is just a wrapper around Spring's bean validation framework. Since Grails is open source you can take a look at how it's done and adapt it to your own needs. The best place to start looking is the GrailsDomainClassValidator and DomainClassGrailsPlugin to get an idea of how it's done. Another point of interest would be the #Validateable AST annotation.
As far as I know, and from what I can see in the source, there isn't a stand alone way to do this outside of a Grails project without writing your own adaptation/implementation.
You can use a external validation without problem. It is possible, for example, using a external "jar" (that do a validation) file on the "lib" folder of your Grails project. Through this way, you can use the API of this jar file. It's a simple way that you can use.