GUI Application in IntelliJ IDEA using Maven: Throws NullPointerException after built into a jar

1.9k Views Asked by At

A similar question to this has been asked here about an year back. However, I find that the particular question has some missing details and points, and it has no proper answer given. So I am re-raising the same.

I have created a Maven project in IntelliJ IDEA and added a GUI form into that. By default IDEA creates a separate XML file for the structure of the form. Mine appears as follows.

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="TestUI">
  <grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
    <margin top="0" left="0" bottom="0" right="0"/>
    <constraints>
      <xy x="20" y="20" width="500" height="400"/>
    </constraints>
    <properties/>
    <border type="none"/>
    <children>
      <component id="e40aa" class="javax.swing.JTextField" binding="txtTest">
        <constraints>
          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
            <preferred-size width="150" height="-1"/>
          </grid>
        </constraints>
        <properties/>
      </component>
    </children>
  </grid>
</form>

This has a class bound to it which appears as follows.

import javax.swing.*;

public class TestUI {
    private JTextField txtTest;
    private JPanel panel1;

    public TestUI() {
        String str = txtTest.getText();
        JOptionPane.showMessageDialog(null, str);
        createAndShowGui();

        txtTest.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "Clicked");
            }
        });
    }

    private  void createAndShowGui(){
        JFrame frame = new JFrame("test");
        frame.setContentPane(panel1);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        TestUI obj = new TestUI();
    }
}

POM.xml for this project originally looks like follows.

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.company.test</groupId>
    <artifactId>UITestWithIJ</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>TestUI</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

When this is run in IDEA, it works flawless. So I have built it into a fat jar via Maven using the assembly plugin. Then the problems started to jump out. When the jar created by Maven is executed, it throws a NullPointerException which appears as follows.

user@group-PC09:~/.m2/repository/com/company/test/UITestWithIJ/1.0-SNAPSHOT$ java -jar UITestWithIJ-1.0-SNAPSHOT-jar-with-dependencies.jar 
Exception in thread "main" java.lang.NullPointerException
    at TestUI.<init>(TestUI.java:13)
    at TestUI.main(TestUI.java:34)

Deeper I dug, I found that the reason for this is the line #13 that which is having txtTest identifier in it. This identifier by no mean is initialized. Hence it takes the default value null. So I realized that the problem is actually with IDEA and I simply need to transform the .form file generated by IDEA into some format that JVM alone could read.

Upon research I could find a candidate solution here. According to the instructions therein, I have modified my POM.xml as follows.

  • Added the following dependency

    <dependency>
        <groupId>com.intellij</groupId>
        <artifactId>forms_rt</artifactId>
        <version>7.0.3</version>
    </dependency>
    
  • Added the following plugin

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>ideauidesigner-maven-plugin</artifactId>
        <executions>
            <execution>
                <goals>
                    <goal>javac2</goal>
                </goals>
            </execution>
        </executions>
    
        <configuration>
            <fork>true</fork>
            <debug>true</debug>
            <failOnError>true</failOnError>
        </configuration>
    </plugin>
    

This has resolved the problem. However, in the TestUI.java you see that there is an event listener added. This could be replaced with a lambda expression from Java 8 forth. Once I have done that replacement, Maven fails to build the jar, throwing the following errors.

user@group-PC09:~/IdeaProjects/UITestWithIJ$ mvn clean install
[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for com.company.test:UITestWithIJ:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.codehaus.mojo:ideauidesigner-maven-plugin is missing. @ line 53, column 21
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building UITestWithIJ 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ UITestWithIJ ---
[INFO] Deleting /home/user/IdeaProjects/UITestWithIJ/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ UITestWithIJ ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.6.0:compile (default-compile) @ UITestWithIJ ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /home/user/IdeaProjects/UITestWithIJ/target/classes
[INFO] 
[INFO] --- ideauidesigner-maven-plugin:1.0-beta-1:javac2 (default) @ UITestWithIJ ---
[INFO] Executing IDEA UI Designer task...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.227 s
[INFO] Finished at: 2016-12-29T11:11:43+05:30
[INFO] Final Memory: 17M/205M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:ideauidesigner-maven-plugin:1.0-beta-1:javac2 (default) on project UITestWithIJ: Execution default of goal org.codehaus.mojo:ideauidesigner-maven-plugin:1.0-beta-1:javac2 failed: 52264 -> [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/PluginExecutionException

I have retired the same with -X switch and found that what actually fails here is the maven goal javac2 for the plugin ideauidesigner-maven-plugin and the only possible cause for that is the lambda expression. A method in the plugin throws an ArrayIndexOutOfBoundsException I have checked this and the dependency forms_rt in Maven repository and I noticed that those are last updated in 2009 and 2010. May be the plugin is incapable of handling lambda expression.

Following are my questions.

  • Am I doing something wrong?
  • Is there a fix for this?
  • Is there a viable alternative for this?
3

There are 3 best solutions below

1
On

First possibility:

frame.setContentPane(panel1);

Here, pane1 is not initialized and it is null.

Second possibility:

String str = txtTest.getText();
JOptionPane.showMessageDialog(null, str);

You are passing null to showMessageDialog() where it expects the parent Component.

1
On

I came across this issue when I was using IntelliJ to convert my project to a maven one. This process automatically created package folders and put my src files in it. So I added the package to the top of all my files. But this caused the exact same error when my JFrame was working fine before. Turns out in the form file, in the XML, the binding was wrong because now I was using packages

<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="TestUI">

I changed the bind-to-class attribute to correctly include the new package. This post is old but it might help someone looking through here in the future.

0
On

Your candidate solution didn't work for me.

After research, this happen only if we compile using maven. If we compile using Intellij, everything goes fine. So my only solution is doing this step when packaging.

  1. Clean using Maven to make sure every compiled class cleared
  2. Build using built-in Intellij
  3. Package using Maven