Quarkus: NullpointerException when building from profile

Created on 19 Jun 2020  路  20Comments  路  Source: quarkusio/quarkus

Describe the bug
When building a dev-jar from profile the build fails with an NullPointerException

Expected behavior
Build builds correctly.

Actual behavior
NullpointerException:

Caused by: org.apache.maven.plugin.MojoExecutionException: Failed to build quarkus application
    at io.quarkus.maven.BuildMojo.execute (BuildMojo.java:208)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: java.lang.NullPointerException
    at io.quarkus.maven.BuildMojo.execute (BuildMojo.java:174)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)

To Reproduce
Steps to reproduce the behavior:

clone https://github.com/tkalmar/quarkus-reproduce-9546/tree/reproduce_npe_profile_build
mvn -Pqjar-h2 -f server -X
Configuration

# Add your application.properties here, if applicable.

Screenshots
(If applicable, add screenshots to help explain your problem.)

Environment (please complete the following information):

  • Output of uname -a or ver: MINGW64_NT-10.0-18363 XXXX 3.0.7-338.x86_64 2019-11-21 23:07 UTC x86_64 Msys
  • Output of java -version:
    openjdk version "11.0.7" 2020-04-14
    OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
    OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)
  • GraalVM version (if different from Java):
  • Quarkus version or git rev: 1.5.2Final (works in 1.4.2Final
  • Build tool (ie. output of mvnw --version or gradlew --version):
    Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
    Additional context
    (Add any other context about the problem here.)

Maybe unrelated but : mvn clean install; mvn quarkus:dev -f server produces:

Exception in thread "main" java.lang.RuntimeException: java.lang.NullPointerException
        at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:130)
        at io.quarkus.deployment.dev.DevModeMain.main(DevModeMain.java:56)
Caused by: java.lang.NullPointerException
        at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:98)
        at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
        at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
        at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:229)
        at java.base/java.nio.file.Path.of(Path.java:147)
        at java.base/java.nio.file.Paths.get(Paths.java:69)
        at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:84)

but: mvn quarkus:dev -f server works after that until next clean install

kinbug

All 20 comments

cc @famod

1.5.2Final (works in 1.4.2Final

This part is easy to miss so in all clarity: This is a regression!

@tkalmar It seems you copied the wrong version for quarkus-jdbc-h2:
https://github.com/tkalmar/quarkus-reproduce-9546/blob/reproduce_npe_profile_build/server/pom.xml#L51

But even without this version (so that 1.5.2.Final is used) the problem persists.

The code fails here:
https://github.com/quarkusio/quarkus/blob/1.5.2.Final/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java#L174

projectArtifact.getFile() returns null and therefore .toPath() fails with a NPE.

@stuartwdouglas Since you added this line: Do you have any idea what is going on?

Thanks!

cc @aloubyansky

Do you have any idea why getFile is returning null? Is there something different about this project?

@stuartwdouglas I'm not sure who you wanted to adress with your question but from my POV the only special thing here is that the h2 dependency is just present in a profile.

It looks like it's related to the fact the server has neither sources nor resources, so it will end up being packaged an empty JAR. But until the packaging phase, there is literally no real content. So that may explain the null and why mvn -f server package works.

@famod @aloubyansky The dependency is not the problem, even if you remove this dependency from the profile getFile is null. Perhaps the maven model is built different for profiles than for "normal" runs? Even if i dumb down the example to a single module with one rest resource i get the NPE when building from profile ... So even if an non empty jar exists ...

Could you push that single module example somewhere on github? Or zip it and attach to this issue? Thanks @tkalmar

In this case it hasn't been compiled. If you do compile quarkus:build it'll work

or

diff --git a/pom.xml b/pom.xml
index b871416..e5f3e0d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
     <profile>
         <id>qjar-h2</id>
         <build>
-            <defaultGoal>quarkus:build@default</defaultGoal>
+            <defaultGoal>compile quarkus:build@default</defaultGoal>^M

Indeed, it has nothing to do with profile :/ mvn quarkus:build without compile NPEs also, works with quarkus 1.4.2Final, so this is a regression as @famod stated.

It's not true though that it actually worked in 1.4.2.Final. What happened in that version the resolver would simply pick up your previously installed JAR from the local repo. It's easy to reproduce using your minimal example. Remove the server artifact from your local repo and re-run.
We never did automatic compilation in the BuildMojo (unlike in DevMojo).

You are right. The Errormessage is not optimal in both versions, but i think NullPointerExceptioninstead of ...Could not find artifact is no improvement.

Well, if we are going to play that game...:) What's better: to fail fast with an NPE or be fooled by running stale code? :D
We do agree it needs to be properly fixed. No doubt about that :)

I vote for fail fast ;)

BTW, while we certainly could copy "auto-compile" from the DevMojo to BuildMojo, I don't feel good about that idea. It has its limitations. I'd prefer throwing an error if a project hasn't been compiled yet instead in this case.
Just in case, here is a fix

diff --git a/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java
index ee9449942..423d790b6 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/BuildMojo.java
@@ -9,6 +9,7 @@ import java.util.List;
 import java.util.Properties;

 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.Component;
@@ -172,7 +173,20 @@ public class BuildMojo extends AbstractMojo {
             final AppArtifact appArtifact = new AppArtifact(projectArtifact.getGroupId(), projectArtifact.getArtifactId(),
                     projectArtifact.getClassifier(), projectArtifact.getArtifactHandler().getExtension(),
                     projectArtifact.getVersion());
-            appArtifact.setPaths(PathsCollection.of(projectArtifact.getFile().toPath()));
+
+            File projectFile = projectArtifact.getFile();
+            if (projectFile == null) {
+                projectFile = new File(project.getBuild().getOutputDirectory());
+                if (!projectFile.exists()) {
+                    if (hasSources(project)) {
+                        throw new MojoExecutionException("Project " + project.getArtifact() + " has not been compiled yet");
+                    }
+                    if (!projectFile.mkdir()) {
+                        throw new MojoExecutionException("Failed to create the output dir " + projectFile);
+                    }
+                }
+            }
+            appArtifact.setPaths(PathsCollection.of(projectFile.toPath()));

             QuarkusBootstrap.Builder builder = QuarkusBootstrap.builder()
                     .setAppArtifact(appArtifact)
@@ -223,4 +237,15 @@ public class BuildMojo extends AbstractMojo {
         }
     }

+    private static boolean hasSources(MavenProject project) {
+        if (new File(project.getBuild().getSourceDirectory()).exists()) {
+            return true;
+        }
+        for (Resource r : project.getBuild().getResources()) {
+            if (new File(r.getDirectory()).exists()) {
+                return true;
+            }
+        }
+        return false;
+    }
 }

Okay, trying to catch up: So you are saying that the build goal depends on target/classes (which is created by resources plugin) even if this is more less empty? Am I missing something?

If there are no sources and no resources and the artifact hasn't been previously packaged, it's not resolvable.

Was this page helpful?
0 / 5 - 0 ratings