This document provides an overview of creating and distributing Spring Roo add-ons. It discusses the architectural journey that led to Roo's design, including decisions to use Java and AspectJ rather than creating a new runtime. It also covers getting started with a new add-on using the Add-on Creator, implementation details like using common services and file monitoring, and how to develop add-ons that integrate with the Roo shell and OSGi container. The document concludes with pointers for starters, like reviewing example add-ons and Spring Roo source code.
4. Design Goals
• High productivity for Java developers
– Reuse their existing knowledge, skills and experience
• Eliminate barriers to adoption
– Lock-in, runtime, size, development experience
• Embrace the strengths of Java
– Dev-time: tooling, popularity, API quality, static typing
– Deploy-time: performance, memory use, footprint
5. High-Impact Decisions
• Use Java
– This is a tool for Java developers
– It defeats the purpose if we insist on a new language
• Don't create a runtime
– This avoids bugs, lock-in, adoption barriers, approvals
– This avoids CPU cost, RAM cost and footprint cost
• This easily led to some sort of generation model
6. Prototyped Approaches
• Pluggable Annotation Processing API (JSR 269)
• Generate source at build time (XDoclet-style)
• Generate bytecode at build time (ASM)
• Generate bytecode at runtime (ASM)
• Advanced proxy-based approaches (Spring AOP)
• IDE plugins
• None of them satisfied all of the design goals
7. Decision 1: Use AspectJ
• AspectJ ITDs for “active” generation
– Active generation automatically maintains output
• Delivers compilation unit separation of concern
– Easier for users, and easier for us as developers
• Instant IDE support
– Reduce time to market and adoption barriers
• Other good reasons
– Mature, “push in” refactor, compile-time is welcome
8. ITD Model
• Roo owns *_Roo_*.aj files
– Will delete them if necessary
• Every ITD provider registers a “suffix” it uses
– Eg “Entity” becomes *_Roo_Entity.aj
– A missing ITD provider causes AJ file removal
• ITDs have proper import management
– So they look and feel normal to developers
– So they “push in refactor” in a natural form
9. Decision 2: Create A Shell
• Need something to host the “active” generation
• Need something to receive user commands
• Usability issues were of extremely high priority
• We chose an interactive shell
– Highest usability (tab, context awareness, hiding, hints...)
– Background monitoring of externally-made changes
– Background monitoring avoided crude “generate” steps
10. Shell Model
• Shell will perform a “startup” scan
– To handle changes made while it wasn't running
• Shell will monitor file system once started
– To handle changes made while it is running
• Shell will have a set of commands registered
– To handle explicit directives from the user
• Roo will never modify a *.java file except at the explicit
request of a user via a shell command
14. Add-on Creator
• ‘Add-on Creator’ itself is a Roo add-on
• Quick start for Roo add-on development
• Currently supports three types of add-ons:
– Simple Add-on
• ideal for small additions to project dependencies and/or
configuration
– Advanced Add-on
• ideal for starting fully-fledged Spring Roo add-ons
– Internationalization Extension for MVC scaffolding
• ideal for offering new language translations for Roo’s
scaffolded Spring MVC admin UI
15. Add-on Creator
• Project Maven pom.xml is configured for
– hosting in SVN repository
– easy creation of Maven repository
– automatic generation of PgP signed artifacts
• Optimized for hosting as Google Code projects
• Add-ons are compliant with RooBot
– PgP signed artifacts with public keys
– Generation of OSGi compliant bundles
– use of httppgp protocol
16. New Add-on command (Simple)
• Three new commands in version 1.1.x of Roo
– ‘addon create simple’
• What: Command & Operations support
• When: Simple add-ons which want to add dependencies and/
or configuration artifacts to project
• Example:
– addon create simple --topLevelPackage com.foo.batch
– optional attributes
» projectName (can use this to map to Google code project names)
» description (Meaningful description of add-on)
17. New Add-on Commands (Advanced)
– ‘addon create advanced’
• What: Command, Operations & ITD support
• When: Full-fledged add-ons which offer new functionality to
project
– enhancements to existing Java types in project
– introduction of new Java types (+ ITDs)
• Example:
– addon create advanced --topLevelPackage com.foo.batch
– optional attributes
» projectName (can use this to map to Google code project names)
» description (Meaningful description of add-on)
18. New Add-on command (i18n)
– ‘addon create i18n’
• What: extension to the existing ‘web mvc install language’
command
• Example:
– addon create i18n --topLevelPackage com.foo.ru --locale
ru --messageBundle <path-to>/messages_ru.properties
– optional attributes
» projectName (can use this to map to Google code project names)
» description (Meaningful description of add-on)
» flagGraphic* (provide a custom flag icon for UI use)
» language** (provide a meaningful language name)
* based on the ISO 3166 country code Roo will attempt to download the graphic automatically
** based on the ISO 3166 country code Roo will attempt to determine the language name
automatically
20. RooBot
• RooBot is a Vmware hosted service for Roo add-on
registration
• Register new add-on repository by Email
– send email to s2-roobot@vmware.com
– subject line: MUST be URL to OSGi repository definition
• ie: http://spring-roo-simple-addon.googlecode.com/svn/repo/repository.xml
– body: currently not used (but you can send greetings to the
Roo team ;-)
– other interaction forms planned
• Web front-end,
• Roo shell command
21. RooBot requirements
RooBot verifies:
– the provided repository.xml is a OSGi Repository
– the resource URI must use the httppgp prefix
• ie: <resource uri="httppgp://fr-test.googlecode.com/svn/…/>
– the referenced bundle in the repository has a
corresponding .asc file containing the PgP public key
– RooBot will retrieve publicly accessible key information (key
owner name, email) from public key server
– the referenced bundle contains a OSGi compliant
manifest.mf file
22. RooBot
• RooBot compliant add-on bundles
– are registered in a publicly accessible roobot.xml file
• http://spring-roo-repository.springsource.org/roobot.xml
– popularity of bundles registered (soon)
• RooBot Roo Shell client
– addon list (lists all known add-ons)
• optional ’--refresh’ attribute
– addon info --bundleSymbolicName <TAB>
– addon install --bundleSymbolicName <TAB>
– PgP trust model integrated
– addon suggestions for unknown commands
24. Metadata
• Project details
– Project name, dependencies, build system...
• Java type details
– Fields, methods, constructors, inheritance...
• Higher-level concepts
– Entity properties, controller paths, validation rules...
• Must be automatically determined from project
– With @Roo* (source level retention) where infeasible
25. Metadata Model
• Immutable
– String-based keys (start with “MID:”)
– Built on demand only (never persisted)
• Metadata can depend on other metadata
– If “upsteam” metadata changes, “downstream” is told
– Some metadata will want to monitor the file system
• Central metadata service and cache required
26. Conventions we follow
• Ensure usability is first-class
• Minimize the JAR footprint that Roo requires
• Relocate runtime needs to sister Spring projects
• Embrace immutability as much as possible
• Maximize performance in generated code
• Minimize memory consumption in generated code
• Use long artifact IDs to facilitate identification
• Don't put into @Roo* what you could calculate
• Don't violate generator predictability conventions
27. Role of Third Party Add-Ons
• 3rd party add-ons have a long-term role in Roo
• Minimize download size of Roo distribution
• Avoid licensing issues with Roo distribution
• Facilitate features of more niche interest
• Separate project management and maintenance
• Enable end user customization
• Provide a sandbox for easy experimentation
29. File Monitor API
• Mostly used by project and classpath modules
– Rare for an add-on to directly use file monitor
• Publishes startup and “on change” events
• Events
– Create
– Update
– Delete
– Rename (if implementation supported)
– Monitoring start (for each file when first found)
30. File Monitor Implementation
• Polling-based implementation
• Auto-scales to reduce CPU overhead
• Shell commands
– “poll status” → indicates scan frequency and duration
– “poll speed” → allows specification of frequency
– “poll now” → forces an immediate poll
31. Common Services
• Services
– o.s.roo.process.manager.FileManager
• use file manager for all file system operations in project (offers
automatic undo on exception)
– o.s.roo.project.PathResolver
• offers abstraction over common project paths
– o.s.roo.metadata.MetadataService
• offers access to Roo metadata
– bean info metadata for mutators/accessors of target type
– o.s.roo.project.ProjectMetadata
• project name, top level package
• read access to project dependencies, repositories, etc
32. Common Utils
• o.s.roo.support.util.Assert
– similar to Spring’s Assert
• o.s.roo.support.util.FileCopyUtils
– useful for copying resources from add-on into project
• o.s.roo.support.util.TemplateUtils
– useful for obtaining InputStream of resources in bundle
• o.s.roo.support.util.XmlUtils
– hides XML ugliness
• writeXml methods
• Xpath abstraction
33. Source Code Metadata Abstraction
• o.s.roo.classpath.details.*MetadataBuilder types
– FieldMetadataBuilder
– MethodMetadataBuilder
• most commonly used builder during add-on development
– ConstructorMedataBuilder
– AnnotationMetadataBuilder
35. Roo Shell
• Implementations for STS and JLine
• Add-ons should
– Make a “Command” class and implement CommandMaker
– Delegate methods through to an “Operations” object
– Annotate methods with @CliCommand
– Annotate method parameters with @CliOption
– Optionally use @CliAvailabilityIndicator if desired
– Throw any exceptions to abort and rollback changes
– Use JDK logging or return objects for console output
36. Development mode
• Enable via
– Loading Roo via roo-dev shell script
– JVM property developmentMode = true
– Typing “development mode” at the roo> shell prompt
• Outputs full exception traces within Roo
– Ugly for normal usage (exceptions are the normal way that
an add-ons abort from unexpected conditions)
• First line of troubleshooting add-on bugs is to ask for
“development mode” exception data
37. OSGi
• Roo runs in an OSGi container since version 1.1
– ideal for Roo’s add-on model
– developers can install, uninstall, start, and stop different
add-ons dynamically without restarting the Roo shell
– automatic provisioning of external add-on repositories
– OSGi provides very good infrastructure for developing
modular, as well as embedded, and service-oriented
applications
– Roo uses Apache Felix OSGi implementation
38. OSGi Container & Roo Shell
• ‘osgi’ commands
– osgi ps displays OSGi bundle information & status
– osgi log access OSGi container logs
– osgi scr info info about a specific component
– help osgi help to ~20 osgi commands
• ‘addon install’ command
– addon install high level abstraction for
‘felix shell start httppgp://…’
39. Development with OSGi
• Technical implications minimal:
– use Apache Felix Annotations
• @Service offer functionality to other add-ons; must use
interfaces
• @Component (required) for OSGi container
• @Reference allows injection of services by other bundles
– Manifests are (auto-)generated by Maven bundle plugin
• Reference other Roo bundles or OSGi compliant
dependencies in the add-on pom.xml
40. Development with OSGi
• Use activate method for
– inititalization tasks performed at bundle startup
– metadata dependency registration
• Don’t forget deactivate method
// example from JsonMetadataProviderImpl"
protected void activate(ComponentContext context) {"
metadataDependencyRegistry.registerDependency (…);"
addMetadataTrigger(new JavaType(RooJson.class.getName()));"
addMetadataTrigger(new JavaType(”org.springf.roo.addon.entity.RooIdentifier"));"
}"
protected void deactivate(ComponentContext context) {"
metadataDependencyRegistry.deregisterDependency(..);"
removeMetadataTrigger(new JavaType(RooJson.class.getName()));"
}"
43. Add-on Development Examples
• Roo 30+ core add-ons provide plenty of examples
addon-create a typical simple add-on with
commands and operations
addon-toString a simple ITD-providing add-on with
trigger annotation
addon-json a ‘classic’ add-on with commands,
operations, ITD & trigger annotation
44. Spring Roo Sources
• We develop against a public Git repository
– You can anonymously checkout the code
– git clone git://git.springsource.org/roo/roo.git spring-roo
• Review source code without Git
– http://git.springsource.org/roo/roo/trees/master
– https://fisheye.springsource.org/changelog/spring-roo
• Roo itself uses Maven, so it's very easy to build
– Standard package, install, assembly and site goal
– PgP should be installed
– see readme.txt in Roo master root for details