Maven plugin for JPackage from Java 14

Good afternoon!

Not so long ago, the new Java 14 was released. Among many interesting features, I was interested in one, namely the jpackage packer (while in the incubator).

The meaning of this feature is to take our application, all the dependencies and runtime, and assemble one installation file, which is easy to distribute, install and run.

The description of how to use the tool is in the article .

After playing with the packer, I wanted to try to implement it on my pet project.Since the project was written using Maven, it was decided to write a plugin. Since this is the first time I am writing a plugin for Maven, this task has become doubly interesting for me.

After googling on the topic of plugins, it became clear that writing them is not difficult: I inherited from the AbstractMojo class , implemented the void execute () method , hung up the Mojo annotation, and the plugin is ready.

The result is such a blank:

@Mojo(name = "createpackage", defaultPhase = LifecyclePhase.VERIFY, threadSafe =true)
public class JpackageMojo extends AbstractMojo {

   @Override
   public void execute() {
        //    .
   }
}

“Createpackage" is the name of the target;
“LifecyclePhase.VERIFY” - will be performed on verification.

To build the .exe installer, you must run the command:

jpackage --name myapp --input lib --main-jar main.jar

That is, you need to specify the name of the file at the output, the folder with the application and specify the dzharnik with the main method. To obtain this data, add the following lines to the class:

@Parameter(defaultValue = "${project.build.directory}")
private File buildDirectory;
@Parameter( defaultValue = "${project}", readonly = true )
private MavenProject project;

The documentation says that the tool is available through java.util.spi.ToolProvider.findFirst ("jpackage") , but I could not use it. Perhaps this is due to the fact that jpackage is in the incubator. If someone knows the solution, then please share in the comments.

Well, since we can’t do it beautifully, we will do it ugly, through Runtime.getRuntime (). Exec (command). For simplicity, I suggested that jpackage.exe is added to the environment variables.

The resulting command to execute:

jpackage.exe --name name --input path --main-jar main --dest dest --win-menu --win-shortcut

where a couple more flags are added : --dest dest indicates the place for the result, --win-menu --win-shortcut adds links to me and to the desktop in Windows.

As a result, I got the following:

@Mojo(name = "createpackage", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true)
public class JpackageMojo extends AbstractMojo {

   public static final String ERROR_CREATE_PACKAGE = "Error create package";

   @Parameter(defaultValue = "${project.build.directory}")
   private File buildDirectory;
   @Parameter( defaultValue = "${project}", readonly = true )
   private MavenProject project;

   @Override
   public void execute() {
       var name = project.getArtifactId();
       var path = buildDirectory.getPath();
       var main = project.getArtifact().getFile().getName();
       var dest = path + "\\dest";
       try {
           String command  = "jpackage.exe --name " + name + " --input "
                   + path + " --main-jar " + main + " --dest " + dest
                   + " --win-menu --win-shortcut";
           getLog().debug(command);
           Process proc = Runtime.getRuntime().exec(command);
           getLog().info(Arrays.toString(proc.getInputStream().readAllBytes()));
           proc.waitFor();
           proc.destroy();
       } catch (IOException e) {
           getLog().error(ERROR_CREATE_PACKAGE, e);
       } catch (InterruptedException e) {
           getLog().error(ERROR_CREATE_PACKAGE, e);
           Thread.currentThread().interrupt();
       }
   }
}

In the project, you can connect by adding the following lines to pom.xml
<plugin>
   <groupId>org.sterzhen</groupId>
   <artifactId>jpackage-maven-plugin</artifactId>
   <version>1.0-SNAPSHOT</version>
   <executions>
       <execution>
           <goals>
               <goal>createpackage</goal>
           </goals>
       </execution>
   </executions>
</plugin>

When testing the plugin on a pet project, there was one more surprise, namely, for the packer to work in Windows, it is necessary to additionally install WiX 3.0 or later.

After installing WiX, the plugin worked, which brought me the joy of a small victory. Yes, while it is primitive and works only for Windows, but this is only the beginning.

I will be glad to hear comments and suggestions.

The source code can be found at the link.

Documentation:

http://openjdk.java.net/jeps/343
https://docs.oracle.com/en/java/javase/14/docs/specs/man/jpackage.html
https://docs.oracle. com / en / java / javase / 14 / jpackage / packaging-overview.htm

Thank you!

All Articles