Programming NetBeans Platform with IntelliJ IDEA

by
Dan Lewis, Principal Software Engineer
Object Computing, Inc. (OCI)

Introduction

The NetBeans Platform allows rapid construction of an application that has some advanced capabilities, including templates, undo/redo, auto update, and more. It is an alternative to Eclipse Platform for those that wish to use standard Java Swing user interface instead of the Eclipse SWT user interface. The NetBeans Platform grew organically from the lessons learned about application architecture learned by the NetBeans IDE development team. Some of those lessons included the need to isolate the various parts of the application into "Modules" and the need to organize user interface items of interest into a hierarchy of "Nodes".

The NetBeans Platform enjoys use on many Java Swing-based Java UI applications. Unfortunately, the NetBeans Platform is coupled to the NetBeans IDE, and some developers prefer to use another IDE, such as IntelliJ IDEA. Most examples of NetBeans Platform development are illustrated using the NetBeans IDE to perform the development. Fortunately, with the help of this article, you can develop your NetBeans Platform application using IntelliJ IDEA.

IntelliJ IDEA is an IDE that used to be a commercial-only tool, but was recently open-sourced. IntelliJ IDEA is favored by some developers because it focuses on productivity and refactoring support. For those IntelliJ developers that wish to develop on the NetBeans Platform, steps can be taken that will allow an IntelliJ developer to work effectively on a NetBeans Platform application.

NetBeans vs IntelliJ notion of a Module

NetBeans defines a module as a cohesive chunk of code or a 3rd-party library with carefully defined dependencies and available public packages. IntelliJ defines a module similarly, but without the ability to identify certain packages as internal only. This means that you will sometimes have the IntelliJ IDE able to compile the application, but NetBeans Platform will refuse to run it because one module is accessing a non-public package of another module. Another reason IntelliJ IDE will compile the application but it won't run is because the module dependencies are not set up properly. This means that IntelliJ has one module accessing a class in another module without the necessary configuration in NetBeans to have it work.

To illustrate, we will use NetBeans Platform 7.3 Quick Start to quickly create a NetBeans Platform Application using NetBeans. The result of following along with the example is a NetBeans 7.3 Platform Application called "Word Processor" with five modules: WordEditorCore, WordEditorAPI, UppercaseFilter, LowercaseFilter, and WordHistory. We will use IntelliJ IDEA 12.1.4 for the illustrations. IntelliJ IDEA is free and open source.

Opening Word Processor Application in IntelliJ

Figure 1: Create New Project
create new project
Figure 2: Create New Project (Continued...)
create new project step 2
Figure 3: Create New Module
create new project step 3

In figure 4 when we configure the module, we exclude the build directory. This prevents IntelliJ from overwriting compile outputs created by Ant or NetBeans.

Figure 4: Create New Module (Continued...)
create new project step 4

Repeat the processes in Figures 3 and 4 for the remaining four modules: WordEditorAPI, UppercaseFilter, LowercaseFilter, and WordHistory. Figure 5 shows what the dialog looks like when done. We now have one IntelliJ module for each NetBeans module in our project.

Figure 5: All Modules Created
create new project step 5

Compiling the Word Processor Application in IntelliJ

Now attempt to build the project in IntelliJ idea.

Figure 6a: First Compile of Word Processor Application in IntelliJ: Rebuild Project
rebuild project
Figure 6b: First Compile of Word Processor Application in IntelliJ: Results
compile step 1

Observe that IntelliJ doesn't know anything about the NetBeans Platform. How does the NetBeans build system know where to find the supporting jar files? The answer is in a file called $wordproc\nbproject\private\platform-private.properties. The variable $wordproc is the directory containing your word processor example program. On the author's system, this is c:\wordproc. It contains one line:

user.properties.file=C:\\tools\\.netbeans\\7.3.1\\build.properties

Opening that file reveals two lines at the end:

nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness
nbplatform.default.netbeans.dest.dir=C:\\tools\\netbeans-7.3.1-201306052037-javase

These lines tell the NetBeans build system where to find the NetBeans Platform jars and the IntelliJ project needs to know this information too. They are located in a subdirectory named platform in the NetBeans IDE installation. One can also obtain the smaller NetBeans Platform zip if the only requirement is to compile the project. However, certain ANT targets in the NetBeans build system for deployment, such as build-zip require something called a harness, which is not included in the Platform zip. For this example, we will create an IntelliJ library that includes all of the jar files in the NetBeans platform subdirectory, recursively, but excluding locale-specific jars.

Figure 7: Creating the IntelliJ library containing NetBeans Platform jars
compile step 2

Once the IntelliJ library called "NetBeans Platform" is created, we need to add it as a dependency of the IntelliJ modules in our application.

Figure 8: Adding the dependencies on NetBeans Platform.
compile step 3

After we have added the dependencies, we can rebuild the project. We have fewer compilation problems now, but we are still unhappy, as shown in the next figure.

Figure 9: Second Compile of Word Processor Application in IntelliJ
compile step 5

It turns out that the NetBeans Platform example makes use of compile time annotations. These annotations generate code as part of the compile step. We must tell IntelliJ to go ahead and run the annotations and place them in a spot where we can see the generated code from our IDE.

Figure 10: Enable Annotations Processing
annotation processor

After we have enabled annotation processing, we can rebuild the project. We have fewer compilation problems now, but we have yet more configuration to set up, as is shown in the next figure.

Figure 11: Third Compile of Word Processor Application in IntelliJ
compile step 6

The IntelliJ module WordEditorCore cannot find the package org.word.editor.api. That package is inside the WordEditorAPI module. We need to add this dependency.

Figure 11: Adding Inter-Module Dependencies in IntelliJ
compile step 7

Repeat this process so that modules LowercaseFilter and UppercaseFilter also depend upon WordEditorCore.

Figure 12: Fourth Compile of Word Processor Application in IntelliJ
compile step 8

While we do obtain a clean compilation, we still need to instruct IntelliJ where the location of the generated source code is so that we can navigate to it in the editor. For each of the five modules we will identify the "generated" subdirectory as a location of source code. *The compilation is clean yet the red squiggly underline in WordTopComponent.java shows that the configuration is still incomplete.

Figure 13: Identifying annotation-generated sources in IntelliJ
compile step 9

Observe that IntelliJ can now cleanly compile and navigate to the generated source code of the application.

Debugging the NetBeans Platform Application from IntelliJ

It is possible to develop a custom launcher program that will launch the NetBeans platform without the necessity to run either the NetBeans IDE or ANT-based NetBeans build system. In the absence of such a launcher program, launch your application using ANT and connect to it using a remote debugging profile. First, you will need to create a remote debugging run configuration in IntelliJ.

Figure 14a: Creating the Remote Debugging Profile
remote debug 1
Figure 14b: Creating the Remote Debugging Profile (continued)
remote debug 2

Next, you will add the line with the debugging arguments to the suite's project.properties file. On the author's system, this is located at $wordproc/nbproject/project.properties. project.properties file. Remember to prefix the line that you copy paste from the IntelliJ dialog with "-J".

app.name=${branding.token}
app.title=WordProcessor
modules=\
    ${project.org.word.editor.core}:\
    ${project.org.word.editor.api}:\
    ${project.org.word.editor.uppercase}:\
    ${project.org.word.editor.lowercase}:\
    ${project.org.word.editor.history}
project.org.word.editor.api=WordEditorAPI
project.org.word.editor.core=WordEditorCore
project.org.word.editor.history=WordHistory
project.org.word.editor.lowercase=LowercaseFilter
project.org.word.editor.uppercase=UppercaseFilter
run.args.extra=-J-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

Common Pitfalls

Failure to synchronize NetBeans and Intellij module dependencies.

If a module A depends upon a module B in the NetBeans universe, then the same should be true in the IntelliJ universe. The same is true the other way. If you are editing code in IntelliJ and you add a dependency between two modules, you need to make an analogous change in your NetBeans module dependencies. This can be done by hand in the modules' nbproject/project.xml file for the modules in question or using the NetBeans IDE in the normal way.

Failure to add new packages to the list of public packages in a module.

If you add a new package to a module that you would like to be visible within other packages, you need to edit the modules' nbproject/project.xml in the <public-packages> element to include that package. Note that this is necessary because IntelliJ does not have the ability to restrict visibility at the package level. This is a NetBeans capability that is enforced by the NetBeans Platform runtime.

Summary

Some developers have acquired proficiency with the IntelliJ IDE and may wish to maintain or develop an application based on the NetBeans Platform without having to use the NetBeans IDE. This article has shown the necessary steps to allow the IntelliJ developer to edit, compile, and debug a NetBeans Platform application from within IntelliJ IDE.

References


Valid XHTML 1.0 Strict [Valid RSS]
RSS
Top