Maven, NetBeans platform, JavaRebel

| 9 Comments

When I was playing with JavaRebel in April, it was not possible to use JavaRebel with the NetBeans platform. Basically because the module system is just another container and for each container you need a JavaRebel plugin. The guys at Zeroturnaround wrote the plugin a few weeks back (thanks!) so I've downloaded the nightly build and tried to experiment a bit. I've also worked some more on Compile on Save support for 6.8, so I wanted to test how far we've got with #161337. Here's the result.

I've been using latest NetBeans dev builds, not 6.7. And the latest nightly JavaRebel from Zeroturnaround.com

1. create a new maven nb platform based app from the archetype:
GroupId: org.codehaus.mojo.archetypes
ArtifactId: netbeans-platform-app-archetype
Version: 1.1

In the simple module subproject, define a new simple action (via New Action wizard) that will reside in toolbar and main menu.

2. add a profile for javarebel in the root pom.xml

<profile>
<id>rebel</id>
<pluginRepositories>
<pluginRepository>
<id>zt-repo</id>
<name>Zero turnaround repo</name>
<url>http://repos.zeroturnaround.com/maven2</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.zeroturnaround</groupId>
<artifactId>javarebel-maven-plugin</artifactId>
<version>1.0.5</version>
<executions>
<execution>
<id>generate-rebel-xml</id>
<phase>process-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<packaging>jar</packaging>
</configuration>
</plugin>
</plugins>
</build>
</profile>

The important part here is the packaging parameter which we set to "jar" to have the netbeans modules (which have packaging "nbm" - unknown to the plugin) processed as plain jars.

3. in project properties dialog enable Configurations on the root project and activate the rebel profile. Then perform a build, all modules that are part of the project shall have the rebel.xml file generated now.

4. In Tools/Variables dialog, define a variable REBEL that points to the directory where you extracted JavaRebel to.

5. In the properties dialog of the nbm-application project, configure the startup parameters of the Run project action binding to include javarebel agent:
netbeans.run.params=-J-noverify -J-javaagent:${REBEL}/javarebel.jar -J-Drebel.log=true

Please Note: In 6.7, steps 4+5 won't work as described and you have to put the absolute path the javarebel jar in the action binding. Since it's written to the nbactions.xml file in the project basedir, it's rather inconvenient since you want to share that file in version control.

6. Now you can run the application. You can verify in the output of the maven build that the javarebel agent was started. You should have a basic Nb platform application started with the new action in the main menu. It doesn't do anything yet, let's change it. Note: keep the platform application running, don't exit.

7. Let's put something simple and visible into the action's performAction() method:


DialogDescriptor dd = new DialogDescriptor(new JLabel("foo"), "bar");
DialogDisplayer.getDefault().notify(dd);

Save the file. Unfortunately the class didn't get compiled on save, we will need to go to the module's project properties Compile panel and turn "Compile on Save" on for application sources. Now let's change and save the action class again and you should get the class compiled. Switch to the running application and trigger the action. You should get a dialog showing up now. Hurray!

Please note that in 6.7, you will have to add an maven-antrun-plugin snippet as described in the previous blog entry.

Note to self: It would be nice if the CoS support in the IDE would recognize the rebel.xml file in the target/classes folder and just automatically assume CoS shall be on, without additional configuration in the projects.

8. Unfortunately not everything is so bright, some things don't get propagated, like resources. If you try replace the explicit strings with

org.openide.util.NbBundle.getMessage(MyAction.class, "LBL_foo");
or
java.util.ResourceBundle.getBundle("com/mkleint/platformwithjavarebel/Bundle").getString("LBL_foo")

you end up with MissingResourceException. First I though it's caused by some caching in the ResourceBundle or NbBundle classes, but even if you create a new class in new package that was not touched before by the app, it will always just look for the bundle file in the jar, and never in the sources or output folder, which is strange because the javarebel log claims to watch the target/classes and src/main/resources folders when you start up the application.

9. I haven't even tried but anything that has to do with layer files, META-INF/services registration and annotations will not work either. I guess it could be added to the JavaRebel's netbeans plugin. Like dropping the various caches and reload everything when some of the significant files changes or appears, however it wil not work without having the resource problems mentioned in bullet 8.

Still, even with these limitations, the development cycle has been shortened significantly. Someone volunteer to add javarebel file generation to the Netbeans.org ant scripts?

9 Comments

Hi,

do you know a way to use JavaRebel with NB 6.7?

Thanks and regards
Rolf

Rolf, it should be possible in 6.7 as well, the only hassle is the need to generate the .netbeans_automatic_build stamp file n the target/classes - see my previous entry on the AppFramework + JavaRebel for the pom.xml snippet.

Hi,

we currently do not use Maven (it is on our map for the future). As i know there is a problem with debugging and JavaRebel in NB 6.5 which is solved using the plugin. How is it in NB 6.7? Do we still need the plugin, wich is not available for 6.7?

Thanks and regards
Rolf

Sorry, I don't do debugging much, I prefer System.out.println messages usually. I've never used javarebel together with debugger, so cannot really comment.

Ok. Do you know someone else who can help?

You should probably ask the netbeans debugger people, javarebel guys or the creator of the plugin you were using.

Hi,

when I try to invoke a TopComponent instead of the DialogDisplayer, it works fine without javarebel active during runtime.

But when I run my application together with jrebel, I receive a java.lang.ClassNotFoundException: org.openide.nodes.Node

A workaround is to explicitly set a direct dependency on org-openide-nodes instead of the transitive dependency inhereted from org-openide-windows.

Any suggestions on how to avoid this editing of dependencies just for javarebel execution so that I can use the same dependencies as during normal execution?

Kindest regards,

Bjorn

Hello Bjorn,

this could be a jrebel issue. The windows api module does indeed have a dependency on nodes api, so it probably is using it internally, I'm not sure if it exposes the nodes classes from it's own API though. But in general I've seen the issue in netbeans as well, even without the jrebel around. It's enough if api module A has a method with return value of class Foo which is part of api module B. Then even if you don't use or import the Foo class, you might get the CNFE as well. A deficiency of the module system I'd say together with "badly" designed api..

About this Entry

This page contains a single entry by mkleint published on July 1, 2009 1:59 PM.

NB 6.7 binaries in Maven repository was the previous entry in this blog.

Quick tip: Expressions in Maven dependency declarations is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.