Repository: quarkusio/quarkus
Issue: Make Quarkus Maven plugin smart "create" consistent with codestarts

**Describe the bug**
Currently when providing no arguments to create, it asks:
```shell script
Set the project groupId [org.acme.quarkus.sample]: 
Set the project artifactId [my-quarkus-project]: 
Set the project version [1.0-SNAPSHOT]: 
Do you want to create a REST resource? (y/n) [no]: y
Set the resource classname [org.acme.quarkus.sample.HelloResource]: 
Set the resource path  [/hello]: /andy
```

**Expected behavior**
We should instead ask: 
```shell script
Set the project groupId [org.acme.quarkus.sample]: 
Set the project artifactId [my-quarkus-project]: 
Set the project version [1.0-SNAPSHOT]: 
What extensions do you wish to add (comma separated list): []
Do you want example code to get started (yes), or just an empty project (no) [yes]?
```

Changed files:
devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java
independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/LegacyCreateProjectCommandHandler.java
independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartData.java
independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java
integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java

diff --git a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java
index 9261b005314..e4a0274c6d3 100644
--- a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java
+++ b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java
@@ -61,7 +61,10 @@
 @Mojo(name = "create", requiresProject = false)
 public class CreateProjectMojo extends AbstractMojo {
 
-    private static final String DEFAULT_GROUP_ID = "org.acme.quarkus.sample";
+    private static final String DEFAULT_GROUP_ID = "org.acme";
+    private static final String DEFAULT_ARTIFACT_ID = "code-with-quarkus";
+    private static final String DEFAULT_VERSION = "1.0.0-SNAPSHOT";
+    private static final String DEFAULT_EXTENSIONS = "resteasy";
 
     @Parameter(defaultValue = "${project}")
     protected MavenProject project;
@@ -102,9 +105,22 @@ public class CreateProjectMojo extends AbstractMojo {
     @Parameter(property = "path")
     private String path;
 
+    /**
+     * This parameter is only working with the RESTEasy and Spring Web extensions and is going to be removed.
+     * Use packageName instead.
+     *
+     * {@code className}
+     */
     @Parameter(property = "className")
+    @Deprecated
     private String className;
 
+    /**
+     * If not set, groupId will be used
+     */
+    @Parameter(property = "packageName")
+    private String packageName;
+
     @Parameter(property = "buildTool", defaultValue = "MAVEN")
     private String buildTool;
 
@@ -228,6 +244,7 @@ public void execute() throws MojoExecutionException {
                     .version(projectVersion)
                     .sourceType(sourceType)
                     .className(className)
+                    .packageName(packageName)
                     .extensions(extensions)
                     .legacyCodegen(legacyCodegen)
                     .noExamples(noExamples);
@@ -352,15 +369,15 @@ private void askTheUserForMissingValues() throws MojoExecutionException {
         // If the user has disabled the interactive mode or if the user has specified the artifactId, disable the
         // user interactions.
         if (!session.getRequest().isInteractiveMode() || shouldUseDefaults()) {
-            // Inject default values in all non-set parameters
+            if (StringUtils.isBlank(projectArtifactId)) {
+                // we need to set it for the project directory
+                projectArtifactId = DEFAULT_ARTIFACT_ID;
+            }
             if (StringUtils.isBlank(projectGroupId)) {
                 projectGroupId = DEFAULT_GROUP_ID;
             }
-            if (StringUtils.isBlank(projectArtifactId)) {
-                projectArtifactId = "my-quarkus-project";
-            }
             if (StringUtils.isBlank(projectVersion)) {
-                projectVersion = "1.0-SNAPSHOT";
+                projectVersion = DEFAULT_VERSION;
             }
             return;
         }
@@ -373,28 +390,43 @@ private void askTheUserForMissingValues() throws MojoExecutionException {
 
             if (StringUtils.isBlank(projectArtifactId)) {
                 projectArtifactId = prompter.promptWithDefaultValue("Set the project artifactId",
-                        "my-quarkus-project");
+                        DEFAULT_ARTIFACT_ID);
             }
 
             if (StringUtils.isBlank(projectVersion)) {
                 projectVersion = prompter.promptWithDefaultValue("Set the project version",
-                        "1.0-SNAPSHOT");
+                        DEFAULT_VERSION);
             }
 
-            if (StringUtils.isBlank(className)) {
-                // Ask the user if he want to create a resource
-                String answer = prompter.promptWithDefaultValue("Do you want to create a REST resource? (y/n)", "no");
-                if (isTrueOrYes(answer)) {
-                    String defaultResourceName = projectGroupId.replace("-", ".")
-                            .replace("_", ".") + ".HelloResource";
-                    className = prompter.promptWithDefaultValue("Set the resource classname", defaultResourceName);
-                    if (StringUtils.isBlank(path)) {
-                        path = prompter.promptWithDefaultValue("Set the resource path ", CreateUtils.getDerivedPath(className));
+            if (legacyCodegen) {
+                if (StringUtils.isBlank(className)) {
+                    // Ask the user if he want to create a resource
+                    String answer = prompter.promptWithDefaultValue("Do you want to create a REST resource? (y/n)", "no");
+                    if (isTrueOrYes(answer)) {
+                        String defaultResourceName = projectGroupId.replace("-", ".")
+                                .replace("_", ".") + ".HelloResource";
+                        className = prompter.promptWithDefaultValue("Set the resource classname", defaultResourceName);
+                        if (StringUtils.isBlank(path)) {
+                            path = prompter.promptWithDefaultValue("Set the resource path ",
+                                    CreateUtils.getDerivedPath(className));
+                        }
+                    } else {
+                        className = null;
+                        path = null;
                     }
-                } else {
-                    className = null;
-                    path = null;
                 }
+            } else {
+                if (extensions.isEmpty()) {
+                    extensions = Arrays
+                            .stream(prompter.promptWithDefaultValue("What extensions do you wish to add (comma separated list)",
+                                    DEFAULT_EXTENSIONS)
+                                    .split(","))
+                            .map(String::trim).filter(StringUtils::isNotEmpty)
+                            .collect(Collectors.toSet());
+                }
+                String answer = prompter.promptWithDefaultValue(
+                        "Do you want example code to get started (yes), or just an empty project (no)", "yes");
+                noExamples = answer.startsWith("n");
             }
 
         } catch (IOException e) {
@@ -417,13 +449,16 @@ private boolean isTrueOrYes(String answer) {
     }
 
     private void sanitizeOptions(SourceType sourceType) {
-        // If className is null, we won't create the REST resource,
         if (className != null) {
             className = sourceType.stripExtensionFrom(className);
 
-            if (!className.contains(".")) {
-                // No package name, inject one
-                className = projectGroupId.replace("-", ".").replace("_", ".") + "." + className;
+            int idx = className.lastIndexOf('.');
+            if (idx >= 0 && StringUtils.isBlank(packageName)) {
+                // if it's a full qualified class name, we use the package name part (only if the packageName wasn't already defined)
+                packageName = className.substring(0, idx);
+
+                // And we strip it from the className
+                className = className.substring(idx + 1);
             }
 
             if (StringUtils.isBlank(path)) {
@@ -432,6 +467,7 @@ private void sanitizeOptions(SourceType sourceType) {
                 path = "/" + path;
             }
         }
+        // if package name is empty, the groupId will be used as part of the CreateProject logic
     }
 
     private void sanitizeExtensions() {
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartData.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartData.java
index d54be2a604a..77a35b738f4 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartData.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartData.java
@@ -101,6 +101,7 @@ public static Map<String, Object> convertFromLegacy(Map<String, Object> legacy)
         }
     }
 
+    // TODO remove the class_name convertion when its removed
     private static String convertClassName(final Map<String, Object> legacyData) {
         Optional<String> classNameValue = NestedMaps.getValue(legacyData, "class_name");
         if (classNameValue.isPresent()) {
@@ -119,6 +120,7 @@ private static String convertPackageName(final Map<String, Object> legacyData) {
         if (packageNameValue.isPresent()) {
             return packageNameValue.get();
         }
+        // TODO remove this block when class_name is removed
         Optional<String> classNameValue = NestedMaps.getValue(legacyData, "class_name");
         if (classNameValue.isPresent()) {
             final String className = classNameValue.get();
@@ -127,6 +129,12 @@ private static String convertPackageName(final Map<String, Object> legacyData) {
                 return className.substring(0, idx);
             }
         }
+
+        // Default to cleaned groupId if packageName not set
+        Optional<String> groupIdValue = NestedMaps.getValue(legacyData, "project_groupId");
+        if (groupIdValue.isPresent()) {
+            return groupIdValue.get().replace("-", ".").replace("_", ".");
+        }
         return null;
     }
 }
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java
index 942c1421aef..29d046e9806 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/CreateProject.java
@@ -95,6 +95,10 @@ public CreateProject resourcePath(String resourcePath) {
         return this;
     }
 
+    /**
+     * Use packageName instead as this one is only working with RESTEasy and SpringWeb
+     */
+    @Deprecated
     public CreateProject className(String className) {
         if (className == null) {
             return this;
@@ -106,6 +110,17 @@ public CreateProject className(String className) {
         return this;
     }
 
+    public CreateProject packageName(String packageName) {
+        if (packageName == null) {
+            return this;
+        }
+        if (!(SourceVersion.isName(packageName) && !SourceVersion.isKeyword(packageName))) {
+            throw new IllegalArgumentException(packageName + " is not a  package name");
+        }
+        setValue(PACKAGE_NAME, packageName);
+        return this;
+    }
+
     public CreateProject extensions(Set<String> extensions) {
         if (extensions == null) {
             return this;
@@ -219,7 +234,6 @@ public QuarkusCommandOutcome execute() throws QuarkusCommandException {
             setValue(IS_SPRING, true);
             if (containsRESTEasy(extensions)) {
                 values.remove(CLASS_NAME);
-                values.remove(PACKAGE_NAME);
                 values.remove(RESOURCE_PATH);
             }
         }
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/LegacyCreateProjectCommandHandler.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/LegacyCreateProjectCommandHandler.java
index 8a45c6f909d..e4fd4e1e838 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/LegacyCreateProjectCommandHandler.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/commands/handlers/LegacyCreateProjectCommandHandler.java
@@ -67,6 +67,13 @@ public QuarkusCommandOutcome execute(QuarkusCommandInvocation invocation) throws
                 invocation.setValue(CLASS_NAME, className);
             }
 
+            // Default to cleaned groupId if packageName not set
+            final String pkgName = invocation.getStringValue(PACKAGE_NAME);
+            final String groupId = invocation.getStringValue(PROJECT_GROUP_ID);
+            if (pkgName == null && groupId != null) {
+                invocation.setValue(PACKAGE_NAME, groupId.replace("-", ".").replace("_", "."));
+            }
+
             final List<AppArtifactCoords> extensionsToAdd = computeCoordsFromQuery(invocation, extensionsQuery);
 
             // extensionsToAdd is null when an error occurred while matching extensions
diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java
index d51a6834772..d2ebba6f4e3 100644
--- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java
+++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java
@@ -60,7 +60,7 @@ public void testProjectGenerationFromScratch() throws MavenInvocationException,
         Properties properties = new Properties();
         properties.put("projectGroupId", "org.acme");
         properties.put("projectArtifactId", "acme");
-        properties.put("projectVersion", "1.0-SNAPSHOT");
+        properties.put("projectVersion", "1.0.0-SNAPSHOT");
         InvocationResult result = setup(properties);
 
         assertThat(result.getExitCode()).isZero();
@@ -374,9 +374,9 @@ public void testThatDefaultPackageAreReplaced() throws Exception {
 
         assertThat(result.getExitCode()).isZero();
         // As the directory is not empty (log) navigate to the artifactID directory
-        testDir = new File(testDir, "my-quarkus-project");
-        check(new File(testDir, "src/main/java/org/acme/quarkus/sample/MyGreatResource.java"),
-                "package org.acme.quarkus.sample;");
+        testDir = new File(testDir, "code-with-quarkus");
+        check(new File(testDir, "src/main/java/org/acme/MyGreatResource.java"),
+                "package org.acme;");
     }
 
     private void check(final File resource, final String contentsToFind) throws IOException {
@@ -419,7 +419,7 @@ public void generateNewProjectAndRun() throws Exception {
         String resp = DevModeTestUtils.getHttpResponse();
 
         assertThat(resp).containsIgnoringCase("ready").containsIgnoringCase("application").containsIgnoringCase("org.acme")
-                .containsIgnoringCase("1.0-SNAPSHOT");
+                .containsIgnoringCase("1.0.0-SNAPSHOT");
 
         String greeting = DevModeTestUtils.getHttpResponse("/hello");
         assertThat(greeting).containsIgnoringCase("hello");