5.9 Archetypes - Reference Documentation
Authors: Andres Almiray
Version: 1.2.0
Table of Contents
5.9 Archetypes
While it's true that artifact templates can be provided by plugins it simply was not possible to configure how an application is created. Application Archetypes fill this gap by providing a hook into the application creation process. Archetypes can do the following:- provide new versions of existing templates, like Model, Controller and so forth
- create new directories and files
- most importantly perhaps, install a preset of plugins
$USER_HOME/.griffon/<version>/archetypes
. Archetypes are registered with an application's metadata when creating an application. You can either manually modify the value of 'app.archetype' to a known archetype name or specify an -archetype=<archetypeName>
flag when creating a new application.If no valid archetype is found then the default archetype will be used. Following is the default template for an application archetypeimport griffon.util.MetadataincludeTargets << griffonScript('CreateMvc')target(name: 'createApplicationProject', description: 'Creates a new application project', prehook: null, posthook: null) { createProjectWithDefaults() createMVC() // to install plugins do the following // Metadata md = Metadata.getInstance(new File("${basedir}/application.properties")) // // for a single plugin // installPluginExternal md, pluginName, pluginVersion // ** pluginVersion is optional ** // // for multiple plugins where the latest version is preferred // installPluginsLatest md, [pluginName1, pluginName2] // // for multiple plugins with an specific version // installPlugins md, [pluginName1: pluginVersion1] } setDefaultTarget(createApplicationProject)
5.9.1 A Fancy Example
This section demonstrates how an archetype can be created and put to good use for building applications.#1 Create the archetype
The first step is to create the archetype project and its descriptor, which can be done by executing the following commandgriffon create-archetype fancy cd fancy
#2 Tweak the archetype descriptor
Locate the archetype descriptor (application.groovy
) and open it in your favorite editor, paste the following snippetimport griffon.util.MetadataincludeTargets << griffonScript('CreateMvc')target(name: 'createApplicationProject', description: 'Creates a new application project', prehook: null, posthook: null) { createProjectWithDefaults() argsMap.model = 'MainModel' argsMap.view = 'MainView' argsMap.controller = 'MainController' createMVC() createArtifact( name: mvcFullQualifiedClassName, suffix: 'Actions', type: 'MainActions', path: 'griffon-app/views') createArtifact( name: mvcFullQualifiedClassName, suffix: 'MenuBar', type: 'MainMenuBar', path: 'griffon-app/views') createArtifact( name: mvcFullQualifiedClassName, suffix: 'StatusBar', type: 'MainStatusBar', path: 'griffon-app/views') createArtifact( name: mvcFullQualifiedClassName, suffix: 'Content', type: 'MainContent', path: 'griffon-app/views') Metadata md = Metadata.getInstance(new File("${basedir}/application.properties")) installPluginExternal md, 'miglayout' }setDefaultTarget(createApplicationProject)
griffon-app/views
. Finally it installs the latest version of the MigLayout plugin.#3 Create the artifact templates
According to the conventions laid out in the archetype descriptor there must exist a file undertemplates/artifacts
that matches each one of the specified artifact types, in other words we need the following filesMainModel.groovy
@artifact.package@import groovy.beans.Bindable import griffon.util.GriffonNameUtilsclass @artifact.name@ { @Bindable String status void mvcGroupInit(Map args) { status = "Welcome to ${GriffonNameUtils.capitalize(app.config.application.title)}" } }
@artifact.package@class @artifact.name@ { def model def view // void mvcGroupInit(Map args) { // // this method is called after model and view are injected // } // void mvcGroupDestroy() { // // this method is called when the group is destroyed // } def newAction = { evt = null -> model.status = 'New action' } def openAction = { evt = null -> model.status = 'Open action' } def saveAction = { evt = null -> model.status = 'Save action' } def saveAsAction = { evt = null -> model.status = 'Save As action' } def aboutAction = { evt = null -> model.status = 'About action' } def quitAction = { evt = null -> model.status = 'Quit action' } def cutAction = { evt = null -> model.status = 'Cut action' } def copyAction = { evt = null -> model.status = 'Copy action' } def pasteAction = { evt = null -> model.status = 'Paste action' } }
@artifact.package@build(@artifact.name.plain@Actions) application(title: GriffonNameUtils.capitalize(app.config.application.title), pack: true, locationByPlatform:true, iconImage: imageIcon('/griffon-icon-48x48.png').image, iconImages: [imageIcon('/griffon-icon-48x48.png').image, imageIcon('/griffon-icon-32x32.png').image, imageIcon('/griffon-icon-16x16.png').image]) { menuBar(build(@artifact.name.plain@MenuBar)) migLayout(layoutConstraints: 'fill') widget(build(@artifact.name.plain@Content), constraints: 'center, grow') widget(build(@artifact.name.plain@StatusBar), constraints: 'south, grow') }
@artifact.package@import groovy.ui.Consoleactions { action( id: 'newAction', name: 'New', closure: controller.newAction, mnemonic: 'N', accelerator: shortcut('N'), smallIcon: imageIcon(resource:"icons/page.png", class: Console), shortDescription: 'New' ) action( id: 'openAction', name: 'Open...', closure: controller.openAction, mnemonic: 'O', accelerator: shortcut('O'), smallIcon: imageIcon(resource:"icons/folder_page.png", class: Console), shortDescription: 'Open' ) action( id: 'quitAction', name: 'Quit', closure: controller.quitAction, mnemonic: 'Q', accelerator: shortcut('Q'), ) action( id: 'aboutAction', name: 'About', closure: controller.aboutAction, mnemonic: 'B', accelerator: shortcut('B') ) action( id: 'saveAction', name: 'Save', closure: controller.saveAction, mnemonic: 'S', accelerator: shortcut('S'), smallIcon: imageIcon(resource:"icons/disk.png", class: Console), shortDescription: 'Save' ) action( id: 'saveAsAction', name: 'Save as...', closure: controller.saveAsAction, accelerator: shortcut('shift S') ) action(id: 'cutAction', name: 'Cut', closure: controller.cutAction, mnemonic: 'T', accelerator: shortcut('X'), smallIcon: imageIcon(resource:"icons/cut.png", class: Console), shortDescription: 'Cut' ) action(id: 'copyAction', name: 'Copy', closure: controller.copyAction, mnemonic: 'C', accelerator: shortcut('C'), smallIcon: imageIcon(resource:"icons/page_copy.png", class: Console), shortDescription: 'Copy' ) action(id: 'pasteAction', name: 'Paste', closure: controller.pasteAction, mnemonic: 'P', accelerator: shortcut('V'), smallIcon: imageIcon(resource:"icons/page_paste.png", class: Console), shortDescription: 'Paste' ) }
@artifact.package@import static griffon.util.GriffonApplicationUtils.*menuBar = menuBar { menu(text: 'File', mnemonic: 'F') { menuItem(newAction) menuItem(openAction) separator() menuItem(saveAction) menuItem(saveAsAction) if( !isMacOSX ) { separator() menuItem(quitAction) } } menu(text: 'Edit', mnemonic: 'E') { menuItem(cutAction) menuItem(copyAction) menuItem(pasteAction) } if(!isMacOSX) { glue() menu(text: 'Help', mnemonic: 'H') { menuItem(aboutAction) } } }
@artifact.package@label('Main content')
@artifact.package@label(id: 'status', text: bind { model.status })
#4 Package and install the archetype
This step is easily done with a pair of command invocationsgriffon package-archetype griffon install-archetype target/package/griffon-fancy-0.1.zip
#5 Use the archetype
Now that the archetype has been installed all that is left is put it to good use, like thisgriffon create-app sample --archetype=fancy
- griffon-app
- controllers
- sample
SampleController
- models
- sample
sampleModel
- views
- sample
SampleActions
SampleContent
SampleMenuBar
SampleStatusBar
SampleView
application.properties
file you'll notice that the miglayout plugin has been installed too.Archetypes can be versioned, installed and released in the same way plugins are.