quarkus icon indicating copy to clipboard operation
quarkus copied to clipboard

How to build two distinct Quarkus runner JARs in a single Maven build (one for crypto-soft, one for crypto-hsm)

Open SnehBratJha opened this issue 1 week ago • 9 comments

I'm using Quarkus in a multi-module Maven project. I need to produce two separate Quarkus runner JARs in a single reactor build:

quarkus-service-soft-runner.jar Uber-jar (Quarkus runner) Includes only quarkus-crypto-soft (not crypto-hsm)

quarkus-service-hsm-runner.jar Uber-jar (Quarkus runner) Includes only quarkus-crypto-hsm (not crypto-soft)

Context:

The parent POM runs quarkus-maven-plugin with goals build, generate-code, generate-code-tests.

 <plugin>
 <groupId>io.quarkus</groupId>
                    <artifactId>quarkus-maven-plugin</artifactId>
                    <version>3.27.1.redhat-00001</version>
                    <extensions>true</extensions>
                    <executions>
                        <execution>
                            <goals>
                                <goal>build</goal>
                                <goal>generate-code</goal>
                                <goal>generate-code-tests</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

The service module declares dependencies including acs-quarkus-crypto-soft and acs-quarkus-crypto-hsm.

I attempted two approaches:

  1. Use two maven-assembly-plugin executions with jar-with-dependencies and dependencySet/excludes to create two fat JARs. This produced non-Quarkus runner jars which will not work .

  2. Use two Quarkus plugin executions (profiles) in the service module with finalName and quarkus.package.type uber-jar, but I hit issues: Some configurations threw “Element quarkus.package.type is not allowed here” or “Element excludes is not allowed here”. The parent plugin’s codegen (generate-code) sometimes runs before the runner jars exist, causing failures.

This is how I am implementing the second approach and then through maven build I am activating one profile and in pom I am activating the other by default. Also I have tried activating the both through maven build

    <profile>
            <id>crypto-soft</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>com.crypto</groupId>
                    <artifactId>crypto-soft</artifactId>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.quarkus</groupId>
                        <artifactId>quarkus-maven-plugin</artifactId>
                        <executions>
                            <execution>
                            <goals>
                                <goal>build</goal>
                            </goals>
                            <phase>package</phase>
                            <configuration>
                                <finalName>quarkus-service-soft-runner</finalName>
                            </configuration>
                        </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>crypto-hsm</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>com.crypto</groupId>
                    <artifactId>crypto-hsm</artifactId>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.quarkus</groupId>
                        <artifactId>quarkus-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build</goal>
                                </goals>
                                <phase>package</phase>
                                <configuration>
                                    <finalName>quarkus-service-hsm-runner</finalName>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

When I am build my module it is giving me below error

Quarkus code generation phase has failed

And if I tried something like below directly in plugin without using profile in quarkus it is doing the build twice and creating jars:

                <plugins>
                <plugin>
                                <groupId>io.quarkus</groupId>
                                <artifactId>quarkus-maven-plugin</artifactId>
                                <executions>
                                    <execution>
                                        <id>soft-war</id>
                                        <phase>package</phase>
                                        <goals>
                                            <goal>build</goal>
                                        </goals>
                                        <configuration>
                                            <finalName>quarkus-service-soft-runner</finalName>
                                        </configuration>
                                    </execution>
                                    <execution>
                                        <phase>package</phase>
                                        <id>hsm-war</id>
                                        <goals>
                                            <goal>build</goal>
                                        </goals>
                                        <configuration>
                                            <finalName>quarkus-service-hsm-runner</finalName>
                                        </configuration>
                                    </execution>
                                </executions>
                            </plugin>
                        </plugins>

In JBOSS we are using below plugin to achieve the same and now we are doing migration to Quarkus :

            <plugin>
                            <artifactId>maven-war-plugin</artifactId>
                            <executions>
                                <!-- First execution: HSM variant (default one) -->
                                <execution>
                                    <id>hsm-war</id>
                                    <phase>package</phase>
                                    <goals>
                                        <goal>war</goal>
                                    </goals>
                                    <configuration>
                                        <!-- Exclude the soft jar from this WAR -->
                                        <packagingExcludes>
                                            **/acs-crypto-soft*.jar,
                                            WEB-INF/lib/acs-crypto-soft*.jar
                                        </packagingExcludes>
                                    </configuration>
                                </execution>
            
                                <!-- Second execution: Soft variant -->
                                <execution>
                                    <id>soft-war</id>
                                    <phase>package</phase>
                                    <goals>
                                        <goal>war</goal>
                                    </goals>
                                    <configuration>
                                        <!-- This classifier will create: xxx-soft.war -->
                                        <classifier>soft</classifier>
                                        <!-- Exclude the hsm related jars from this WAR -->
                                        <packagingExcludes>
                                            **/acs-crypto-hsm*.jar,
                                            WEB-INF/lib/acs-crypto-hsm*.jar,
                                            WEB-INF/lib/crypt2pay*.jar,
                                            WEB-INF/lib/crys-hsm*.jar,
                                        </packagingExcludes>
                                    </configuration>
                                </execution>
                            </executions>
                        </plugin>

I want a single, clean, Quarkus-friendly solution that produces two runnable Quarkus Uber-Jars in one build, without requiring workarounds or changing the parent’s codegen flow.

SnehBratJha avatar Dec 09 '25 09:12 SnehBratJha

/cc @quarkusio/devtools (maven)

quarkus-bot[bot] avatar Dec 09 '25 09:12 quarkus-bot[bot]

can some one please check if they have insights on this? Let me know if you need anything from my end.

SnehBratJha avatar Dec 09 '25 18:12 SnehBratJha

There is this trick https://quarkus.io/guides/maven-tooling#maven-multi-build Not very elegant, but it's tricky to build multiple apps with different dependencies from the same module.

I guess, another approach would be to create a common parent POM with all the common dependencies and the plugin configuration in the pluginManagement. Then create two application modules inheriting from the common parent POM, adding application-specific dependencies and config.

aloubyansky avatar Dec 09 '25 20:12 aloubyansky

I think i would recommend the parent and two modules approach. While we can assemble multiple applications from the same module with slightly different dependencies, the test classpath will include all the optional dependencies, which is something to be aware of.

aloubyansky avatar Dec 09 '25 21:12 aloubyansky

I think i would recommend the parent and two modules approach. While we can assemble multiple applications from the same module with slightly different dependencies, the test classpath will include all the optional dependencies, which is something to be aware of.

Actually I need to do the two jar creation for all of my services and this is the first service which I have started so if i use this approach I need to create two modules for each of my services right?

SnehBratJha avatar Dec 10 '25 05:12 SnehBratJha

There is this trick https://quarkus.io/guides/maven-tooling#maven-multi-build Not very elegant, but it's tricky to build multiple apps with different dependencies from the same module.

I guess, another approach would be to create a common parent POM with all the common dependencies and the plugin configuration in the pluginManagement. Then create two application modules inheriting from the common parent POM, adding application-specific dependencies and config.

I tried with this approach as well but it is not filtering the jar. Both dependency is getting included in both war and Also 2 build one for each is executed. Can you please comment what is wrong with this approach.

      <dependency>
                  <groupId>com.crypto</groupId>
                  <artifactId>quarkus-crypto-soft</artifactId>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>com.crypto</groupId>
                  <artifactId>quarkus-crypto-hsm</artifactId>
                  <optional>true</optional>
              </dependency>
      
      
       <plugin>
                      <groupId>io.quarkus</groupId>
                      <artifactId>quarkus-maven-plugin</artifactId>
                      <executions>
                          <execution>
                              <id>soft-war</id>
                              <phase>package</phase>
                              <goals>
                                  <goal>build</goal>
                              </goals>
                              <configuration>
                                  <properties>
                                      <quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
                                      <quarkus.package.jar.included-optional-dependencies>com.crypto:quarkus-crypto-soft::jar</quarkus.package.jar.included-optional-dependencies>
                                      <quarkus.package.jar.type>uber-jar</quarkus.package.jar.type>
                                      <quarkus.package.output-name>quarkus-service-soft-runner</quarkus.package.output-name>
                                  </properties>
                              </configuration>
                          </execution>
                          <execution>
                              <phase>package</phase>
                              <id>hsm-war</id>
                              <goals>
                                  <goal>build</goal>
                              </goals>
                              <configuration>
                                  <properties>
                                      <quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
                                      <quarkus.package.jar.included-optional-dependencies>com.crypto:quarkus-crypto-hsm::jar</quarkus.package.jar.included-optional-dependencies>
                                      <quarkus.package.jar.type>uber-jar</quarkus.package.jar.type>
                                      <quarkus.package.output-name>quarkus-service-hsm-runner</quarkus.package.output-name>
                                  </properties>
                              </configuration>
                          </execution>
                      </executions>
                  </plugin>

SnehBratJha avatar Dec 10 '25 06:12 SnehBratJha

I'll need to look into this. We do have a test for this here https://github.com/quarkusio/quarkus/tree/main/integration-tests/maven/src/test/resources-filtered/projects/multi-build-mode

aloubyansky avatar Dec 10 '25 11:12 aloubyansky

I'll need to look into this. We do have a test for this here https://github.com/quarkusio/quarkus/tree/main/integration-tests/maven/src/test/resources-filtered/projects/multi-build-mode

I checked this URL and the example I have tried is almost the same to the above URL Whenever you get time if you can just have a look and let me know if anything is missing in the example.

Thank you

SnehBratJha avatar Dec 10 '25 12:12 SnehBratJha

@SnehBratJha could you also try adding an equivalent of

<quarkus.package.output-directory>fast-foo-quarkus-app</quarkus.package.output-directory>

to every execution?

aloubyansky avatar Dec 10 '25 13:12 aloubyansky

@SnehBratJha could you also try adding an equivalent of

<quarkus.package.output-directory>fast-foo-quarkus-app</quarkus.package.output-directory>

to every execution?

I tried this as well <quarkus.package.output-directory>post-quarkus</quarkus.package.output-directory>

Jar is created at this place but with same issue both the dependency are present. :(

SnehBratJha avatar Dec 11 '25 05:12 SnehBratJha

Just to make sure, did you configure different output directories for each application?

aloubyansky avatar Dec 11 '25 06:12 aloubyansky

Just to make sure, did you configure different output directories for each application?

Yes for both execution different output directory

    <plugin>
                    <groupId>io.quarkus</groupId>
                    <artifactId>quarkus-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>soft-war</id>
                            <phase>package</phase>
                            <goals>
                                <goal>build</goal>
                                <goal>generate-code</goal>
                                <goal>generate-code-tests</goal>
                            </goals>
                            <configuration>
                                <properties>
                                    <quarkus.package.output-directory>postgresql-quarkus</quarkus.package.output-directory>
                                    <quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
                                    <quarkus.package.jar.included-optional-dependencies>com.worldline.acs:acs-quarkus-crypto-soft::jar</quarkus.package.jar.included-optional-dependencies>
                                    <quarkus.package.output-name>acs-quarkus-authentication-service-soft-runner</quarkus.package.output-name>
                                </properties>
                            </configuration>
                        </execution>
                        <execution>
                            <phase>package</phase>
                            <id>hsm-war</id>
                            <goals>
                                <goal>build</goal>
                            </goals>
                            <configuration>
                                <properties>
                                    <quarkus.package.output-directory>post-quarkus</quarkus.package.output-directory>
                                    <quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
                                    <quarkus.package.jar.included-optional-dependencies>com.worldline.acs:acs-quarkus-crypto-hsm::jar</quarkus.package.jar.included-optional-dependencies>
                                    <quarkus.package.output-name>acs-quarkus-authentication-service-hsm-runner</quarkus.package.output-name>
                                </properties>
                            </configuration>
                        </execution>
                    </executions>
                </plugin> 

SnehBratJha avatar Dec 11 '25 06:12 SnehBratJha

@SnehBratJha it seems to work for me. I guess I'd need a reproducer to investigate it further. Here is the configuration I used to test it.

    <properties>
        <compiler-plugin.version>3.14.1</compiler-plugin.version>
        <maven.compiler.release>17</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
        <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
        <quarkus.platform.version>3.30.3</quarkus.platform.version>
        <skipITs>true</skipITs>
        <surefire-plugin.version>3.5.4</surefire-plugin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>${quarkus.platform.artifact-id}</artifactId>
                <version>${quarkus.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>commons-math</groupId>
            <artifactId>commons-math</artifactId>
            <version>1.2</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.21.0</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-junit5</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>quarkus-maven-plugin</artifactId>
                <version>${quarkus.platform.version}</version>
                <extensions>true</extensions>
                <executions>
                    <execution>
                        <id>commons-math</id>
                        <goals>
                            <goal>build</goal>
                        </goals>
                        <configuration>
                            <properties>
                                <quarkus.package.output-directory>commons-math-app</quarkus.package.output-directory>
                                <quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
                                <quarkus.package.jar.included-optional-dependencies>commons-math:commons-math</quarkus.package.jar.included-optional-dependencies>
                                <quarkus.package.jar.type>uber-jar</quarkus.package.jar.type>
                                <quarkus.package.output-name>commons-math</quarkus.package.output-name>
                            </properties>
                        </configuration>
                    </execution>
                    <execution>
                        <id>commons-io</id>
                        <goals>
                            <goal>build</goal>
                        </goals>
                        <configuration>
                            <properties>
                                <quarkus.package.output-directory>commons-io-app</quarkus.package.output-directory>
                                <quarkus.package.jar.filter-optional-dependencies>true</quarkus.package.jar.filter-optional-dependencies>
                                <quarkus.package.jar.included-optional-dependencies>commons-io:commons-io</quarkus.package.jar.included-optional-dependencies>
                                <quarkus.package.jar.type>uber-jar</quarkus.package.jar.type>
                                <quarkus.package.output-name>commons-io</quarkus.package.output-name>
                            </properties>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

aloubyansky avatar Dec 11 '25 09:12 aloubyansky

In my case those two dependency crypto hsm and crypto soft is my internal project modules. Is it possible because of that it is not working because in your example commons io and commons math are external library?

SnehBratJha avatar Dec 11 '25 11:12 SnehBratJha

No, seems to work for me.

aloubyansky avatar Dec 11 '25 15:12 aloubyansky

Might be because the dependency which I wanted to include is my project internal modules(dependency) and the one which you have used in your example are the external library(dependency). It seems this solution is not working for me I will check more on this and will post the answer if I get. Meanwhile I will be using profile to create two different jars in two different build.

SnehBratJha avatar Dec 12 '25 12:12 SnehBratJha

Might be because the dependency which I wanted to include is my project internal modules(dependency) and the one which you have used in your example are the external library(dependency).

No, I tried that. If you like you could create a reproducer for me to try.

aloubyansky avatar Dec 13 '25 07:12 aloubyansky