Roo has been become more and more powerful and offers more options for users on how to use Roo. This in turn makes it more challenging in some scenarios to use Roo in a consistent way throughout a project.
The tailor addon enables:
Teams working on large projects to ensure streamlined Roo usage according to their project's standards and guidelines
Single users to define the approach they usually take in one file to reuse it over multiple projects
Examples of use cases:
A team does not want to use the Active Record pattern for entities, but always wants developers to specify "--activeRecord false", and create a JPA repository based on every new entity.
A developer always uses a certain project structure to create web projects, for exmple a Maven project with 2 modules called "domain" and "web". The developer wants to be able to reuse this structure with the project command, and make sure that the shell automatically focuses on the correct module for certain commands (e.g. entity > domain, web mvc > web).
When tailoring is activated, Roo commands are intercepted by the shell and transformed to a new set of commands according to user specifications obtained from configuration file, if any exist for that particular command. The shell then executes this transformed set of commands instead of the initial command. A user can define one or multiple tailor configurations and activate and deactivate them while working with the shell.
With the tailor add-on, you can define:
Reusable project structures to use with the "project" command
Default target modules for commands.
Default values for command arguments.
Chains of commands, either triggered by an existing command or composed by an alias
Note that although a tailor configuration can save you a lot of time and effort, it cancels out some of the shell's command completion benefits at the same time. For example, some commands are only available in certain modules (e.g. JPA commands are only available in modules with JPA setup). Tailoring a default module for JPA commands like "entity jpa" means that you can execute those commands while focused on modules without JPA setup. But the tailoring only kicks in at execution time, so the shell won't know about it while you are typing. Thus, the shell won't offer command completion for these commands because it thinks they are not available.
tailor list - Shows the list of available tailor configurations. A tailor configuration defines the set of transformation you want executed for certain commands (see next section "Tailor Configuration").
roo> tailor list Available tailor configurations: o webstyle - Web project with 2 modules, DOMAIN and PRESENTATION
tailor activate – Activate one of the available configurations.
roo> tailor activate --name webstyle
"tailor list" indicates which configuration is currently activated:
roo> tailor list
Available tailor configurations:
o webstyle [ ACTIVE ] - Web project with 2 modules, DOMAIN and PRESENTATION
tailor deactivate – Deactivate the tailor mode. There is no active configuration after this command
roo> tailor deactivate
A tailor configuration can be created in two ways:
XML configuration file (no add-on development required)
Directly in Java (requires creation and installation of a new add-on)
Each tailor configuration has one or more command configurations. A command configuration defines a set of Actions that are triggered whenever a certain command is executed. Execution of those actions results in a new list of output commands that will eventually be executed by the shell. A command configuration is triggered whenever a command that starts with a defined string is executed. E.g., if a command configuration defines "web mvc" as a trigger, then it will be used by the tailor every time a "web mvc" subcommand is executed. The order in which you define the command configurations might matter, the tailor will always take the first command configuration that matches a command.
An action is a transformation step to be applied to the command defined in a command configuration. Each action type defines a set of parameters that can be set in a tailor definition. The tailor addon can be extended with more action types by the community.
Actions are executed sequentially by the tailor, so the order in which they are declared matters.
The following actions are currently available:
Adds a command to the list of commands to be executed. Note that each command configuration should have at least one execute action, otherwise the tailor will not lead to any command executions.
Command line to be executed. If empty, this action will add the original command to the list of output commands at this point. (optional)
A comma separated list of arguments that should be removed from the command before execution. This can be useful if the original command is executed ("command" argument not set), and it was enhanced with additional arguments for the benefit of the tailoring. (optional)
If the Roo user does not provide a value for an argument with the given name on the shell, this default value will be chosen.
Name of the Roo command's argument that will get a default value. (mandatory)
Default value for the argument. (mandatory)
If "true", the default value will be chosen even if the user specified an alternative value in the command. (optional, defaults to "false")
Focus on a module, in form of a simple pattern to match against the module names. Does not support regular expressions, just a simple "contains" match. Use this instead of an "execute command 'module focus...'" if you do not want to hard code your module names into the reusable tailor configuration. (mandatory)
Advanced usage: Use a comma-separated list of strings to look for in module names. The comma will be interpreted as "AND" by the search for a module. Use a slash "/" before a string in the list to indicate that this next string must "NOT" be contained in the module name.
This section describes how to create a tailor configuration with XML by examples.
The XML configuration file “tailor.xml” must be placed into the root project folder. Alternatively, you can put a "tailor.xml" into your system's user folder, to maintain tailor configurations that you want to reuse over several projects. The tailor addon will only look for this file if it does not find a tailor.xml file in the project root.
The following configuration defines a chain of commands that will be triggered by the project command, to create a parent project with packaging “pom” with two modules named “projectname-domain” and “projectname-data”.
Note how you can use argument values from the input command as placeholders by using “${argumentname}”.
tailor.xml:
<tailor name="mywebstyle" description="Standards for web projects with 2 modules"> <config command="project"> <action type="defaultvalue" argument="packaging" value="pom" /> <action type="execute" /> <action type="execute" command="module create --moduleName ${projectName}-domain --topLevelPackage ${topLevelPackage}"/> <action type="focus" module="~"/> <action type="execute" command="module create --moduleName ${projectName}-web --topLevelPackage ${topLevelPackage} --packaging war"/> <action type="focus" module="${projectName}-domain"/> </config> </tailor>
Shell:
tailor activate --name mywebstyle
project --topLevelPackage com.foo.sample --projectName myapp
Will result in:
project --topLevelPackage com.foo.sample --projectName mywebapp --packaging pom
module create --moduleName myapp-domain --topLevelPackage com.foo.sample
module focus --moduleName ~
module create --moduleName myapp-web --topLevelPackage com.foo.sample --packaging war
module focus --moduleName myapp-domain
The following example shows how to tailor the “entity jpa” command with a default value for the "activeRecord" argument, and a default module to put all entities in.
Note that the module name value for the "focus" action is interpreted as "module name contains x". That is why this example works with the project setup described in the previous example, which sets up a module named "${projectName]-domain".
tailor.xml:
<config command="entity jpa">
<action type="focus" module="domain"/>
<action type="defaultvalue" argument="--activeRecord" value="false"/>
<action type="execute"/>
</config>
Shell:
entity jpa --class ~.Customer
Results in:
module focus --moduleName webapp-domain entity jpa --class ~.Customer --activeRecord false
In this example, the tailor configuration defines a new alias command that will trigger a set of other commands to scaffold repository, service and web layer for an entity. Note that this configuration does not define the "execute" action to execute the original "layer" command.
Although "layer" is not a command known to the shell, it won’t produce an error, because the tailor will transform it into a set of different commands, excluding the original. The downside is that you won’t get command completion support for this alias from the shell.
tailor.xml:
<config command="layer"> <action type="focus" module="domain"/> <!-- Create spring data JPA repository --> <action type="execute" command="repository jpa --interface ${entity}Repository --entity ${entity}"/> <!-- Create service interface and implementation class--> <action type="execute" command="service --interface ${entity}Service --class ${entity}ServiceImpl --entity ${entity}"/> <action type="focus" module="web"/> <action type="execute" command="web mvc scaffold --class ${entity}Controller --backingType ${entity}"/> </config>
Shell:
layer --entity ~.Customer
Results in:
module focus --moduleName webapp-domain repository jpa --interface ~.CustomerRepository --entity ~.Customer service --interface ~.CustomerService --class ~.CustomerServiceImpl --entity ~.Customer module focus --moduleName webapp-web web mvc scaffold --class ~.CustomerController --backingType ~.Customer
A new tailor configuration can also be defined in Java, instead of XML. This requires the creation of a new simple addon that you would need to build and install as a bundle in your Roo installation. Once your tailor extension bundle is running, the “tailor” commands will recognize all tailor configurations you implemented in that addon.
This is a more static and elaborate way of creating tailor configurations. However, it might be useful if you want to distribute a configuration to a large group of users.
After you created a new (simple) addon, you need to do the following:
<dependency> <groupId>org.springframework.roo</groupId> <artifactId>org.springframework.roo.addon.tailor</artifactId> </dependency>
@Component @Service public class TailorWebSimpleConfiguration implements TailorConfigurationFactory { ... }
@Override public TailorConfiguration createTailorConfiguration() { String description = "Web project with 2 modules DOMAIN-PRESENTATION"; TailorConfiguration configuration = new TailorConfiguration("webstyle-simple", description); configuration.addCommandConfig(createCommandConfigProject()); configuration.addCommandConfig(createCommandConfigJpaSetup()); return configuration; }
Add a chain of actions similar to how you would do in an XML configuration file, as described above.
private CommandConfiguration createCommandConfigJpaSetup() { CommandConfiguration config = new CommandConfiguration(); config.setCommandName("jpa setup"); config.addAction(ActionConfigFactory.focusAction( "domain")); config.addAction(ActionConfigFactory.defaultArgumentAction( "database", "HYPERSONIC_IN_MEMORY")); config.addAction(ActionConfigFactory.defaultArgumentAction( "provider", "HIBERNATE")); config.addAction(ActionConfigFactory.executeAction()); return config; }