Creating a Grails Plugin in NetBeans IDE

Let's create a plugin for Grails. Grails is, after all, modular and pluggable. Here's the ultimate simple Grails plugin, just to give an idea what is involved, from start to finish. The most useful references I have found so far are these:

Between those three, you should have enough to figure things out. I still found it hard, despite those instructions and so to avoid having to figure things out again some time in the future, I'll write absolutely everything here.

Creating the Plugin

  1. On the command line, run this:
    grails create-plugin SamplePlugin

    Now you have a Grails plugin. However, at the same time it is just another Grails application, which means you can simply open it in NetBeans IDE. (I.e., there is no import process and no NetBeans artifacts are added to the plugin in order to be able to open it in the IDE.)

  2. So open the plugin in the IDE. The Projects window isn't very interesting, it just shows you the same as you would normally see for Grails applications:

    The Files window (Ctrl-2) however, shows a lot more:

    Open the "SamplePluginGrailsPlugin.groovy" file and there you see the following:

    class SamplePluginGrailsPlugin {
        def version = 0.1
        def dependsOn = [:]
    	
        def doWithSpring = {
            // TODO Implement runtime spring config (optional)
        }
       
        def doWithApplicationContext = { applicationContext ->
            // TODO Implement post initialization spring config (optional)		
        }
    
        def doWithWebDescriptor = { xml ->
            // TODO Implement additions to web.xml (optional)
        }
    	                                      
        def doWithDynamicMethods = { ctx ->
            // TODO Implement registering dynamic methods to classes (optional)
        }
    	
        def onChange = { event ->
            // TODO Implement code that is executed when this class plugin class is changed  
            // the event contains: event.application and event.applicationContext objects
        }
                                                                                      
        def onApplicationChange = { event ->
            // TODO Implement code that is executed when any class in a GrailsApplication changes
            // the event contain: event.source, event.application and event.applicationContext objects
        }
    }

    I.e., you have hooks for integrating your code into meaningful places in the plugin.

  3. Now we'll create code that will let our plugin provide a new "constraint". (If you don't know what that is, you will know by the time you finish reading all this.) To do so, we will need to extend org.codehaus.groovy.grails.validation.AbstractConstraint, in a package within src/groovy:
    import org.codehaus.groovy.grails.validation.AbstractConstraint
    import org.springframework.validation.Errors
    
    class BestFrameworkConstraint extends AbstractConstraint {
    
        private static final String DEFAULT_MESSAGE_CODE = "default.answer.invalid.message";
        public static final String NAME = "oneCorrectResponse";
    
        private boolean validateConstraint
    
        //The parameter which the constraint is validated against:
        @Override
        public void setParameter(Object constraintParameter) {
            if (!(constraintParameter instanceof Boolean))
                throw new IllegalArgumentException("Parameter for constraint ["
                        + NAME + "] of property ["
                        + constraintPropertyName + "] of class ["
                        + constraintOwningClass + "] must be a boolean value");
            this.validateConstraint = ((Boolean) constraintParameter).booleanValue()
            super.setParameter(constraintParameter);
        }
    
        //Returns the default message for the given message code in the current locale:
        @Override
        protected void processValidate(Object target, Object propertyValue, Errors errors) {
            if (validateConstraint && !validate(target, propertyValue)) {
                def args = (Object[]) [constraintPropertyName, constraintOwningClass,
                        propertyValue]
                super.rejectValue(target, errors, DEFAULT_MESSAGE_CODE,
                        "not." + NAME, args);
            }
        }
    
        //Returns whether the constraint supports being applied against the specified type:
        @Override
        boolean supports(Class type) {
            return type != null && String.class.isAssignableFrom(type);
        }
    
        //The name of the constraint, which the user of the plugin will use
        //when working with your plugin.
        @Override
        String getName() {
            return NAME;
        }
    
        //Validate this constraint against a property value,
        //In this case, ONLY "Grails" is valid, everything else will cause an error:
        @Override
        boolean validate(target, propertyValue) {
            propertyValue ==~ /\^Grails$/
        }
    
    }

  4. Next, back in the Groovy plugin class that we looked at earlier, hook the above class into the plugin, using the "doWithSpring" closure to do so:
    def doWithSpring = {
        ConstrainedProperty.registerNewConstraint(
            BestFrameworkConstraint.NAME,
            BestFrameworkConstraint.class);
    }

  5. Now, back on the command line, navigate to within the "SamplePlugin" folder. There, run the following:
    grails package-plugin

    Back in the IDE, examine the ZIP file that the above command created:

That ZIP file is your Grails plugin.

Installing the Plugin

Now we will install our plugin in a new application.

  1. First, create a new Grails application by going to the New Project wizard (Ctrl-Shift-N) and choosing Groovy | Grails Application. Click Next and type "SampleApplication" and then click Finish.

  2. After the IDE has finished running the "grails create-app" command for you, you will see the new application open in the IDE. Right-click it and choose "Plugins", as shown here:

  3. In the Grails Plugins dialog, notice that the list gets filled with many potential plugins that you might want to install, from the Grails plugins repository. Instead, we'll install our own. Click Browse and browse to the ZIP file that we created three steps ago and notice that it appears in the text field at the bottom of the dialog:

  4. Click "Install" and then a progress bar appears, ending with the plugin being installed. Notice that you can also uninstall it:

  5. Take a look at your application and notice (in the Files window) what's happened to the plugin. It's been unzipped, plus the ZIP file is still there. And all that's been done in the "plugins" folder. Nothing else has changed, which means that uninstallation is as simple as removing the folder from the "plugins" folder:

    Thanks to "convention over configuration", Grails knows exactly where everything is—so that, for example, the "plugin.xml" file that you see above, if found within the folder structure you see above, is the indicator to Grails that a plugin is available for use.

Using the Functionality Provided By the Plugin

  1. Let's now use our plugin. Create a domain class called "Quiz", after right-clicking the "Domain Classes" node and choosing "Create new Domain Class":

  2. Right-click the "Controllers" node and choose "Create new controller". Type "Quiz" and then click Finish. Use the Groovy editor to add one line for adding the scaffolding (and uncomment the other line):

  3. Back in the "Quiz" domain class, add your property and use the "oneCorrectResponse" constraint defined in your plugin, as shown here:

    Note: The "oneCorrectResponse" constraint that you see above is the name of the constraint defined in the plugin.

  4. And then add the message to the messages.properties file, which is within the "Messages Bundles" node:

  5. Run the application and you will see that your constraint will prevent anything other than "Grails" from being considered acceptable, when "Create" is clicked below:

Congratulations, you've created, installed, and used your first Grails plugin!

Comments:

Very nice plugin and excellent step-by-step tutorial, and the constraint seems very useful and should be included in Grails ;-)

Posted by Guillaume Laforge on July 22, 2008 at 06:12 PM PDT #

Very nice, the one thing is still bothersome is having to run the create-plugin in the beginning of the tutorial on the command line : something like this should be in the IDE support.

The conclusion at the end really makes the tutorial shine, NICE !!!

Posted by Alex Kotchnev on July 22, 2008 at 08:09 PM PDT #

Yes, Alex. We're talking about a new project type for Grails Plugins, it'll be on the same level as Grails Applications. It'll run the "grails create-plugin" and then later you'll be able to select "grails install-plugin", i.e., when you want to install it. Won't be there for 6.5 probably though. Thanks for your support Alex and also Guillaume, I am very honored.

Posted by Geertjan on July 22, 2008 at 08:14 PM PDT #

Cool!

Posted by Macel Overdijk on July 22, 2008 at 09:05 PM PDT #

Very interesting stuff here but I don't get which versions of the grails plugin for netbeans you're using.
The default plugin for NetBeans 6.5 M1 does not have the context menu shown in your screenshots. Especially the "Plugins" option is missing...
Could you provide us with the version of netbeans and grails plugin youre working with?

Thanks!

Posted by Moritz Winter on July 28, 2008 at 07:58 AM PDT #

Michael, install NetBeans 6,5 Milestone 1, Web & Java EE distribution. No grails plugin needed.

Posted by Geertjan on July 28, 2008 at 02:36 PM PDT #

Altough Michael is not my name I guess the comment was the answer to my question ;-)
Thanks for your answer but I did almost exactly what you did and downloaded the NB 6.5 M1 _All_ Distribution.
My context menu looks very different tough:
http://img227.imageshack.us/img227/7278/screenrr1.jpg

As mentioned above I specially miss the "Plugins" option. Well no problem I still can use the windows-console to run webtest!

Posted by Moritz Winter on July 29, 2008 at 03:46 AM PDT #

Hi Moritz. Sorry for the name confusion. Maybe you need to get a daily build instead. There it is now in a different place, i.e., the Plugins menu item, but still in the contextual menu. Remember that all of this is still under development so things will continue changing until 6.5 is released.

Posted by Geertjan on July 29, 2008 at 03:49 AM PDT #

Very nicely written..... thanks

Posted by Himanshu Seth on January 26, 2009 at 12:47 PM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today