Skip to content
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

Quarkus dev loads maven modules after each other, ingores --projects #42750

Closed
Stwissel opened this issue Aug 25, 2024 · 13 comments
Closed

Quarkus dev loads maven modules after each other, ingores --projects #42750

Stwissel opened this issue Aug 25, 2024 · 13 comments
Labels
area/maven kind/bug Something isn't working

Comments

@Stwissel
Copy link

Describe the bug

I have a multi-module consisting of services (with their own http) and support modules, the services depend on. The reactor pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.acme</groupId>
        <artifactId>parent</artifactId>
        <relativePath>./parent</relativePath>
        <version>1.0.0-SNAPSHOT</version>
    </parent>

    <artifactId>apps</artifactId>
    <name>Application collection</name>
    <description>All backend modules as micro services</description>

    <packaging>pom</packaging>

    <modules>
        <module>library1</module>
	<module>library2</module>
        <module>service1</module>
    </modules>

</project>

service1 depends on library1 and library2. I can successfully run mvn clean package, but not quarkus dev

Expected behavior

When starting quarkus dev have the ability to specify which module to load or start them concurrently. Or the ability for Quarkus to discover the reactor project

Actual behavior

quarkus dev

only library1 gets processed, then quarkus stops

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] library1                                                           [jar]
[INFO] library2                                                           [jar]
[INFO] service1                                                           [jar]
[INFO] Application collection                                             [pom]
[INFO] 
[INFO] -------------------------< org.acme:library1 >--------------------------
[INFO] Building library1 1.0.0-SNAPSHOT                                   [1/4]
[INFO]   from library1/pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- quarkus:3.13.3:dev (default-cli) @ library1 ---
[INFO] Invoking resources:3.3.1:resources (default-resources) @ library1
[INFO] Copying 1 resource from src/main/resources to target/classes
[INFO] Invoking quarkus:3.13.3:generate-code (default) @ library1
[INFO] Invoking compiler:3.13.0:compile (default-compile) @ library1
[INFO] Nothing to compile - all classes are up to date.
[INFO] Invoking resources:3.3.1:testResources (default-testResources) @ library1
[INFO] skip non existing resourceDirectory /home/stw/Code/quarkus-trouble/library1/src/test/resources
[INFO] Invoking quarkus:3.13.3:generate-code-tests (default) @ library1
[INFO] Invoking compiler:3.13.0:testCompile (default-testCompile) @ library1
[INFO] No sources to compile
Listening for transport dt_socket at address: 5005







__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2024-08-26 03:02:41,601 INFO  [io.quarkus] (Quarkus Main Thread) library1 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.13.3) started in 0.734s. 

2024-08-26 03:02:41,603 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2024-08-26 03:02:41,604 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi]

--
Tests paused
Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

Quarkus loads the first library, then when stopping it (key q), the next module etc.

Trying to start quarkus dev from the service1 module leads to:

[INFO] Scanning for projects...
[INFO] 
[INFO] -------------------------< org.acme:service1 >--------------------------
[INFO] Building service1 1.0.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] The POM for org.acme:library1:jar:1.0.0-SNAPSHOT is missing, no dependency information available
[WARNING] The POM for org.acme:library2:jar:1.0.0-SNAPSHOT is missing, no dependency information available
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.141 s
[INFO] Finished at: 2024-08-26T03:06:50+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project service1: Could not resolve dependencies for project org.acme:service1:jar:1.0.0-SNAPSHOT
[ERROR] dependency: org.acme:library1:jar:1.0.0-SNAPSHOT (compile)
[ERROR] 	Could not find artifact org.acme:library1:jar:1.0.0-SNAPSHOT
[ERROR] dependency: org.acme:library2:jar:1.0.0-SNAPSHOT (compile)
[ERROR] 	Could not find artifact org.acme:library2:jar:1.0.0-SNAPSHOT
[ERROR] 
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

How to Reproduce?

Clone the Reproducer repo and run quarkus dev

git clone git@github.com:Stwissel/quarkus-multi-module-question.git
cd quarkus-multi-module-question
quarkus dev

Output of uname -a or ver

Linux stw-multipass 6.8.0-40-generic #40-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 5 10:34:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "21.0.4" 2024-07-16 LTS OpenJDK Runtime Environment Zulu21.36+17-CA (build 21.0.4+7-LTS) OpenJDK 64-Bit Server VM Zulu21.36+17-CA (build 21.0.4+7-LTS, mixed mode, sharing)

Quarkus version or git rev

3.13.2

Build tool (ie. output of mvnw --version or gradlew --version)

Maven home: /home/stw/.sdkman/candidates/maven/current Java version: 21.0.4, vendor: Azul Systems, Inc., runtime: /home/stw/.sdkman/candidates/java/21.0.4-zulu Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "6.8.0-40-generic", arch: "amd64", family: "unix"

Additional information

No response

@Stwissel Stwissel added the kind/bug Something isn't working label Aug 25, 2024
Copy link

quarkus-bot bot commented Aug 25, 2024

/cc @quarkusio/devtools (maven)

@Stwissel Stwissel changed the title Quarkus dev does not discover maven modules Quarkus dev loads maven modules after each other Aug 25, 2024
@Stwissel
Copy link
Author

Update: followed this advice and tried to use --projects:

mvn clean compile quarkus:dev --projects service1 --also-make

Unfortunately quarkus ignores the parameter and loads all modules sequentially

@Stwissel Stwissel changed the title Quarkus dev loads maven modules after each other Quarkus dev loads maven modules after each other, ingores --projects Aug 25, 2024
@aloubyansky
Copy link
Member

aloubyansky commented Aug 25, 2024

mvn clean compile quarkus:dev --projects service1 --also-make instructs Maven to run clean compile quarkus:dev on every module in the reactor, that will include service1 and its dependencies. So, you are instructing Maven to run quarkus:dev on the library modules.

The quarkus:dev will attempt to launch a Quarkus app from every module that has quarkus-maven-plugin:build goal configured, since if a module has quarkus-maven-plugin:build goal configured, it means this module is a Quarkus app and so it should be launchable in dev mode too.

In the reproducer the quarkus-maven-plugin is configured in a parent POM, which means all the modules, including the library ones, inherit the same quarkus-maven-plugin configuration, so every module appears to be a Quarkus application. With this kind of setup, the observed behavior is expected.

If the library modules are not meant to be Quarkus applications themselves then the quarkus-maven-plugin configuration in the parent POM could be moved to pluginManagement and then the quarkus-maven-plugin could be added as a build plugin to the service1 module. Or the whole quarkus-maven-plugin configuration could move to the service1 module.

If the library modules are actually Quarkus applications and must have quarkus:build configured then the build goal would have to be skipped for those based on some condition, for example a profile or a property.

I'm closing this issue, since the described behavior is not a bug. If you have a more specific suggestion how to improve the experience, feel free to re-open. Thanks.

@Stwissel
Copy link
Author

Thank you for the explanation, appreciate the insight. I shall adjust the pom accordingly.

I'm still looking how to run quarkus dev on a chosen module. The observed behaviour is: Quarkus dev runs on the first Quarkus app found. Only once terminated runs on the second. In my actual application I have more than one service and need to test them interacting.

I'll update the reproducer to make that clearer.

@aloubyansky
Copy link
Member

Launching a specific app with quarkus:dev in a multi module project with multiple Quarkus apps gets a bit tricky.

The simplest way would be to run mvn clean install [-DskipTests] from the root - this will install the JARs into the local Maven repo and then Maven will be able to resolve them even if those modules are not in the reactor. So you can simply quarkus:dev from the module directory you want to launch. In this case, Maven will resolve dependencies from the local Maven repo but Quarkus will load the sources and classes from the project itself and you'll be able to work on the whole workspace as expected.

Another approach could be to define various Maven profiles.
For example, you could move the quarkus-maven-plugin configuration to the pluginManagement of a parent POM. Then move quarkus-maven-plugin from the default build/plugins in every application module to a profile that is activeByDefault, so that when you launch mvn package it just works.
Then you could add another profile, such as -PdevService1 which would also include quarkus-maven-plugin. So that when you launch mvn -PdevService1 only service1 will have the quarkus-maven-plugin configured.

@Stwissel
Copy link
Author

I updated the reproducer to include 2 services (in my actual app it's closer to 10). Moving the quarkus-maven-plugin to pluginMangement in the parent works and only the Quarkus apps are picked up by Quarkus dev. When you run quarkus dev now it loads service1 and after termination service2. I have service a landing page. The buttons there call out to service1 and service2.

service1 errors out (no surprise there), unless you open another terminal and run quarkus dev again. It complains about the debug port (fix: put the port in the pom - didn't do that yet), but adjust it and then starts service 1. Then it works and the two services can be debugged - potentially needing VSCode launch config (doable).

so "the hack" for now is: open as many terminal windows as applications. Start quarkus dev and terminate until you reach the last unstarted app. Switch to the next terminal. Repeat. ;-). So you start service_n, service_n-1, service_n-2 ... service1.

What might be a way forward to allow to specify which app to launch. Saves the "terminate till you reach the app".
Thoughts?

@aloubyansky
Copy link
Member

That's what I tried to describe in the previous comment but I guess it was too confusing

@Stwissel
Copy link
Author

Ahh got it. So you would put the quarkus-maven-plugin into profiles, so there would be serviceProfile1, serviceProfile2 ... and you run
quarkus dev -PserviceProfile[1|2|...]

That makes a lot of sense, thank you.

@Stwissel
Copy link
Author

I updated the project's main branch to be a sample as per your suggestion. I also described the process in readme.md and created a vscode task to launch in one go and specify the debugger settings.

Have a look what can be improved.

Blog entry pending. Thx again for your help

@aloubyansky
Copy link
Member

In this specific case I would recommend the following

diff --git a/pom.xml b/pom.xml
index 39b2851..55b1f25 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,8 +20,26 @@
     <modules>
         <module>library1</module>
                <module>library2</module>
-        <module>service1</module>
-        <module>service2</module>
     </modules>
 
+    <profiles>
+        <profile>
+            <id>service1</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <modules>
+                <module>service1</module>
+            </modules>
+        </profile>
+        <profile>
+            <id>service2</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <modules>
+                <module>service2</module>
+            </modules>
+        </profile>
+    </profiles>
 </project>
diff --git a/service1/pom.xml b/service1/pom.xml
index cda6276..fea1019 100644
--- a/service1/pom.xml
+++ b/service1/pom.xml
@@ -56,20 +56,10 @@
             <plugin>
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+            </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-           <id>service1</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>${quarkus.platform.group-id}</groupId>
-                        <artifactId>quarkus-maven-plugin</artifactId>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
 </project>
\ No newline at end of file
diff --git a/service2/pom.xml b/service2/pom.xml
index 593f988..1b82be6 100644
--- a/service2/pom.xml
+++ b/service2/pom.xml
@@ -51,23 +51,13 @@
             <plugin>
                 <artifactId>maven-failsafe-plugin</artifactId>
             </plugin>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+                <configuration>
+                    <debug>5006</debug>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
-
-    <profiles>
-        <profile>
-            <id>service2</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>${quarkus.platform.group-id}</groupId>
-                        <artifactId>quarkus-maven-plugin</artifactId>
-                        <configuration>
-                            <debug>5006</debug>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
 </project>

With this approach mvn clean package or install would build, test and publish all the modules to Maven.

Launching dev mode would look like mvn compile quarkus:dev -PserviceN and once you terminate it it won't proceed building other services.

@Stwissel
Copy link
Author

Double edged sword. you do a mvn clean package -Pnative and the services won't build. Having them in the reactor also makes it clearer - guess a matter of preference or project. I summed it up in a blog post: https://wissel.net/blog/2024/08/quarkus-in-multimodule-projects.html

@aloubyansky
Copy link
Member

You can do -Dnative instead of -Pnative and it will work

@Stwissel
Copy link
Author

Stwissel commented Sep 2, 2024

what would be awesome:

quarkus create app [...] --with-parent
quarkus module add [...]

SO the pom.xml for app, reactor and parent get created properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/maven kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants