How to create a quarkus uber-jar with a custom shading or configuration?

1,095 views
Skip to first unread message

Mario Fusco

unread,
Jul 6, 2021, 6:31:36 AM7/6/21
to quark...@googlegroups.com
Hi all,

Premise: Drools, that as you know is internally used by Kogito, is made of many (optional) modules and the biggest part of them contains a file called META-INF/kie.conf describing all the services provided by that module. When it is necessary to create an uber-jar, the content of all the kie.conf files included in the drools modules required by the user's project have to be concatenated into a single file and to this purpose we suggest to use the maven-shade-plugin as for instance documented here.

My problem is that I couldn't find a way to make the shade-plugin to integrate or cooperate in any way with the Quarkus way of creating an uber-jar. In fact without the shade-plugin and using the application property

  quarkus.package.type=uber-jar

Quarkus creates a jar that, as expected, contains a kie.conf file that is randomly picked among the many ones available in the many imported Drools modules. Adding the shade-plugin doesn't help because doing so the jar packaging fails with an error like the following:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:3.2.0:shade (default) on project optaplanner-solver-factory-issue: Failed to create shaded artifact, project main artifact does not exist. -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:3.2.0:shade (default) on project optaplanner-solver-factory-issue: Failed to create shaded artifact, project main artifact does not exist.
[ERROR] The project main artifact does not exist. This could have the following
[ERROR] reasons:
[ERROR] - You have invoked the goal directly from the command line. This is not
[ERROR]   supported. Please add the goal to the default lifecycle via an
[ERROR]   <execution> element in your POM and use "mvn package" to have it run.
[ERROR] - You have bound the goal to a lifecycle phase before "package". Please
[ERROR]   remove this binding from your POM such that the goal will be run in
[ERROR]   the proper phase.
[ERROR] - You removed the configuration of the maven-jar-plugin that produces the main artifact.

I believe that what's happening in this case is that Quarkus runs before the shading, replacing the actual jar with the -runner one so that the shading-plugin is no longer able to find the jar to be shaded. Unfrotunately the shade-plugin doesn't allow to specify a different name for the jar to be shaded. I also tried to change the name of the uber-jar produced by Quarkus as explained here, to restore the name expected by the shade-plugin, but Quarkus always appends (a bit arbitrarily imo) the -runner suffix to the name of the requested file name. 

Finally, in a desperate attempt to make this work, I manually created the concatenated META-INF/kie.conf file and added it to the user project, but still the Quarkus uber-jar creation process is ignoring it and randomly picking one from the imported Drools modules. This very likely implies that even if I had a way to make Kogito to programmatically generate that concatenated conf file it would be still very possible for Quakrus to ignore it and take a different one.

Can you suggest any other workaround to solve this problem? More in general is there any plan to make the Quarkus uber-jar creation a bit more flexible/configurable and cover similar use cases?

Thanks for help,
Mario

Alexey Loubyansky

unread,
Jul 6, 2021, 8:11:06 AM7/6/21
to Mario Fusco, Quarkus Development mailing list
Have you tried using Quarkus build items for that?
E.g. PackageTypeBuildItem or PackageConfig can be used to check whether the package type is the uber-jar. If it's the uber-jar you could try producing the following build items:
1) UberJarIgnoredResourceBuildItem could be used to filter out resources (e.g. the META-INF/kie.conf files) during the packaging phase;
2) GeneratedResourceBuildItem representing the merged META-INF/kie.conf file (which you could generated by looking for 'META-INF/kie.conf' on the classpath or iterating through the runtime dependencies CurateOutcomeBuildItem.getEffectiveAppModel().getUserDependencies()).

--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/quarkus-dev/CALO%3D_Z6YcwY9RDeje3OCFa11BMyScZ9J1OVtJ9G94utKpOiHqA%40mail.gmail.com.

Alexey Loubyansky

unread,
Jul 6, 2021, 8:14:46 AM7/6/21
to Mario Fusco, Quarkus Development mailing list
On Tue, Jul 6, 2021 at 2:10 PM Alexey Loubyansky <alexey.l...@redhat.com> wrote:
Have you tried using Quarkus build items for that?
E.g. PackageTypeBuildItem or PackageConfig can be used to check whether the package type is the uber-jar. If it's the uber-jar you could try producing the following build items:
1) UberJarIgnoredResourceBuildItem could be used to filter out resources (e.g. the META-INF/kie.conf files) during the packaging phase;
2) GeneratedResourceBuildItem representing the merged META-INF/kie.conf file (which you could generated by looking for 'META-INF/kie.conf' on the classpath or iterating through the runtime dependencies CurateOutcomeBuildItem.getEffectiveAppModel().getUserDependencies()).

It may look confusing to ignore and generate the same path (META-INF/kie.conf) at the same time but it looks like it should work.

Alexey Loubyansky

unread,
Jul 6, 2021, 8:17:38 AM7/6/21
to Mario Fusco, Quarkus Development mailing list
There is actually code performing concatenation already for a couple of known resources. But it's not configurable at this point. It makes sense to expose a config for it so you could simply produce something like ConcatenateResourcesBuildItem("META-INF/kie.conf") in case the packaging type is uber-jar.

George Gastaldi

unread,
Jul 6, 2021, 8:30:16 AM7/6/21
to Alexey Loubyansky, Mario Fusco, Quarkus Development mailing list
The solution is to produce a GeneratedResourceBuildItem or a UberJarMergedResourceBuildItem in your extension.


Alexey Loubyansky

unread,
Jul 6, 2021, 8:33:23 AM7/6/21
to George Gastaldi, Mario Fusco, Quarkus Development mailing list
Oh, it is configurable, nice.

Mario Fusco

unread,
Jul 6, 2021, 9:02:12 AM7/6/21
to Alexey Loubyansky, George Gastaldi, Quarkus Development mailing list
Thanks a lot for your suggestions Alexey and George.

I wasn't aware of that UberJarMergedResourceBuildItem, I'll try to use it in the kogito extension and keep you updated.

Thanks again,
Mario

George Gastaldi

unread,
Jul 6, 2021, 9:05:43 AM7/6/21
to Mario Fusco, Alexey Loubyansky, Quarkus Development mailing list
You're welcome!

For the record, use UberJarMergedResourceBuildItem if the target file can be concatenated (like a properties file), otherwise use GeneratedResourceBuildItem
Reply all
Reply to author
Forward
0 new messages