Maven-based NetBeans platform development with JRebel 6 – minor update

Some months ago I wrote about how easy it is to use JRebel for development of NetBeans platform module [1]. That article was focused mainly on standard ant-based modules. But recently I started to convert my plugins to the maven-based approach. At the same time I started testing JRebel 6 in an EAP. This combination didn’t work as described in one of my previous blog entries [2], but I figured it out and I like to document it using this blog post.

Steps to get maven-based nbms running using JRebel 6

  • enable “compile on save”
  • generate rebel.xml to /src/main using the context menu of jrebel (this way it will be copied to target/classes)
  • alter the properties-section of the pom.xml like this
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <netbeans.run.params.ide/>
            <netbeans.run.params>-J-noverify -J-javaagent:e:/tools/jrebel/jrebel.jar -J-Drebel.log=true ${netbeans.run.params.ide}</netbeans.run.params>
        </properties>
    
  • run the module – JRebel will create a bootstrap file in your temp directory once and will quit the execution
    JRebel: Starting logging to file: C:\Users\markiewb\.jrebel\jrebel.log
    [INFO] JRebel is now building a boot class cache.
    [INFO] This will only happen on this first run, or after manually deleting the rebel boot folder.
    [WARNING] JRebel bootclasspath not specified!
    [WARNING] Make sure to add -Xbootclasspath/p:C:/Users/markiewb/AppData/Local/Temp//rebelboot.jar to jvm arguments
    [WARNING] Otherwise this warning will appear again, and you won't be able to start your application
    [INFO] System will exit now, please restart the application to run with JRebel enabled.
    
  • add the bootclasspath argument with the path from the previous output to netbeans.run.params too (please note the “-J” prefix, that is important) (If NetBeans does not start, try to remove ${netbeans.run.params.ide} from the <netbeans.run.params>-parameter
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <netbeans.run.params.ide/>
            <netbeans.run.params>-J-noverify -J-Xbootclasspath/p:C:\Users\markiewb\AppData\Local\Temp\rebelboot.jar -J-javaagent:e:/tools/jrebel/jrebel.jar -J-Drebel.log=true ${netbeans.run.params.ide}</netbeans.run.params>
        </properties>
    
  • run the module – the application with your module and JRebel should start up
  • make changes to your classes and jrebel will pick them up

Tested with Win7 64bit, Oracle JDK 1.7.0u40, JRebel 6.0.0-M3, NetBeans IDE 7.4

 

Updates:
15/Mar/2014:

  • Tested with Win7 64bit, Oracle JDK 1.7.0u45, JRebel 6.0.0-M6, NetBeans IDE 7.4Patch2
  • Added comment about removing ${netbeans.run.params.ide}

[1] https://benkiew.wordpress.com/2013/05/01/netbeans-platform-development-with-jrebel-even-more-simplified/
[2] https://benkiew.wordpress.com/2011/12/28/netbeans-module-development-with-jrebel/

Advertisements

NetBeans IDE module development with JRebel

This post is mostly obsolete: See http://wp.me/pIpWO-n0 for an updated version.


In my previous post http://wp.me/pIpWO-5M i showed you how to create your own nbm-modules with the help of JRebel. Today i will show you how you can use JRebel to fasten up the development of the NetBeans IDE platform modules.

So if you want to use JRebel to “instantly reload” your compiled changes to a locally compiled bleeding-edge-development-version of NetBeans IDE you have to follow these steps:

  1. checkout the sources
  2. run “ant” to compile the sources and build a NetBeans installation
  3. open a module to be changed from the checkout sources
  4. create or open \nbbuild\user.build.properties
  5. add the line: tryme.args=-J-noverify -J-javaagent:d:/tools/JRebel/jrebel.jar -J-Drebel.log=true (update the path to the correct installation folder)
  6. create or generate a jrebel.xml in the sourcefolder of the module – let the JRebel-plugin do this for you
  7. run the module against the previously compiled version of NetBeans IDE (now called “target-platform“) using the context menu-entry “Run” (you will see the default JRebel headers in the output window, which means JRebel is loaded, and the Target-IDE will be opened)
  8. make your changes to the code, compile via F9
  9. go back to “target-platform“, do your actions again and the changes are reloaded instantly

FYI: The info about the correct location was taken from http://wiki.netbeans.org/DevFaqNetBeansFullHack

Fast NetBeans module development with JRebel – with screencast

This post is mostly obsolete: See http://wp.me/pIpWO-n0 for an updated version.


Based on a previous post https://benkiew.wordpress.com/2011/12/28/netbeans-module-development-with-jrebel/ i made a small video screencast to show how to use JRebel to improve your productivity when developing NetBeans modules.


1. Preconditions and setup

  • NetBeans 7.1.2/7.2.x installed (should work also with other version, but only these two were tested)
  • a valid installation of JRebel > 4.5.x (tested with 4.5.x, 4.6, 4.6.2, 5.0.0)
  • a valid license for JRebel – can also be the free social one – has to be configured in the JRebel configuration wizard
  • JRebel Netbeans Plugin 1.2 installed (use the update center) – required for debugging JRebel-instrumented code and generating rebel.xml
  • Change shortcut for “compile” to CTRL-S (Compile includes saving) – the equivalent to eclipse “Build automatically” or NetBeans “Compile on save” (Because “compile on save” is not yet available for module development projects)

2. Step by step

  •  Follow the instructions to generate a sample project @ http://platform.netbeans.org/tutorials/nbm-code-generator.html
  •  Select “Generate rebel.xml” in the context menu of your project, select the root path of your sources
  •  Add the following line to \nbproject\platform.properties (can be found in the Projects-panel named as “NetBeans Platform Config”)
    run.args.extra=-J-noverify -J-javaagent:d:/tools/JRebel/jrebel.jar -J-Drebel.log=true
    These parameters are taken from the offical JRebel documentation http://manuals.zeroturnaround.com/jrebel-reference-manual/server.html#server-4.6.1
  • Run the project -> a new NetBeans instance should be opened
    Note the output of the activated JRebel plugin in the output window of the development:
    JRebel: Starting logging to file: D:\tools\JRebel\jrebel.log
    [2012-05-19 12:05:05] #############################################################
    [2012-05-19 12:05:05]
    [2012-05-19 12:05:05] JRebel 4.6.2 (201205021440)
    [2012-05-19 12:05:05] (c) Copyright ZeroTurnaround OU, Estonia, Tartu.
    [2012-05-19 12:05:05]
    [2012-05-19 12:05:05] Over the last XXX days JRebel prevented
    [2012-05-19 12:05:05] at least XXX redeploys/restarts saving you about X,X hours.
    [2012-05-19 12:05:05]
    [2012-05-19 12:05:05] Over the last XXX days JRebel prevented
    [2012-05-19 12:05:05] at least XXX redeploys/restarts saving you about X,X hours.
    [2012-05-19 12:05:05]
    [2012-05-19 12:05:05] This product is licensed to XXXX
    [2012-05-19 12:05:05] until XXX
    [2012-05-19 12:05:05] #############################################################
  • Ignore the OSGI-exceptions (JRebel does not yet officially supports nbm-development) – UPDATE: this seams to be fixed in JRebel 5.0.0
  • Change the method content, change fields, do some refactoring …
  • CTRL-S for compiling including saving (see setup above)
  • execute the action in the target IDE again -> JRebel will reload the code

Spring 2.5.x+3.0.x: Create prototype instances from code

Here follow some snippets to show you the programmatically creation of prototype instances using Spring 2.5.6.SEC01.

a) Create a spring bean with scope “prototype”.

package springsample;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(value = "prototype")
public class Knife {
}

b) Create a spring bean and autowire a ProviderUtil instance (l. 12). The prototype instances are created at line 29 using ProviderUtils.

package springsample;

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class KnifeJuggler {

    @Autowired
    ProviderUtil util;

    public void juggle() {
        List<Knife> list = new ArrayList<Knife>();

        for (int i = 0; i < 5; i++) {
            //create 5 prototype scoped instances
            list.add(createKnifeInstance());
        }

        //print each instance
        for (Knife knife : list) {
            System.out.println(knife);
        }
    }

    private Knife createKnifeInstance() {
        return util.getBeanByType(Knife.class);
    }
}

c) The “magic” is coded here. A utility bean named ProviderUtil is defined and the ApplicationContext is autowired (l. 14). The prototype bean now can be resolved using this context: Every time you call ctx.getBean(xxx) to get the bean a new instance will be returned (l. 24). (Because the scope of the target bean is “prototype”)

package springsample;

import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class ProviderUtil {

    @Autowired
    private ApplicationContext ctx;

    public <T> T getBeanByType(final Class<T> claz) throws UnsupportedOperationException, BeansException {
        Map beansOfType = ctx.getBeansOfType(claz);
        final int size = beansOfType.size();
        switch (size) {
            case 0:
                throw new UnsupportedOperationException("No bean found of type" + claz);
            case 1:
                String name = (String) beansOfType.keySet().iterator().next();
                return claz.cast(ctx.getBean(name, claz));
            default:
                throw new UnsupportedOperationException("Ambigious beans found of type" + claz);
        }
    }
}

d) Enable annotation driven spring bean processing. This registers all Spring beans via annotations like @Component.


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>
 
    <context:component-scan base-package="springsample"/>
</beans>

e) Sample code to test these snippets

package springsample;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("newSpringXMLConfig.xml");
        //resolve by type
        KnifeJuggler juggler = ProviderUtil.getBeanByType(ctx, KnifeJuggler.class);
        juggler.juggle();
    }
}

e) When running this code 5 different prototype instance will be printed to stdout.


springsample.Knife@f9da4fc
springsample.Knife@36baa466
springsample.Knife@177f409c
springsample.Knife@236acdd1
springsample.Knife@38ee6681
BUILD SUCCESSFUL (total time: 0 seconds)


Alternative a) An alternative would be the usage of javax.inject.Provider from JSR 330, but this is not supported for Spring 2.5.x. Using javax.inject.Provider in Spring 3.0.6 works. Do not forget to include a JSR330-dependency (like JEE6-API in NetBeans).

The code is simpler again: Autowire a provider for the prototype bean (l. 13) and use the provider to get the prototype instance (l. 31).

package springsample;

import java.util.ArrayList;
import java.util.List;
import javax.inject.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component(value = "jugglername")
public class KnifeJuggler {

    @Autowired
    Provider<Knife> knifeProvider;

    public void juggle() {
        List<Knife> list = new ArrayList<Knife>();


        for (int i = 0; i < 5; i++) {
            //create 5 prototype scoped instances
            list.add(createKnifeInstance());
        }

        //print each instance
        for (Knife knife : list) {
            System.out.println(knife);
        }
    }

    private Knife createKnifeInstance() {
        return knifeProvider.get();
    }
}

Alternative b) Use ObjectFactory – see the sample at http://techo-ecco.com/blog/spring-prototype-scoped-beans-and-dependency-injection/

Automating hudson/jenkins via REST and curl – a very small cookbook

As you know, Hudson supports a RESTful-API. So here a small cookbook using curl (running in cygwin). It is very easy, when you are accustomed to it.

#Get the current configuration and save it locally
curl -X GET http://user:password@hudson.server.org/job/myjobname/config.xml -o mylocalconfig.xml

#Update the configuration via posting a local configuration file
curl -X POST http://user:password@hudson.server.org/job/myjobname/config.xml --data-binary "@mymodifiedlocalconfig.xml"

#Creating a new job via posting a local configuration file
curl -X POST "http://user:password@hudson.server.org/createItem?name=newjobname" --data-binary "@newconfig.xml" -H "Content-Type: text/xml"

Update: Use --data-binary to post the data, else the line-endings won’t be transfered correctly.

Update 2017-08-13: A good post about securing the calls can be found at https://blog.dahanne.net/2016/05/17/how-to-update-a-jenkins-job-posting-config-xml/

Netbeans module development with JRebel

This post is mostly obsolete: See http://wp.me/pIpWO-n0 for an updated version.


In [project]\nbproject\platform.properties add the following line

run.args.extra=-J-noverify -J-javaagent:e:/tools/jrebel/jrebel.jar -J-Drebel.log=true

Note:

  • This requires a proper installation of jrebel in the path e:/tools/jrebel/
  • Do not forget to generate a rebel.xml into the root of your classpath
  • You have to compile the changed java source manually by Menu->Run->Compile file(“Compile-on-save” is not yet available for netbeans modules)
  • There will be some OSGI-exceptions when running/debugging the application, but class reloading works properly.

Tested with NetBeans IDE 7.1 RC2 (Build 201111302200)+7.1, JRebel 4.5.3


Other resources: http://blogs.codehaus.org/people/mkleint/2009/07/maven-netbeans-platform-javare.html

Update: You can also have a look at Javeleon

Update 2: In maven-based nbms you can run modules the following way (JRebel 4, 5)

  • enable “compile on save”
  • generate rebel.xml to /src/main using the context menu of jrebel (this way it will be copied to target/classes)
  • alter the properties-section of the pom.xml like this
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <netbeans.run.params.ide/>
            <netbeans.run.params>-J-noverify -J-javaagent:e:/tools/jrebel/jrebel.jar -J-Drebel.log=true ${netbeans.run.params.ide}</netbeans.run.params>
        </properties>
    
  • run the module the normal way – you will accounter some osgi-exception as mentioned above
  • make changes to your classes and jrebel will pick it up like [207230] JRebel: Reloading class 'b2s.compare.clipboard.TextDiffer'.
  • small issue: the jrebel-messages do not appear on the output-window – but in jrebel.log

Update 3:
@mkleint also blogged about JRebel and NBM-development at http://wiki.netbeans.org/DevFaqMavenPlatformRebel

[Quicktip] CVS-Changelog plugin for eclipse

As you know CVS is file-based and therefore it has many issues.

For example: In Eclipse (using the standard CVS-plugin) you can only see changes of the currently selected file in the history view. When you select the project, you see no history entries in the project like you are used to using SVN. I know, you can call "cvs log" to see all changes of all file, but that is not very comfortable.

A solution: Install the changelog plugin (http://code.google.com/a/eclipselabs.org/p/changelog/) and working with CVS is now easier… Internally it will call  "cvs log" and present the processed results in a clear table view manner. (See the screenshot at the project page and you will see what i mean.)