+ All Categories
Home > Documents > Introducing Spring Roo, Part 3: Developing Spring Roo...

Introducing Spring Roo, Part 3: Developing Spring Roo...

Date post: 28-Jun-2020
Category:
Upload: others
View: 3 times
Download: 0 times
Share this document with a friend
29
Introducing Spring Roo, Part 3: Developing Spring Roo add-ons Skill Level: Intermediate Shekhar Gulati ([email protected]) Senior Consultant Xebia India 16 Aug 2011 Spring Roo is a RAD tool that lets you build applications (mainly web) quickly and easily. Under the hood, Spring Roo is based on OSGI add-on architecture, which makes it easy to extend Spring Roo by adding add-ons. Spring Roo provides commands to create add-ons that can be very easily made available to the Spring Roo user community. In this article, we first talk about Spring Roo architecture, talking about how Spring Roo leverages its own add-on architecture to provide different features, then we will create add-ons using the Roo shell and modify them to suit our needs. Getting started In Part 1 and Part 2 of this "Introducing Spring Roo" series, we built a full-fledged enterprise application from scratch using Spring Roo. The first two articles focused on building web applications using Spring Roo's rapid application development environment. We covered a lot of features, like JPA, Selenium testing, Spring Security, email integration, Spring Roo social features, database reverse-engineering, etc. Now we will take a look at Spring Roo's add-on architecture. Then we will write Spring Roo add-ons using the addon create command. By the end of this article, you'll be able to quickly and easily create your own add-ons for Spring Roo. Spring Roo add-on architecture In its simplest form, an add-on is a software component that adds a specific ability to Developing Spring Roo add-ons Trademarks © Copyright IBM Corporation 2011 Page 1 of 29
Transcript
Page 1: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Introducing Spring Roo, Part 3: Developing SpringRoo add-onsSkill Level: Intermediate

Shekhar Gulati ([email protected])Senior ConsultantXebia India

16 Aug 2011

Spring Roo is a RAD tool that lets you build applications (mainly web) quickly andeasily. Under the hood, Spring Roo is based on OSGI add-on architecture, whichmakes it easy to extend Spring Roo by adding add-ons. Spring Roo providescommands to create add-ons that can be very easily made available to the SpringRoo user community. In this article, we first talk about Spring Roo architecture,talking about how Spring Roo leverages its own add-on architecture to providedifferent features, then we will create add-ons using the Roo shell and modify them tosuit our needs.

Getting started

In Part 1 and Part 2 of this "Introducing Spring Roo" series, we built a full-fledgedenterprise application from scratch using Spring Roo. The first two articles focusedon building web applications using Spring Roo's rapid application developmentenvironment. We covered a lot of features, like JPA, Selenium testing, SpringSecurity, email integration, Spring Roo social features, databasereverse-engineering, etc. Now we will take a look at Spring Roo's add-onarchitecture. Then we will write Spring Roo add-ons using the addon createcommand. By the end of this article, you'll be able to quickly and easily create yourown add-ons for Spring Roo.

Spring Roo add-on architecture

In its simplest form, an add-on is a software component that adds a specific ability to

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 1 of 29

Page 2: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

a software application. For example, in most web browsers, video support isprovided by add-ons. Another example is Eclipse (an open source IDE that manyJava™ developers use or at least know). Most of the capabilities are provided byadd-ons, like JUnit support, SVN support, etc. I am using add-on as a general termfor plugins and extensions.

Spring Roo also has the notion of add-ons:

1. To enable third-party developers to create abilities that extend thecapabilities of Spring Roo

2. To help Spring Roo easily add new features

3. To help Spring Roo remain a little genie (i.e., reduce the size of SpringRoo)

Spring Roo logical components

Spring Roo is split into two logical parts.

Spring Roo core components: To enable add-on development, Spring Rooprovides a set of core components that form a hosted execution environment fordifferent add-ons. These components are the Classpath, which supports the ProcessManager and the Shell. In turn, the Process Manager supports the Project and theFile Undo. The Project supports the Model, Metadata, and File Monitor. Finally, thereis the Support component, which is used by all. Figure 1 offers a visualrepresentation of these relationships.

Figure 1. Spring Roo core components

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 2 of 29

Page 3: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Let's talk about some of the core modules:

• Support — The org.springframework.roo.support moduleprovides common utility classes used by all the core modules andadd-ons. Some utility classes include Assert, FileCopyUtils,XmlUtils, StringUtils, FileUtils, etc. For example, if you want tocopy the content of one file to the other file, you could useFileCopyUtils to do it for you.

• Metadata — The org.springframework.roo.metadata module provides ametadata service provider interface and implementation that includesdependency registration and caching.

• File monitor — The org.springframework.roo.file.monitor modulepublishes events following detected file system changes (the defaultimplementation uses auto-scaled disk polling).

• File undo — The org.springframework.roo.file.undo module provides afile undo facility for use by the process manager.

• Project — The org.springframework.roo.project module abstracts typicalend-user project build systems like Apache Maven and Apache Ant.

• Process manager — The org.springframework.roo.process.managermodule offers an ACID-like file system abstraction that includes diskrollback and process synchronization.

• Classpath — The org.springframework.roo.classpath module performsabstract syntax tree parsing and type binding of Java and AspectJcompilation units.

Spring Roo core components: Spring Roo provides all the functionality throughadd-ons. The base add-ons shipping with Roo V1.1.3:

• Add-On Creator — The org.springframework.roo.addon.creator add-onenables easy creation of third-party Roo add-ons.

• Backup — The org.springframework.roo.addon.backup add-on enablesbackups to be made to a ZIP file by typing backup.

• Cloud Foundry — The org.springframework.roo.addon.cloud.foundryadd-on provides VMware Cloud Foundry support.

• Configurable — The org.springframework.roo.addon.configurable add-onprovides support for the introduction of Spring's @Configurableannotation through an AspectJ ITD.

• Database reverse engineering — Theorg.springframework.roo.addon.dbre add-on provides support for the

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 3 of 29

Page 4: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

incremental reverse-engineering of existing databases.

• Data on Demand — The org.springframework.roo.addon.dod add-onprovides support for the automatic creation of sample data used forintegration tests.

• Email — The org.springframework.roo.addon.email add-on providessupport for the integration and configuration of Spring's email support inthe target project.

• Entity — The org.springframework.roo.addon.entity add-on providesextensive support for automatically maintaining Java Persistence API@Entity classes.

• Dynamic Finder — The org.springframework.roo.addon.finder createstype-safe code completion-compatible JPA query language finders.

• Git — The org.springframework.roo.addon.git add-on provides support forGIT integration in the project. Each successfully executed command willbe automatically committed to a local GIT repository.

• GWT — The org.springframework.roo.addon.gwt add-on provides supportfor UI scaffolding using Google Web Toolkit.

• JavaBean — The org.springframework.roo.addon.javabean add-onautomatically maintains JavaBean getters/setters for classes with an@RooJavaBean annotation.

• JDBC — The org.springframework.roo.addon.jdbc add-on encapsulatesOSGi-compliant access to JDBC drivers shipped in different bundles(primarily used by other add-ons).

• JMS — The org.springframework.roo.addon.jms add-on provides supportfor configuring Java Messaging System settings in the target project.

• JPA — The org.springframework.roo.addon.jpa add-on installs aspecified JPA provider and sets up JDBC accordingly.

• JSON — The org.springframework.roo.addon.json add-on adds JSONrelated serialization and deserialization methods to POJOs.

• Logging — The org.springframework.roo.addon.logging add-on sets upLog4j, including command-based log-level configuration.

• Pluralization — The org.springframework.roo.addon.plural add-onprovides pluralization of nouns (primarily used by other add-ons).

• Property Editor — The org.springframework.roo.addon.property.editoradd-on manages property editors, as required by Spring MVC.

• Property File — The org.springframework.roo.addon.propfiles add-onprovides support for the management of properties files in the target

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 4 of 29

Page 5: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

project.

• RooBot Client — The org.springframework.roo.addon.roobot.clientadd-on provides support for add-on management through the RooBotserver.

• Security — The org.springframework.roo.addon.security add-on sets upSpring Security, including login pages, filters, and dependencies.

• Serializable — The org.springframework.roo.addon.serializable add-onadds java.io.Serializable support (such as UID maintenance) to requestedJava types.

• Solr — The org.springframework.roo.addon.solr add-on provides supportfor configuration and integration of Apache Solr features in the targetproject.

• Integration Test — The org.springframework.roo.addon.test add-onproduces JUnit integration tests for project entities.

• ToString — The org.springframework.roo.addon.tostring add-onproduces a valid toString() method for any class with the@RooToString annotation.

• WebFlow — The org.springframework.roo.addon.web.flow add-onprovides support for configuration and integration of Spring Web Flowfeatures in the target project.

• Web MVC Controller — Theorg.springframework.roo.addon.web.mvc.controller add-on providessupport for configuration and integration of Spring MVC controllers in thetarget project.

• Web MVC Embedded — Theorg.springframework.roo.addon.web.mvc.embedded add-on providesextension to the MVC add-on, which allows the addition of embeddedfeatures such as maps, videos, etc. into web pages.

• Web MVC JSP — The org.springframework.roo.addon.web.mvc.jspadd-on configures and integrates Spring MVC JSP features in the targetproject.

• Selenium — The org.springframework.roo.addon.web.selenium add-onprovides configuration and integration of Selenium web tests in the targetproject.

Now that we have looked at the Spring Roo core components and base add-onsprovided by Spring Roo, let's write our own add-ons.

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 5 of 29

Page 6: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

OSGi runtime environment

Spring Roo is based on OSGi, which is ideal for Roo's add-on architecture. OSGiprovides a very good infrastructure for developing modular and embeddedservice-oriented applications.

The Roo shell uses Apache Felix as its OSGi runtime framework together withService Component Runtime (SCR) for component management and OSGi BundleRepository (OBR) for bundle resolution. There are various OSGi commandsavailable in the Roo shell, which you can see by typing help osgi, as shown inListing 1.

Listing 1. Roo help for OSGi

roo> help osgi* osgi find - Finds bundles by name* osgi framework command - Passes a command directlythrough to the Felix shell infrastructure* osgi headers - Display headers for a specific bundle* osgi install - Installs a bundle JAR from a given URL* osgi log - Displays the OSGi log information* osgi obr deploy - Deploys a specific OSGi Bundle Repository (OBR) bundle* osgi obr info - Displays information on a specific OSGi Bundle Repository (OBR) bundle* osgi obr list - Lists all available bundles from theOSGi Bundle Repository (OBR) system* osgi obr start - Starts a specific OSGi Bundle Repository (OBR) bundle* osgi obr url add - Adds a new OSGi Bundle Repository (OBR) repository file URL* osgi obr url list - Lists the currently-configuredOSGi Bundle Repository (OBR) repository file URLs* osgi obr url refresh - Refreshes an existingOSGi Bundle Repository (OBR) repository file URL* osgi obr url remove - Removes an existingOSGi Bundle Repository (OBR) repository file URL* osgi ps - Displays OSGi bundle information* osgi resolve - Resolves a specific bundle ID* osgi scr config - Lists the current SCR configuration* osgi scr disable - Disables a specific SCR-defined component* osgi scr enable - Enables a specific SCR-defined component* osgi scr info - Lists information about a specific SCR-defined component* osgi scr list - Lists all SCR-defined components* osgi start - Starts a bundle JAR from a given URL* osgi uninstall - Uninstalls a specific bundle* osgi update - Updates a specific bundle* osgi version - Displays OSGi framework version

Spring Roo add-on create command

Spring Roo comes bundled with add-on create commands for creating differenttypes of add-ons. The Add-on Creator, which exposes the addon createcommands, is also a Roo add-on. Roo currently supports four types of add-ons:

1. Internationalization Add-on — It supports adding language translations

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 6 of 29

Page 7: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

for Roo's scaffolded Spring MVC applications (adding translation for theHindi language, for example).

2. Simple Add-on — Simple Add-ons support small additions to projectdependencies or configuration or both (making some maven pom.xmlmodifications like adding some JARs or Maven plugins, for example).

3. Advanced Add-on — This add-on does the heavy work and is used forbuilding a full-fledged Spring Roo add-on that requires Java code creation(building an add-on that can write equals and hashcode methods foryour domain object, for example). There is already a community add-onfor these functions.

4. Wrapper Add-on — This add-on wraps a Maven artifact to create anOSGi-compliant bundle. This is required when a dependency is requiredby the add-on to complete its functionality. For example, the Spring Roodatabase reverse-engineering add-on requires the Postgres JDBC driverto complete its tasks, so you will wrap the Postgres JDBC driver using thisadd-on.

These add-ons create commands to ease Roo add-on development by creating newadd-ons that are:

httppgp://Spring Roo V1.1 introduced Pretty Good Privacy (PGP), allowingusers to specify which developers were trusted to sign software thatwould be downloaded and activated in the Roo shell. In fact, everyrelease of Roo itself is now PGP-signed. A new protocol handlercalled httppgp:// was introduced into Roo to indicate that a URL alsohas a PGP armour-detached signature available. This provides anopen form of security to help protect users from maliciousdownloads. These standards also allow use of stand-alone PHPtools to independently verify Roo's operations.

• Integrated with Google Code SVN source-code control.

• Hosted in a public Maven repository created as a part of Google codeproject.

• Compliant with RooBot, a VMware-hosted service that indexes importantcontent in public Roo OBR files. The OBR file is an XML-basedrepresentation of bundle metadata. To be compliant with RooBot, add-onsshould be:

1. OSGi-compliant.

2. PGP-signed artifacts with public keys.

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 7 of 29

Page 8: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

3. Registered through the httppgp:// protocol.

Using the Roo addon create command, you get all the features mentioned above,automatically configured for your add-ons. This certainly reduces the time to createand publish the add-ons to the outside world.

Before we start writing add-ons, make sure you have a functioning Spring Rooenvironment. Instructions for installing Spring Roo can be found in Part 1 of thisseries.

I want Hindi language support (i18N add-on creation)

When you create a Spring MVC-based web application using Spring Roo, you canadd support for different languages using the web mvc language command. Outof the box, Spring Roo supports English, German, Spanish, Italian, Dutch, andSwedish. The internationalization support is provided by the Web MVC JSP Add-on,which is enabled only after you have JSPX files in your webapp directory. The JSPXfiles are generated by a controller command that converts a simple JAR-basedapplication to a Spring MVC web application.

Being an Indian, I wanted to add support for Hindi in my web application. Spring Rooprovides an addon create i18n command, which provides an extension to theweb mvc install language command adding support for a new language likeHindi. The only thing it requires is the translation of the messages.properties file inthe desired language.

When Spring Roo creates a Spring MVC web application, it creates two propertyfiles: application.properties and messages.properties. The application.properties filecontains the application-specific properties, like application name. Themessages.properties file contains the properties, which are not specific to anyapplication, like the message "Are you sure want to delete this item?" when you clickthe delete button, or messages like login, logout, etc. So, when you write an i18nadd-on, you have to provide translation for the messages.properties file.

Now that we have talked about the default internationalization support in Spring Roo,let's write an i18n add-on that can add Hindi language support. I will show how youcan set up a project on Google code, write an add-on using the command, publishand release it to outside world, finally registering it with the RooBot service.Registering with the RooBot service is important because this will let RooBot indexyour add-on and show it when other developers search using the addon searchcommand.

Project setup

The Spring Roo documentation eloquently explains setting up your project and

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 8 of 29

Page 9: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Maven repository on Google code, so I am not going to repeat it. I will just note that Iwill use the project name "roo-hind-addon."

Creating an i18N add-on

Once you have set up the project, you will have an empty directory namedroo-hindi-addon. Go into that directory and type roo command. Once in the shell,type addon create i18n. If you press the tab key, you will see that this commandtakes seven attributes. Out of the seven, three attributes are mandatory:topLevelPackage (top-level package of the new add-on), locale (localabbreviations like "it" for Italian), and messageBundle (fully qualified path to themessage_xx.properties, where xx is the locale name). The other four are optionalattributes: language (full name of the language), flagGraphic (full path to xx.pngfile, where xx is the name of flag), description (description of the add-on), andprojectName (name of the project (if not provided, the top-level package name isused)). I would suggest you use the projectName attribute and make sure its valueis the name of the project hosted on Google code. So, in our case, it will beroo-hindi-addon.

Out of the attributes mentioned above, the most important is messageBundle,which specifies the translated messages.properties file. To translate themessages.properties to Hindi language, the easiest option is to use a service likeGoogle translate, converting each property one by one, then writing them to themessages_hi.properties file. However, this does not work in our situation becausethe Java properties files use ISO-8859-1 encoding, which does not support Hindicharacters. To overcome this problem, I used an Eclipse plugin called EclipseResourceBundle Editor, which allows you to convert and create resource bundles fordifferent languages. You can install it using thehttp://www.nightlabs.de/updatesites/development/ update site. Converting themessages.properties file to the messages_hi.properties file is not in the scope of thisarticle. The ResourceBundle Editor plugin is easy to use. Please note that if thelanguage characters were supported, it was not required to use the ResourceBundleEditor. The messages_hi.properties file will look like Listing 2.

Listing 2. Sample of the messages_hi.properties file

button_cancel = \u0930\u0926\u094D\u0926button_end = \u0905\u0902\u0924button_find = \u0916\u094B\u091C\u0947\u0902button_home = \u0918\u0930...

View the full file. Once you have the translated messages_hi.properties file, you areready to create the add-on by just typing a single command. You can create Hindiadd-on by typing the command from Listing 3 into the Roo shell.

Listing 3. Command to create the Hindi add-on

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 9 of 29

Page 10: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

addon create i18n --locale hi --topLevelPackage org.xebia.roo.addon.i18n.hindi--messageBundle <location to messages_hi.properties> \

--language hindi --projectName roo-hindi-addon--flagGraphic <full path to flag hi.png>

Listing 4 shows the artifacts created by the addon create i18n command.

Listing 4. Artifacts created

Created ROOT/pom.xmlCreated ROOT/readme.txtCreated ROOT/legalCreated ROOT/legal/LICENSE.TXTCreated SRC_MAIN_JAVACreated SRC_MAIN_RESOURCESCreated SRC_TEST_JAVACreated SRC_TEST_RESOURCESCreated SRC_MAIN_WEBAPPCreated SRC_MAIN_RESOURCES/META-INF/springCreated ROOT/src/main/assemblyCreated ROOT/src/main/assembly/assembly.xmlCreated SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindiCreated SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi/messages_hi.propertiesCreated SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi/hi.pngCreated SRC_MAIN_JAVA/org/xebia/roo/addon/i18n/hindiCreated SRC_MAIN_JAVA/org/xebia/roo/addon/i18n/hindi/HindiLanguage.java

The command generated a Maven project that can be imported into Eclipse (withm2eclipse) or the SpringSource Tool Suite via File > Import > Maven > ExistingMaven projects. You don't need to import this project because we don't need tomodify the add-on.

Now we can install this add-on, use it in our projects, and publish it to the outsideworld. But first, let's talk about some of the artifacts to gain more understanding ofthe generated code:

• pom.xml — This is a standard Maven project configuration. Thegenerated pom.xml has various pre-configured plugins, which does thework related to signing artifacts using PGP, releasing the add-on usingthe Maven release plugin, and creating OSGi bundles using the Mavenbundle plugin. It also adds OSGi and Felix dependencies to the project,which are needed for the add-on to run inside the Roo shell.

• assembly.xml — This defines the configurations used by the Mavenassembly plugin for packing the add-on.

• messages_hi.properties — This is the message bundle file we providedwhile creating the add-on, which is copied to resources folder.

• hi.png — This is the flag PNG file we provided while creating the add-on,which is copied to resources folder.

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 10 of 29

Page 11: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

• HindiLanguage.java — This is the only Java file created by this add-on,used to get the information corresponding to the specific language. Forexample, it gives the local name, message bundle resource file, etc.

Adding Hindi support to our application

Now I will show you how you can add Hindi support to your application using theadd-on we just created:

1. Exit the Roo shell and run the mvn clean install command. Duringthe build process, it will ask for your GPG passphrase.

2. After the Roo add-on has been built, open the new command line andcreate a directory named i18n-hindi-client. We will create a simple clientfor our add-on.

3. Enter the i18n-hindi-client directory and type the roo command.

4. Execute the following commands in the Roo shell. This will create asimple Spring MVC web application.Listing 5. Roo commands to create MVC web application

project --topLevelPackage com.shekhar.roo.i18n.client \--projectName i18n-hindi-clientpersistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORYentity --class ~.domain.MyUserfield string --fieldName name --notNullcontroller all --package ~.web

5. Type this command and press the tab key: web mvc language--code de en es it nl svYou will not see the Hindi language support. This is because we have notyet installed the Hindi add-on.

6. To install the add-on, type:osgi start --url file:///<location to addon target

folder>/org.xebia.roo.addon.i18n.hindi-0.1.0.BUILD-SNAPSHOT.jar

This should install and activate our Spring Roo Hindi add-on. You canview the status of the add-on using the osgi ps command, whichdisplays the OSGi bundle information and its status as shown below:

[ 95] [Active ] [ 1] roo-hindi-addon (0.1.0.BUILD-SNAPSHOT)

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 11 of 29

Page 12: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

7. Again, type web mvc language –code and press the tab key. Thistime, you will see a code for the Hindi language. Choose the hi code, andHindi language support will be added to your application.

web mvc language –code hi

8. Exit the Roo shell and type mvn tomcat:run. You will see the India flagin the footer. Click on the flag, and your application will be displayed inHindi, as shown in Figure 2.Figure 2. Hindi language support

Once you have tested that the add-on is working fine in your development system,you can push the add-on to the Google code project we created.

Under the hood

Now that we have seen that the add-on we have created works, let's take a look athow the Hindi language was made available to the application:

1. The roo-hindi-addon was started using osgi start command.

2. When the add-on starts, the HindiLanguage class that was created bythe addon create i18n command gets registered withi18nComponent, which is an OSGi service listener for registering andunregistering i18n add-ons. The HindiLanguage class is marked with@Component and @Service annotations, which are provided by ApacheFelix. These annotations make sure that the components and servicesare registered with the Roo shell and are available for use.

3. When we typed the web mvc install language –code commandand pressed the tab key, the tab completion service calls thei18nComponent class getSupportedLanguages() method, whichreturns the java.util.Set of i18n add-ons. Because HindiLanguagewas already registered with i18nComponent, it was also returned.

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 12 of 29

Page 13: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Publishing add-ons to the outside world

It's easy to publish the add-on to the outside world because the Roo createcommand has done most of the things for us by installing all the required Mavenplugins. Go to the project root directory and type the commands from Listing 6.

Listing 6. Publishing the Roo project

svn add pom.xml src/ legal/ readme.txtsvn commit -m "Roo Hindi Addon first version"mvn release:prepare release:perform

The Maven release plugin will ask for the release version, tag name, anddevelopment version. You can just choose the default and proceed forward. It willtake couple of minutes to release and publish the artifacts to the Google codeproject. You can then view the add-on artifacts in your Google code project.

Registering your add-on with RooBot

Once you have released your plugin, you can email it to [email protected] toregister your add-on repository. The email subject line must contain therepository.xml file. For example, for the add-on we just created, the repository.xml ishttp://code.google.com/p/roo-hindi-addon/source/browse/repo/repository.xml. Formore information on registering with RooBot, please refer to Spring Roodocumentation.

I want to Monitor my Java application (simple add-on creation)

It is a common requirement in many enterprise applications that you want to monitoryour Java application to determine application performance bottlenecks. I also hadthe same requirement, so I decided to look at some available open source solutions.Java Application Monitor (JAMon) is a free, high-performance, thread-safe Java APIthat allows you to easily monitor production applications.

To add JAMon support in your web application:

1. You must add jamon JAR in your pom.xml.

2. You must define a JamonPerformanceMonitorInterceptor bean inyour application context file. The sample bean definition looks like thecode in Listing 7.

Listing 7. JamonPerformanceMonitorInterceptor code

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 13 of 29

Page 14: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

<bean id="jamonPerformanceMonitorInterceptor"class=\

"org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"><property name="trackAllInvocations" value="true"></property><property name="useDynamicLogger" value="true"></property>

</bean>

<bean id="autoProxyCreator"class=\

"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="interceptorNames">

<list><idref bean="jamonPerformanceMonitorInterceptor" />

</list></property><property name="beanNames">

<list><value>speakerController</value><value>talkController</value>

</list></property>

</bean>

This is not a simple bean definition that any developer can easily remember, and Ithought that it would be great if I could automate this boilerplate configuration. So Idecided to write an add-on that can automate the process of adding the JAMondependency and wiring the interceptor bean. How do you decide if you need asimple or advanced add-on?

1. Use a simple add-on when you want to add Maven dependencies, addconfiguration artifacts, or add both to your project.

2. Use an advanced add-on when you need to write full-fledged add-onsthat enhance existing Java types, introduce new Java types and AspectJITDs, or do both your project.

Our requirement is to add jamon.jar to the classpath and write an application contextfile that will contain our bean definition. It is better to write a new Spring applicationcontext file rather than using the existing context files because it helps modularizeapplication contexts. From these requirements, it is clear that we should write asimple add-on that can add JAMon support to any web application.

Project setup

We need to do the setup for the project the same way as we did for theinternationalization add-on. I will name this project "spring-roo-addon-jamon".

Creating a simple add-on

Once you have set up the project, you will have a directory namedspring-roo-addon-jamon with just the .svn folder. Go into thespring-roo-addon-jamon directory and start the Spring Roo shell. Then, type the

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 14 of 29

Page 15: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

following command:

addon create simple --topLevelPackage org.xebia.roo.addon.jamon \--projectName spring-roo-addon-jamon

That's it! The add-on is created.

Installing the generated add-on

You can install the add-on using this command:

osgi start --url file://<Location to addontarget folder>/org.xebia.roo.addon.jamon-0.1.0.BUILD-SNAPSHOT.jar

Once you have installed the add-on, create a simple client as we created for the i18nadd-on to test. The generated add-on gives two commands:

1. say hello, a command that prints a welcome message on the Rooshell. This command will be always available, and you can type it anytimewhile the Roo shell is running.

2. web mvc install tags replaces the default MVC tags generatedwhen you scaffold a web application. This command will only be availablewhen you have created a web application.

Looking at the generated code

Now that you have tested the add-on, let's take a look at the files generated by thisadd-on, shown in Listing 8.

Listing 8. Files generated for spring-roo-addon-jamon

Created ROOT/pom.xmlCreated ROOT/readme.txtCreated ROOT/legalCreated ROOT/legal/LICENSE.TXTCreated SRC_MAIN_JAVACreated SRC_MAIN_RESOURCESCreated SRC_TEST_JAVACreated SRC_TEST_RESOURCESCreated SRC_MAIN_WEBAPPCreated SRC_MAIN_RESOURCES/META-INF/springCreated SRC_MAIN_JAVA/com/shekhar/roo/addon/jamonCreated SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonCommands.javaCreated SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonOperations.javaCreated SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonOperationsImpl.javaCreated SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonPropertyName.javaCreated ROOT/src/main/assemblyCreated ROOT/src/main/assembly/assembly.xmlCreated SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamonCreated SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon/info.tagx

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 15 of 29

Page 16: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon/show.tagx

The artifacts pom.xml, assembly.xml, LICENSE.TXT, and readme.txt are the sameas generated by the i18n add-on. We discussed them above, so I am not going totalk about them here again. The artifacts that are of more interest areJamonCommands, JamonOperations, JamonOperationsImpl, andJamonPropertyName. Let's talk about them one by one to get an understanding ofthe code generated by simple add-on command.

1. JamonCommands.java:JamonCommands — This is a class thatimplements a marker interface called CommandMarker and exposes twocommands, say hello and web mvc install tags, as shown in Listing 9.Listing 9. Generated code fromJamonCommands.java:JamonCommands

@Component@Servicepublic class JamonCommands implements CommandMarker {

@Reference private JamonOperations operations;

@Reference private StaticFieldConverter staticFieldConverter;

protected void activate(ComponentContext context) {staticFieldConverter.add(JamonPropertyName.class);}

protected void deactivate(ComponentContext context) {staticFieldConverter.remove(JamonPropertyName.class);

}

@CliAvailabilityIndicator("say hello")public boolean isSayHelloAvailable() {

return true;}

@CliCommand(value = "say hello",help = "Prints welcome message to the Roo shell")

public void sayHello(@CliOption(key = "name", mandatory = true,

help = "State your name") String name,@CliOption(key = "contryOfOrigin", mandatory = false,

help = "Country of origin") JamonPropertyName country) {

log.info("Welcome " + name + "!");log.warning("Country of origin: " + (country == null ? \

JamonPropertyName.NOT_SPECIFIED.getPropertyName() : country.getPropertyName()));

log.severe("It seems you are a running JDK "+ operations.getProperty("java.version"));

log.info("You can use the default JDK logger anywhere in your"+ " add-on to send messages to the Roo shell");

}

@CliAvailabilityIndicator("web mvc install tags")public boolean isInstallTagsCommandAvailable() {

return operations.isInstallTagsCommandAvailable();

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 16 of 29

Page 17: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

}

@CliCommand(value = "web mvc install tags",help="Replace default Roo MVC tags used for scaffolding")

public void installTags() {operations.installTags();

}}

I have removed all the comments generated by the code generator toreduce the verbosity of the code. Let's take a look at important membersof this class:

a. CommandMarker — All the command classes should implementthe CommandMarker interface and should be annotated with@Component and @Service annotations so they are registeredand their commands become available in the Roo shell. The fieldsannotated with @Reference are dependencies of theJamonCommands class are injected by the underlying Roo OSGicontainer. All the classes annotated with @Component and@Service annotations can be injected into other add-ons.

b. Activate and Deactivate Methods — The activate anddeactivate methods are the methods called when you install theadd-on using the addon install command or remove theadd-on using the addon remove command. These methodsallows you to hook into the lifecycle of the add-on, which ismanaged by the underlying Roo OSGi container.

c. Methods annotated with @CliAvailabilityIndicator —The methods annotated with @CliAvailabilityIndicator arethe methods that help hide commands when they are not available.For example, the security setup command, which installsSpring Security into the project, is not visible until the project is aweb application. It is not required that you should have suchmethods, but they are useful as they don't allow user to firecommands that do not make sense at that point in time. Forexample, executing the security setup command before the userhas a web application does not make any sense.

d. Methods annotated with @CliCommand — The methodsannotated with @CliCommand registers the command with the Rooshell. The @CliCommand annotation has two attributes: value,which defines the command name, and help, which defines thehelp message shown when you type the help command. Everycommand can define mandatory and non-mandatory attributesusing the @CliOption annotation, presented as a part of the

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 17 of 29

Page 18: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

command. For example, the say hello command has amandatory attribute called name and non-mandatory attributecalled country.

3. JamonOperationsImpl.java — Command classes need to perform someoperations when a command is executed. These operations areperformed by operation classes. JamonOperationsImpl is anoperations class responsible for doing the actual work, like adding adependency in the pom.xml or copying resources to the desired location.The JamonOperationsImpl class performs its operations by using coreservices provided by the Spring Roo framework. For example, to add adependency, it uses the ProjectOperations interface. To copy thefiles, it uses the FileManager interface. Let's take a look at the code forthe JamonOperationsImpl class (see Listing 10) to get a betterunderstanding of the Roo add-on.Listing 10. JamonOpertionsImpl

@Component@Servicepublic class JamonOperationsImpl implements JamonOperations {

private static final char SEPARATOR = File.separatorChar;

@Reference private FileManager fileManager;@Reference private ProjectOperations projectOperations;

public boolean isInstallTagsCommandAvailable() {return projectOperations.isProjectAvailable() &&

fileManager.exists(projectOperations.getProjectMetadata().getPathResolver().getIdentifier(Path.SRC_MAIN_WEBAPP,

"WEB-INF" + SEPARATOR + "tags"));}

public String getProperty(String propertyName) {Assert.hasText(propertyName, "Property name required");return System.getProperty(propertyName);

}

public void installTags() {PathResolver pathResolver =

projectOperations.getProjectMetadata().getPathResolver();createOrReplaceFile(pathResolver.getIdentifier(

Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR +"tags" + SEPARATOR + "util"), "info.tagx");

createOrReplaceFile(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR +

"tags" + SEPARATOR + "form"), "show.tagx");}

private void createOrReplaceFile(String path, String fileName) {String targetFile = path + SEPARATOR + fileName;MutableFile mutableFile = fileManager.exists(targetFile) ?

fileManager.updateFile(targetFile) :fileManager.createFile(targetFile);

try {FileCopyUtils.copy(TemplateUtils.getTemplate(getClass(),

fileName), mutableFile.getOutputStream());} catch (IOException e) {

throw new IllegalStateException(e);}

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 18 of 29

Page 19: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

}}

JamonOperationsImpl class has two important methods:isInstallTagsCommandAvailable checks whether the command isavailable, and installTags installs the tags into the target project. Toperform these operations the JamonOperationsImpl class uses someSpring Roo core services and utilities:

1. The ProjectOperations : JamonOperationsImpl classuses the ProjectOperations service to check whether theproject is available and to get path of the tags folder.

2. The FileManager : JamonOperationsImpl class uses theFileManager service to check whether a file exists at a certainpath and to get the update or create a MutableFile.MutableFile is another Roo-specific class which represents ahandle to a file which can be modified.

3. The TemplateUtils : TemplateUtils utility class is used toacquire an InputStream to template files (info.tagx andshow.tagx) in our add-on bundle.

4. The FileCopyUtils : FileCopyUtils utility class is usedcopy the templates (from TemplateUtils) to the MutableFile(from FileManager).

Modifying an add-on to meet our requirements

In the first section about a simple add-on, we discussed two requirements that wemust meet so our add-on can configure JAMon in any Spring MVC web application.The requirements were:

1. Add JAMon JAR in your pom.xml

2. Define a JamonPerformanceMonitorInterceptor bean in the applicationcontext file

To meet these requirements, we will make changes in the JamonCommands class tosupport the jamon setup command. Then we will add one operationcorresponding to the jamon setup command to do the actual work to meet therequirements.

JamonCommands — The JamonCommands class will now have just two methods:isInstallJamon to check whether the jamon setup command is available, and

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 19 of 29

Page 20: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

installJamon to install JAMon when the jamon setup command is fired. (SeeListing 11.)

Listing 11. Code for JamonCommands

@Component@Servicepublic class JamonCommands implements CommandMarker {

private Logger log = Logger.getLogger(getClass().getName());

@Reference private JamonOperations operations;

@CliAvailabilityIndicator("jamon setup")public boolean isInstallJamon() {

return operations.isInstallJamonAvailable();}

@CliCommand(value = "jamon setup", help = "Setup Jamon into your project")public void installJamon() {

operations.installJamon();}

}

This is all we need in JamonCommands class. It just needs to expose the jamonsetup command, and the rest of the work is delegated to theJamonOperationsImpl class. (See Listing 12.)

Listing 12. Code for JamonOperationsImpl

JamonOperationsImpl

JamonOperationsImpl need to implement two methods – \isInstallJamonAvailable() and installJamon().

The isinstallJamonAvailable() method returns a boolean indicating whethercommand is available at this location or not. I want to enable JAMon only for the webapplications so we need to perform the check whether the project isa web application or not. To do that we will write the code as shown below

public boolean isInstallJamonAvailable() {return projectOperations.isProjectAvailable() &&

fileManager.exists(projectOperations.getPathResolver().getIdentifier(Path.SRC_MAIN_WEBAPP, "/WEB-INF/web.xml"));

}

The code shown in Listing 12 uses the ProjectOperations service to checkwhether a project is available at this location and to get the path of the web.xml file(the web.xml file only exists for web applications). The FileManager service isused to check whether the web.xml exists at the location specified byProjectOperations.

The second method we need to implement is installJamon(), which should addJAMon dependency in pom.xml and add the bean definition to the

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 20 of 29

Page 21: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

webmvc-config.xml. Before we write code for this method, we must create an XMLfile named configuration.xml inside thesrc/main/resources/org/xebia/roo/addon/jamon folder. The folder structure,org/xebia/roo/addon/jamon, is the same as package structure of your Roo add-on.The configuration.xml defines the JAMon version and JAMon JAR dependency, asshown in Listing 13.

Listing 13. Contents of configuration.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?><configuration>

<jamon><properties>

<jamon.version>2.4</jamon.version></properties><dependencies>

<dependency><groupId>com.jamonapi</groupId><artifactId>jamon</artifactId><version>${jamon.version}</version>

</dependency></dependencies>

</jamon></configuration>

Let's write the code to add dependency in pom.xml, shown in Listing 14.

Listing 14. Contents of pom.xml

public void installJamon() {Element configuration = XmlUtils.getConfiguration(getClass());updatePomProperties(configuration);updateDependencies(configuration);

}

private void updatePomProperties(Element configuration) {List<Element> properties = \

XmlUtils.findElements("/configuration/jamon/properties/*", configuration);for (Element property : properties) {

projectOperations.addProperty(new Property(property));}

}

private void updateDependencies(Element configuration) {

List<Dependency> dependencies = new ArrayList<Dependency>();List<Element> jamonDependencies = XmlUtils.findElements(

"/configuration/jamon/dependencies/dependency", configuration);for (Element dependencyElement : jamonDependencies) {

dependencies.add(new Dependency(dependencyElement));}projectOperations.addDependencies(dependencies);

}

This is a standard mechanism to add a dependency in pom.xml, and you can find itused in most of the Roo add-ons. The code shown in Listing 14 is self-explanatory

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 21 of 29

Page 22: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

and uses the Spring Roo utility class, XmlUtils, to read the content fromconfiguration.xml and then the ProjectOperations service to update the pom.xmlfile.

Once we have added the pom.xml dependency, we need to create a separateSpring configuration, web-jamon-config.xml, which will contain the bean definition forJamonPerformanceMonitorInterceptor.

Listing 15. Contents of web-jamon-config.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?><beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc" \

xmlns:p="http://www.springframework.org/schema/p"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=\

"http://www.springframework.org/schema/beans \http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context \http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/mvc \http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<bean id="jamonPerformanceMonitorInterceptor"class=\

"org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"><property name="trackAllInvocations" value="true"></property><property name="useDynamicLogger" value="true"></property>

</bean>

<bean id="autoProxyCreator"class=\

"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="interceptorNames">

<list><idref bean="jamonPerformanceMonitorInterceptor" />

</list></property><property name="beanNames">

<list><value></value>

</list></property>

</bean>

</beans>

In the web-jamon-config.xml file shown in Listing 15, we have configured everythingrequired for JAMon in a Spring-based application. The only thing I have not specifiedare the names of the beans to monitor. The code generator cannot predict this, so itis left to the add-on developer to specify.

Now we need to write the code that will copy this web-jamon-config.xml file toWEB_INF/spring folder, where webmvc-config.xml resides, and code for the addimport statement in webmvc-config.xml to import web-jamon-config.xml. (SeeListing 16.)

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 22 of 29

Page 23: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Listing 16. Code to manipulate pom.xml

public void installJamon() {

// update pom.xml codePathResolver pathResolver =

projectOperations.getProjectMetadata().getPathResolver();String resolvedSpringConfigPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP,

"/WEB-INF/spring");if (fileManager.exists(resolvedSpringConfigPath + "/web-jamon-config.xml")) {

return;}copyTemplate("web-jamon-config.xml", resolvedSpringConfigPath);

String webMvcConfigPath = resolvedSpringConfigPath + "/webmvc-config.xml";

new XmlTemplate(fileManager).update(webMvcConfigPath, new DomElementCallback() {public boolean doWithElement(Document document, Element root) {

if (null ==XmlUtils.findFirstElement\

("/beans/import[@resource='web-jamon-config.xml']",root)) {Element element = document.createElement("import");

element.setAttribute("resource", "web-jamon-config.xml");root.appendChild(element);

return true;}return false;}

});

}

private void copyTemplate(String templateFileName, String resolvedTargetDirectoryPath) {

try {FileCopyUtils.copy(TemplateUtils.getTemplate(getClass(),

templateFileName), fileManager.createFile(resolvedTargetDirectoryPath + "/" +templateFileName).getOutputStream());

} catch (IOException e) {throw new IllegalStateException(

"Encountered an error during copying of resources for Jamon addon.", e);}

}

The XmlTemplate class used above comes from the Spring web flow add-on. Soyou need to add a dependency for the web flow add-on in your add-on. (See Listing17.)

Listing 17. Add dependency for web flow add-on

<dependency><groupId>org.springframework.roo</groupId><artifactId>org.springframework.roo.addon.web.flow</artifactId><version>${roo.version}</version>

<type>bundle</type>

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 23 of 29

Page 24: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

</dependency>

In Listing 17, roo.version is the version of Roo you are using.

The last thing we need to do in this add-on is to configure project logging and set upthe log level to trace. This is done using LoggingOperations, which is anoperations class for the log4j add-on. To use this class, we need to first add thelogging add-on dependency in pom.xml file, as shown in Listing 18.

Listing 18. XML code to add dependency for the logging add-on

<dependency><groupId>org.springframework.roo</groupId><artifactId>org.springframework.roo.addon.logging</artifactId><version>${roo.version}</version>

<type>bundle</type></dependency>

After adding the dependency in pom.xml, add LoggingOperation into theJamonOperationsImpl class with the following line:

@Reference private LoggingOperations loggingOperations;

Next, add the following line to the installJamon method:

loggingOperations.configureLogging(LogLevel.TRACE, LoggerPackage.PROJECT);

That's all the code we need to write for this add-on. The full code forJamonOperationsImpl class is shown in Listing 19.

Listing 19. Completed code for JamonOperationsImpl

@Component@Servicepublic class JamonOperationsImpl implements JamonOperations {

@Reference private FileManager fileManager;@Reference private ProjectOperations projectOperations;@Reference private LoggingOperations loggingOperations;

public boolean isInstallJamonAvailable() {return projectOperations.isProjectAvailable() &&

fileManager.exists(projectOperations.getPathResolver().getIdentifier(Path.SRC_MAIN_WEBAPP,"/WEB-INF/web.xml"));

}

public void installJamon() {Element configuration = XmlUtils.getConfiguration(getClass());updatePomProperties(configuration);updateDependencies(configuration);PathResolver pathResolver =

projectOperations.getProjectMetadata().getPathResolver();

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 24 of 29

Page 25: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

String resolvedSpringConfigPath =pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP,

"/WEB-INF/spring");if (fileManager.exists(resolvedSpringConfigPath

+ "/web-jamon-config.xml")) {return;

}

copyTemplate("web-jamon-config.xml", resolvedSpringConfigPath);

String webMvcConfigPath = resolvedSpringConfigPath+ "/webmvc-config.xml";

new XmlTemplate(fileManager).update(webMvcConfigPath,new DomElementCallback() {

public boolean doWithElement(Document document, Element root) {if (null == XmlUtils.findFirstElement(

"/beans/import[@resource='web-jamon-config.xml']",root)) {

Element element = document.createElement("import");element.setAttribute("resource", "web-jamon-config.xml");root.appendChild(element);return true;

}return false;

}});loggingOperations.configureLogging(LogLevel.TRACE,

LoggerPackage.PROJECT);}

private void copyTemplate(String templateFileName,String resolvedTargetDirectoryPath) {

try {FileCopyUtils.copy(

TemplateUtils.getTemplate(getClass(), templateFileName),fileManager.createFile(resolvedTargetDirectoryPath + "/" +templateFileName).getOutputStream());} catch (IOException e) {

throw new IllegalStateException("Encountered an error during copying of resources for Jamon addon.", e);}

}

private void updatePomProperties(Element configuration) {List<Element> properties = XmlUtils

.findElements("/configuration/jamon/properties/*",configuration);for (Element property : properties) {

projectOperations.addProperty(new Property(property));}

}

private void updateDependencies(Element configuration) {List<Dependency> dependencies = new ArrayList<Dependency>();List<Element> jamonDependencies = XmlUtils.findElements(

"/configuration/jamon/dependencies/dependency", configuration);for (Element dependencyElement : jamonDependencies) {

dependencies.add(new Dependency(dependencyElement));}projectOperations.addDependencies(dependencies);

}

}

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 25 of 29

Page 26: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

You can download the full source code of this add-on from the Google coderepository. Now, let's add JAMon support to our application, using the add-on wehave just created:

1. Exit the roo shell and run the mvn clean install command. Duringthe build process it will ask for GPG passphrase.

2. After the Roo add-on has been built, open a new command line andcreate a directory named jamon-client. We will create a simple client forour add-on.

3. Go to the directory jamon-client and type the roo command to open aRoo shell.

4. Execute the commands from Listing 20 in the Roo shell. This will create asimple Spring MVC web application.Listing 20. Create simple MVC web application

project --topLevelPackage com.shekhar.roo.jamon.client --projectName jamon-clientpersistence setup --provider HIBERNATE --databaseHYPERSONIC_IN_MEMORYentity --class ~.domain.MyUserfield string --fieldName name --notNullcontroller all --package ~.web

5. To install the add-on, type:osgi start --url <ahref="../../../../">file:///</a><location \to addon target folder >/org.xebia.roo.addon.jamon-0.1.0.BUILD-SNAPSHOT.jar

This should install and activate our JAMon add-on. You can view thestatus of the add-on using the osgi ps command.

6. Type the jamon setup command and you will see JAMon beingconfigured in your application. If you now run your application using mvntomcat:run, you will not see any logs on the console because you havenot configured any bean to monitor. Let's configure ourmyUserController bean in web-jamon-config.xml with the code fromListing 21.Listing 21. Configuration for myUserController inweb-jamon-config.xml

<bean id="autoProxyCreator"class=\

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 26 of 29

Page 27: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"><property name="interceptorNames">

<list><idref bean="jamonPerformanceMonitorInterceptor" />

</list></property><property name="beanNames">

<list><value>myUserController</value>

</list></property>

</bean>

7. Now run the application using mvn tomcat:run and you will see JAMonlogs in your the maven console. A sample is shown in Listing 22.Listing 22. Sample JAMon log

TRACE MyUserController - JAMon performance statistics for method[MyUserController.populateMyUsers]:JAMon Label=MyUserController.populateMyUsers, Units=ms.: (LastValue=187.0,Hits=1.0, Avg=187.0, Total=187.0, Min=187.0, Max=187.0, Active=0.0, AvgActive=1.0, Max Active=1.0, First Access=Wed May 18 15:33:41 IST 2011, LastAccess=Wed May 18 15:33:41 IST 2011)

Once you have tested that your add-on is working fine in your development system,you can push it to the Google code project we created. To publish the add-on to theoutside world, follow the same procedure we used to publish the i18n add-on.Likewise, to register the add-on with RooBot, follow the i18n registration procedure.

Conclusion

We have looked at the Spring Roo add-on architecture and how to writeinternationalization and simple add-ons. The add-on architecture is important forRoo because it gives Roo the flexibility to quickly add new features. For developers,this add-on architecture is important because it allows them to meet theirrequirements without having to wait for features to be implemented globally. Lateron, if a feature is incorporated into Roo, it is relatively easy to change out theimplementation to remove the custom solution.

In Part 4 of this "Introducing Spring Roo" series, I will talk about how you can writeadvanced and wrapper add-ons.

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 27 of 29

Page 28: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Resources

Learn

• Be sure to read Part 1 and Part 2 of this series.

• Learn more about Spring Roo functions by reading the Spring Roodocumentation.

• Give and receive help in the Spring Roo Community Forums.

• To listen to interesting interviews and discussions for software developers,check out developerWorks podcasts.

• Stay current with developerWorks' Technical events and webcasts.

• Follow developerWorks on Twitter.

• Check out upcoming conferences, trade shows, webcasts, and other Eventsaround the world that are of interest to IBM open source developers.

• Visit the developerWorks Open source zone for extensive how-to information,tools, and project updates to help you develop with open source technologiesand use them with IBM's products, as well as our most popular articles andtutorials.

• Watch and learn about IBM and open source technologies and productfunctions with the no-cost developerWorks On demand demos.

Get products and technologies

• Innovate your next open source development project with IBM trial software,available for download or on DVD.

• Download IBM product evaluation versions or explore the online trials in theIBM SOA Sandbox and get your hands on application development tools andmiddleware products from DB2®, Lotus®, Rational®, Tivoli®, andWebSphere®.

Discuss

• Participate in developerWorks blogs and get involved in the developerWorkscommunity.

• Get involved in the developerWorks community. Connect with otherdeveloperWorks users while exploring the developer-driven blogs, forums,groups, and wikis.

About the author

developerWorks® ibm.com/developerWorks

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 28 of 29

Page 29: Introducing Spring Roo, Part 3: Developing Spring Roo add-onspublic.dhe.ibm.com/software/dw/opensource/os-springroo3/os-sprin… · In Part 1 and Part 2 of this "Introducing Spring

Shekhar GulatiShekhar Gulati is a Java consultant working with Xebia India. He hassix years of enterprise Java experience. He has extensive experience inSpring portfolio projects, such as Spring, Spring-WS, Spring Roo, etc.His interests are Spring, NoSQL databases, Hadoop, RAD frameworkslike Spring Roo, cloud computing (mainly PaaS services like GoogleApp Engine, CloudFoundry, OpenShift), Hadoop. He is an active writerand writes for JavaLobby, Developer.com, IBM developerWorks and hisown blog at http://whyjava.wordpress.com/. You can follow him ontwitter @ http://twitter.com/#!/shekhargulati.

ibm.com/developerWorks developerWorks®

Developing Spring Roo add-ons Trademarks© Copyright IBM Corporation 2011 Page 29 of 29


Recommended