# 5. Application Overview

## 5.1 Directory Structure

Here's a more detailed explanation of each directory within the application's structure

- `griffon-app` - top level directory for Groovy sources.

- `conf` - Configuration sources.

- `webstart` - Webstart resources.
- `keys` - Jar signing keys.
- `dist` - Package specific files.

- `shared` - Common files to all packaging targets (like LICENSE.txt)

- `metainf` - Files that should go in META-INF inside the application/addon jar.

- `models` - Models.
- `views` - Views.
- `controllers` - Controllers.
- `services` - Services.
- `resources` - Images, properties files, etc.
- `i18n` - Support for internationalization (i18n).

- `scripts` - Gant scripts.
- `src` - Supporting sources.

- `main` - Other Groovy/Java sources.

- `test` - Unit and integration tests.

- `unit` - Directory for unit tests.
- `integration` - Directory for integration tests.
- `cli` - Directory for command line tests (Scripts).

## 5.2 The MVC Pattern

All Griffon applications operate with a basic unit called the MVC group. An MVC group is comprised of 3 member parts: Models, Views and Controllers. However it is possible to add (or even remove) members from an MVC group by carefully choosing a suitable configuration.

MVC groups configuration is setup in `Application.groovy` located inside `griffon-app/conf`. This file holds an entry for every MVC group that the application has (not counting those provided by plugins/addons).

Here's how a typical MVC group configuration looks like

    mvcGroups {
        // MVC Group for "sample"
        'sample' {
            model      = 'sample.SampleModel'
            view       = 'sample.SampleView'
            controller = 'sample.SampleController'
        }
    }

The order of the members is very important, it determines the order in which each member will be initialized. In the previous example both `model` and `view` will be initialized before the `controller`. Do not mistake initialization for instantiation, as initialization relies on calling mvcGroupInit on the group member.

MVC group configurations accept a special key that defines additional configuration for that group, as it can be seen in the following snippet

    mvcGroups {
        // MVC Group for "sample"
        'sample' {
            model      = 'sample.SampleModel'
            view       = 'sample.SampleView'
            controller = 'sample.SampleController'
        }    // MVC Group for "foo"
        'foo' {
            model      = 'sample.FooModel'
            view       = 'sample.FooView'
            controller = 'sample.FooController'
            config {
                key = 'bar'
            }
        }
    }

Values placed under this key become available to MVC members during the call to mvcGroupInit, as part of the arguments sent to that method. Here's how the `FooController` can reach the key defined in the configuration

    class FooController {
        void mvcGroupInit(Map args) {
            println args.configuration.config.key
        }
    }

While being able to set additional values under this key is a certainly an advantage it would probably be better if those values could be mutated or tweaked, probably treating them as variables, effectively making a group configuration work as a template. For that we'll have to discuss the mvcGroupManager first.

## 5.2.1 MVCGroupManager

This class is responsible for holding the configuration of all MVC groups no matter how they were defined, which can be either in `Application.groovy` or in an addon descriptor.

During the startup sequence an instance of `MVCGroupManager` will be created and initialized. Later the application will instruct this instance to create all startup groups as required. `MVCGroupManager` has a handful set of methods that deal with MVC group configuration alone; however those that deal with group instantiation come in 3 versions, with 2 flavors each (one Groovy, the other Java friendly).

Locating a group configuration is easily done by specifying the name you're interested in finding

    def configuration = app.mvcGroupManager.findConfiguration('foo')

Once you have a configuration reference you can instantiate a group with it by calling any of the variants of the `create` method

    def configuration = app.mvcGroupManager.findConfiguration('foo')
    def group1 = configuration.create('foo1')
    def group2 = configuration.create('foo2', [someKey: 'someValue'])
    // the following will make the group's id match its name
    def group3 = configuration.create()
    def group4 = configuration.create(someKey: 'someValue')

Be careful that creating groups with the same name is usually not a good idea. The default MVCGroupManager will complain when this happens and will automatically spit out an exception. This behavior may be changed by setting a configuration key in `Config.groovy`

    griffon.mvcid.collision = 'warning' // accepted values are 'warning', 'exception' (default)

The manager will log a warning and destroy the previously existing group before instantiating the new one when 'warning' is the preferred strategy

Now, even though you can create group instances based on their configurations the preferred way is to call any of createMVCGroup, buildMVCGroup or withMVCGroup methods. These methods are available to the app property every GriffonArtifact has, which points to the currently running application. Griffon artifacts also inherit these methods as part of their default contract. Finally, any class annotated with the MVCAware AST transformation will also gain access to these methods.

Groups will be available by id regardless of how they were instantiated. You can ask the mvcGroupManager for a particular group at any time, for example

    def g1 = app.mvcGroupManager.groups.foo1
    def g2 = app.mvcGroupManager.findGroup('foo1')
    def g3 = app.mvcGroupManager.foo1
    assert g1 == g2
    assert g1 == g3

It's also possible to query all models, views, controllers and builders on their own. Say you'd want to inspect all currently instantiated models, this is how it can be done

    app.mvcGroupManager.models.each { model ->
        // do something with model
    }

## 5.2.2 MVCGroups and Configuration

Now that you know there are several ways to instantiate MVC groups we can go back to customizing them.

The simples way is to pass in new values as part of the arguments map that mvcGroupInit receives, for example

    def group = app.mvcGroupManager.buildMVCGroup('foo', [key: 'foo'])

However is you wish to use the special `config` key that every MVC group configuration may have then you must instantiate the group in the following way

    def configuration = app.mvcGroupManager.cloneMVCConfiguration('foo', [key: 'someValue'])
    def group = configuration.create()

Note that you can still send custom arguments to the `create()` method.

## 5.2.3 Configuration Options

The following options are available to all MVC groups as long as you use the `config` key.

#### Disabling Lifecycle Events

Every MVC group triggers a few events during the span of its lifetime. These events will be sent to the event bus even if no component is interested in handling them. There may be times when you don't want these events to be placed in the event bus in order to speed up group creation/destruction. Use the following configuration to gain this effect:

    mvcGroups {
        // MVC Group for "sample"
        'sample' {
            model      = 'sample.SampleModel'
            view       = 'sample.SampleView'
            controller = 'sample.SampleController'
            config {
                events {
                    lifecycle = false
                }
            }
        }
    }

The following events will be disabled with this setting:

- `InitializeMVCGroup`
- `CreateMVCGroup`
- `DestroyMVCGroup`

#### Disabling Instantiation Events

The Griffon runtime will trigger an event for every artifact it manages. As with the previous events this one will be sent to the event bus even if no component handles it. Skipping publication of this event may result in a slight increase of speed during group instantiation. Use the following configuration to gain this effect:

    mvcGroups {
        // MVC Group for "sample"
        'sample' {
            model      = 'sample.SampleModel'
            view       = 'sample.SampleView'
            controller = 'sample.SampleController'
            config {
                events {
                    instantiation = false
                }
            }
        }
    }

The following events will be disabled with this setting:

- `NewInstance`

#### Disabling Controllers as Application Event Listeners

Controllers are registered as application event handlers by default when a group in instantiated. This makes it very convenient to have them react to events placed in the application's event bus. However you may want to avoid this automatic registration altogether, as it can lead to performance improvements. You can disable this feature with the following configuration:

    mvcGroups {
        // MVC Group for "sample"
        'sample' {
            model      = 'sample.SampleModel'
            view       = 'sample.SampleView'
            controller = 'sample.SampleController'
            config {
                events {
                    listener = false
                }
            }
        }
    }

You can still manually register a controller as an application event handler at any time, with the caveat that it's now your responsibility to unregister it when the time is appropriate, most typically during the group's destroy sequence.

## 5.3 Application Lifecycle

Every Griffon application goes through the same life cycle phases no matter in which mode they are running, with the exception of applet mode where there is an additional phase due to the intrinsic nature of applets. The application's lifecycle has been inspired by JSR-296, the Swing Application Framework.

Every phase has an associated life cycle script that will be invoked at the appropriate time. These scripts are guaranteed to be invoked inside the UI thread (the Event Dispatch Thread in Swing). The script names match each phase name; you'll find them inside `griffon-app/lifecycle`.

## 5.3.1 Initialize

The initialization phase is the first to be called by the application's life cycle. The application instance has just been created and its configuration has been read. No other artifact has been created at this point, which means that event publishing and the `ArtifactManager` are not yet available to the script's binding.

This phase is typically used to tweak the application for the current platform, including its Look & Feel.

Addons will be initialized during this phase.

> The `Initialize` script will be called right after the configuration has been read but before addons are initialized. You wont have access to addon contributions.

## 5.3.2 Startup

This phase is responsible for instantiating all MVC groups that have been defined in the application's configuration (`Application.groovy`) and that also have been marked as startup groups in the same configuration file.

> The `Startup` script will be called after all MVC groups have been initialized.

## 5.3.3 Ready

This phase will be called right after Startup with the condition that no pending events are available in the UI queue. The application's main frame will be displayed at the end of this phase.

## 5.3.4 Shutdown

Called when the application is about to close. Any artifact can invoke the shutdown sequence by calling `shutdown()` on the `app` instance.

> The `Shutdown` script will be called before any `ShutdownHandler` or event handler interested in the `ShutdownStart` event.

## 5.3.5 Stop

This phase is only available when running on applet mode. It will be called when the applet container invokes `destroy()` on the applet instance.

## 5.4 Application Events

Applications have the ability to publish events from time to time to communicate that something of interest has happened at runtime. Events will be triggered by the application during each of its life cycle phases, also when MVC groups are created and destroyed.

> All application event handlers are guaranteed to be called in the same thread that originated the event.

Any artifact or class can trigger an application event, by routing it through the reference to the current running application instance. All artifacts posses an instance variable that points to that reference. All other classes can use ApplicationHolder to gain access to the current application's instance.

Publishing an event can be done synchronously on the current thread or asynchronously relative to the UI thread. For example, the following snippet will trigger an event that will be handled in the same thread, which could be the UI thread itself

    app.event('MyEventName', ['arg0', 'arg1'])

Whereas the following snippet guarantees that all event handlers that are interested in an event of type `MyEventName` will be called outside of the UI thread

    app.eventOutside('MyEventName', ['arg0', 'arg1'])

Finally, if you'd want event notification to be handed in a thread that is not the current one (regardless if the current one is the UI thread or not) then use the following method

    app.eventAsync('MyEventName', ['arg0', 'arg1'])

There may be times when event publishing must be stopped for a while. If that's the case then you can instruct the application to stop delivering events by invoking the following code

    app.eventPublishingEnabled = false

Any events sent through the application's event bus will be discarded after that call; there's no way to get them back or replay them. When it's time to enable the event bus again simply call

    app.eventPublishingEnabled = true

## 5.4.1 Life Cycle Events

The following events will be triggered by the application during each one of its phases

- `Log4jConfigStart[config]` - during the Initialize phase.
- `BootstrapStart[app]` - after logging configuration has been setup, during the Initialize phase.
- `BootstrapEnd[app]` - at the end of the Initialize phase.
- `StartupStart[app]` - at the beginning of the Startup phase.
- `StartupEnd[app]` - at the end of the Startup phase.
- `ReadyStart[app]` - at the beginning of the Startup phase.
- `ReadyEnd[app]` - at the end of the Startup phase.
- `ShutdownRequested[app]` - before the Shutdown begins.
- `ShutdownAborted[app]` - if a Shutdown Handler prevented the application from entering the Shutdown phase.
- `ShutdownStart[app]` - at the beginning of the Shutdown phase.

## 5.4.2 Artifact Events

The following events will be triggered by the application when dealing with artifacts

- `NewInstance[klass, type, instance]` - when a new artifact is created.
- `LoadAddonsStart[app]` - before any addons are initialized, during the Initialize phase.
- `LoadAddonsEnd[app, addons]` - after all addons have been initialized, during the Initialize phase. `addons` is a Map of <name, instance> pairs.
- `LoadAddonStart[name, addon, app]` - before an addon is initialized, during the Initialize phase.
- `LoadAddonEnd[name, addon, app]` - after an addon has been initialized, during the Initialize phase.

These events will be triggered when dealing with MVC groups

- `InitializeMVCGroup[configuration, group]` - when a new MVC group is initialized. `configuration` is of type MVCGroupConfiguration; `group` is of type MVCGroup.
- `CreateMVCGroup[group]` - when a new MVC group is created. `configuration` is of type MVCGroupConfiguration; `group` is of type MVCGroup.
- `DestroyMVCGroup[group]` - when an MVC group is destroyed. `group` is of type MVCGroup.

## 5.4.3 Miscellaneous Events

These events will be triggered when a specific condition is reached

- `UncaughtExceptionThrown[exception]` - when an uncaught exception bubbles up to GriffonExceptionHandler.
- `WindowShown[window]` - triggered by the WindowManager when a Window is shown.
- `WindowHidden[window]` - triggered by the WindowManager when a Window is hidden.

## 5.4.4 Custom Events

Any artifact that holds a reference to the current application may trigger events at its leisure by calling the `event()` or `eventAsync` methods on the application instance. The following example demonstrates how a Controller triggers a "Done" event after an action has finished

    class MyController {
        def action = { evt = null ->
            // do some work
            app.event('Done')
        }
    }

There are two versions of the `event()` method. The first takes just the name of the event to be published; the second accepts an additional argument which should be a List of parameters to be sent to every event handler. Event handlers notified by this method are guaranteed to process the event in the same thread that published it. However, if what you need is to post a new event and return immediately then use the `eventAsync` variants. If you want the event to be handled outside of the UI thread then use the `eventOutsideUI()` variants.

## 5.4.5 Event Handlers

Any artifact or class that abides to the following conventions can be registered as an application listener, those conventions are:

- it is a Script, class, Map, RunnableWithArgs or closure.
- in the case of scripts or classes, they must define an event handler whose name matches on<EventName>, this handler can be a method, RunnableWithArgs or a closure property.
- in the case of a Map, each key maps to <EventName>, the value must be a RunnableWithArgs or a closure.
- scripts, classes and maps can be registered/unregistered by calling `addApplicationListener`/ `removeApplicationListener` on the app instance.
- RunnableWithArgs and closure event handlers must be registered with an overloaded version of `addApplicationListener`/`removeApplicationListener` that takes <EventName> as the first parameter, and the runnable/closure itself as the second parameter.

There is a general, per application, script that can provide event handlers. If you want to take advantage of this feature you must define a script named `Events.groovy` inside `griffon-app/conf`. Lastly both Controller and Service instances are automatically registered as application event listeners. This is the only way to declare event listeners for `Log4jConfigStart` and `BootstrapStart` events.

> You can also write a class named `Events.java` in `src/main` as an alternative to `griffon-app/conf/Events.groovy`, but not both!

These are some examples of event handlers:

- Display a message right before default MVC groups are instantiated

`File: griffon-app/conf/Events.groovy`

    onBootstrapEnd = { app ->
      println """Application configuration has finished loading.
    MVC Groups will be initialized now."""
    }

- Quit the application when an uncaught exception is thrown

`File: src/main/Events.java`

    import griffon.util.ApplicationHolder;public class Events {
        public void onUncaughtExceptionThrown(Exception e) {
            ApplicationHolder.getApplication().shutdown();
        }
    }

- Print the name of the application plus a short message when the application is about to shut down.

`File: griffon-app/controller/MyController.groovy`

    class MyController {
      def onShutdownStart = { app ->
        println "${app.config.application.title} is shutting down"
      }
    }

- Print a message every time the event "Foo" is published

`File: griffon-app/controller/MyController.groovy`

    class MyController {
      void mvcGroupInit(Map args) {
        app.addApplicationListener([
          Foo: {-> println 'got foo!' }
        ])
      }  def fooAction = { evt = null ->
        // do something
        app.event('Foo')
      }
    }

- An alternative to the previous example using a closure event handler

`File: griffon-app/controller/MyController.groovy`

    class MyController {
      void mvcGroupInit(Map args) {
        app.addApplicationListener('Foo'){-> println 'got foo!' }
      }  def fooAction = { evt = null ->
        // do something
        app.event('Foo')
      }
    }

- Second alternative to the previous example using a RunnableWithArgs event handler

`File: griffon-app/controller/MyController.java`

    import java.util.Map;
    import griffon.util.RunnableWithArgs;
    import org.codehaus.griffon.runtime.core.AbstractGriffonController;public class MyController extends AbstractGriffonController {
      public void mvcGroupInit(Map<String, Object> params) {
        getApp().addApplicationListener("Foo", new RunnableWithArgs() {
            public void run(Object[] args) {
                System.out.println("got foo!");
            }
        });
      }  public void fooAction() {
        // do something
        getApp().event("Foo");
      }
    }

## 5.4.6 Custom Event Publishers

As the name implies application events are sent system wide. However there is an option to create localized event publishers. Griffon provides a @griffon.transform.EventPublisher AST transformation that you can apply to any class that wishes to be an event publisher.

This AST transformation will inject the following methods to the annotated classes:

- addEventListener(Object)
- addEventListener(String, Closure)
- addEventListener(String, RunnableWithArgs)
- removeEventListener(Object)
- removeEventListener(String, Closure)
- removeEventListener(String, RunnableWithArgs)
- publishEvent(String)
- publishEvent(String,List)
- publishEventOutsideUI(String)
- publishEventOutsideUI(String,List)
- publishEventAsync(String)
- publishEventAsync(String,List)
- isEventPublishingEnabled()
- setEventPublishingEnabled(boolean)

Event listeners registered with these classes should follow the same rules as application event handlers (they can be Scripts, classes, maps or closures, and so on).

The following example shows a trivial usage of this feature

    @griffon.transform.EventPublisher
    class Publisher {
       void doit(String name) {
          publishEvent('arg', [name])
       }   void doit() {
          publishEvent('empty')
       }
    }class Consumer {
       String value   void onArg(String arg) { value = 'arg = ' + arg }
       void onEmpty() { value = 'empty' }
    }p = new Publisher()
    c = new Consumer()
    p.addEventListener(c)
    assert !c.value
    p.doit()
    assert c.value == 'empty'
    p.doit('Groovy')
    assert c.value == 'arg = Groovy'

## 5.5 Application Features

The GriffonApplication interface defines the base contract for all Griffon applications. However there are some meta enhancements done at runtime to all applications. The following methods become available before the Initialize phase is executed:

- MVC

- newInstance
- buildMVCGroup
- createMVCGroup
- destroyMVCGroup
- withMVCGroup

- Threading

- execInsideUISync
- execInsideUIAsync
- execOutsideUI
- execFuture
- isUIThread

## 5.5.1 Runtime Configuration

The application's runtime configuration is available through the `config` property of the application instance. This is a `ConfigObject` whose contents are obtained by merging `Application.groovy` and `Config.groovy`. Builder configuration is available through the `builderConfig` property and reflects the contents of `Builder.groovy`.

However starting with Griffon 0.9.2 there's an alternative for defining the application's configuration. You can now use properties files instead of Groovy scripts. If both properties files and Groovy scripts are available in the classpath then the settings of the scripts will be overriden by those set in the properties file. Each properties file must match the name of the configuration script. The following table shows the conventions

Script File | Properties File
--- | ---
Application.groovy | Application.properties
Config.groovy | Config.properties
Builder.groovy | Builder.properties

An application can change the name of the configuration script but it can not change the name of the configuration properties file.

## 5.5.2 Metadata

Access to the application's metadata file (`application.properties`) is available by querying the `griffon.util.Metadata` singleton. Here's a snippet of code that shows how to setup a welcome message that displays the application's name and version, along with its Griffon version

    import griffon.util.Metadatadef meta = Metadata.current
    application(title: "Some app", package: true) {
        gridLayout cols: 1, rows: 2
        label "Hello, I'm ${meta['app.name']}-${meta['app.version']}"
        label "Built with Griffon ${meta['app.griffon.version']}"
    }

There are also a few helpful methods on this class

- `getApplicationName()` - same result as `meta['app.name']`
- `getApplicationVersion()` - same result as `meta['app.version']`
- `getGriffonVersion()` - same result as `meta['app.griffon.version']`
- `getGriffonStartDir()` - returns the value of `'griffon.start.dir'` from the System properties
- `getGriffonWorkingDir()` - returns a File that points to `'griffon.start.dir'` if the value is set and the file is writable, otherwise returns a File pointing to the current location if it is writable; if that fails then attempts to return a File pointing to `'user.dir'`; if all fail it will return the location to a temporal file, typically `'/tmp/${griffonAppName}'`.

## 5.5.3 Environment

A Griffon application can run in several environments, default ones being DEVELOPMENT, TEST and PRODUCTION. An application can inspect its current running environment by means of the `griifon.util.Environment` enum.

The following example enhances the previous one by displaying the current running environment

    import griffon.util.Metadata
    import griffon.util.Environmentdef meta = Metadata.current
    application(title: "Some app", package: true) {
        gridLayout cols: 1, rows: 3
        label "Hello, I'm ${meta['app.name']}-${meta['app.version']}"
        label "Built with Griffon ${meta['app.griffon.version']}"
        label "Current environment is ${Environment.current}"
    }

## 5.5.4 Running Mode

Applications can run in any of the following modes: STANDALONE, WEBSTART or APPLET. The `griffon.util.RunMode` enum allows access to the current running mode.

This example extends the previous one by adding information on the current running mode

    import griffon.util.Metadata
    import griffon.util.Environment
    import griffon.util.RunModedef meta = Metadata.current
    application(title: "Some app", package: true) {
        gridLayout cols: 1, rows: 3
        label "Hello, I'm ${meta['app.name']}-${meta['app.version']}"
        label "Built with Griffon ${meta['app.griffon.version']}"
        label "Current environment is ${Environment.current}"
        label "Current running mode is ${RunMode.current}"
    }

## 5.5.5 Shutdown Handlers

Applications have the option to let particular artifacts abort the shutdown sequence and/or perform a task while the shutdown sequence is in process. Artifacts that desire to be part of the shutdown sequence should implement the `griffon.core.ShutdownHandler` interface and register themselves with the application instance.

The contract of a `ShutdownHandler` is very simple

- `boolean canShutdown(GriffonApplication app)` - return `false` to abort the shutdown sequence.
- `void onShutdown(GriffonApplication app)` - called if the shutdown sequence was not aborted.

There are no default ShutdownHandlers registered with an application.

## 5.5.6 Application Phase

All applications have the same life-cycle phases. You can inspect in which phase the application is currently on by calling the `getPhase()` method on an application instance. Valid values are defined by the ApplicationPhase enum : `INITIALIZE`, `STARTUP`, `READY`, `MAIN` and `SHUTDOWN`.

## 5.5.7 Application Locale

Starting with Griffon 0.9 applications have a bound `locale` property that is initialized to the default Locale. Components can listen to Locale changes by registering themselves as PropertyChangeListeners on the application instance.

## 5.5.8 Default Imports

Since Griffon 0.9.1 default imports per artifacts are supported. All Groovy based artifacts will resolve classes from the `griffon.core` and `griffon.util` packages automatically, there is no longer a need to define imports on those classes unless you require an static import or define an alias. An example of this feature would be as follows.

    class MyController {
        void mvcGroupInit(Map args) {
            println Metadata.current.'app.name'
        }
    }

The `Metadata` class is defined in package `griffon.util`. There are additional imports per artifact type, here's the list of default definitions

- Model

- groovy.beans -> @Bindable, @Vetoable
- java.beans -> useful for all PropertyChange* classes

- View (when using Swing)

- java.awt
- java.awt.event
- javax.swing
- javax.swing.event
- javax.swing.table
- javax.swing.text
- javax.swing.tree

The list of imports per artifacts can be tweaked or changed completely at will. You only need to specify a file named `META-INF/griffon-default-imports.properties` with the following format

    <artifact_type> = <comma_separated_package_list>

These are the contents of the default file

    views = javax.swing., javax.swing.event., javax.swing.table., javax.swing.text., javax.swing.tree., java.awt., java.awt.event.
    models = groovy.beans., java.beans.

Imports are cumulative, this means you a package can't be removed from the default list provided by Griffon.

## 5.5.9 Startup Arguments

Command line arguments can be passed to the application and be accessed by calling `getStartupArgs()` on the application instance. This will return a copy of the args (if any) defined at the command line.

Here's a typical example of this feature in development mode

    griffon run-app arg0 arg1 argn

Here's another example demonstrating that the feature can be used once the application has been packaged, in this case as a single jar

    griffon dev package jar
    java -jar dist/jars/app.jar arg0 arg1 argn

## 5.5.10 Locating Resources

Resources can be loaded form the classpath using the standard mechanism provided by the Java runtime, that is, ask a `ClassLoader` instance to load a resource `URL` or obtain an `InputStream` that points to the resource.

But the code can get quite verbose, take for example the following view code that locates a text file and displays it on a text component

    scrollPane {
        textArea(columns: 40, rows: 20,
            text: this.class.classLoader.getResource('someTextFile.txt').text)
    }

In order to reduce visual clutter, also to provide an abstraction over resource location, both `GriffonApplication` and `GriffonArtifact` have a new pair of methods that simply working with resources. Those methods are provided by `ResourceHandler`:

- `URL getResourceAsURL(String resourceName)`
- `InputStream getResourceAsStream(String resourceName)`
- `List<URL> getResources(String resourceName)`

Thus, the previous example can be rewritten this way

    scrollPane {
        textArea(columns: 40, rows: 20,
            text: getResourceAsURL('someTextFile.txt').text)
    }

In the future Griffon may switch to a modularized runtime, this abstraction will shield you from any problems when the underlying mechanism changes.

These methods can be attached to any non-artifact class at compile time if you apply the @griffon.transform.ResourcesAware AST transformation.

## 5.5.10 Uncaught Exceptions

There are times when an exception catches you off guard. The JVM provides a mechanism for handling these kind of exceptions: Thread.UncaughtExceptionHandler. You can register an instance that implements this interface with a Thread or ThreadGroup, however it's very likely that exceptions thrown inside the EDT will not be caught by such instance. Furthermore, it might be the case that other components would like to be notified when an uncaught exception is thrown. This is precisely what GriffonExceptionHandler does.

Stack traces will be sanitized by default, in other words, you won't see a long list containing Groovy internals. However you can bypass the filtering process and instruct Griffon to leave the stack traces untouched by specifying the following flag either in the command line with `-D` switch or in `Config.groovy`

    griffon.full.stacktrace = true

Exceptions will be automatically logged using the `error` level. Should you choose to disable logging but still have some output when an exception occurs then configure the following flag

    griffon.exception.output = true

Any exception caught by GriffonExceptionHandler will trigger a pair of events. The event names match the following convention

- Uncaught<exception.class.simpleName>
- UncaughtExceptionThrown

The exception is sent as the sole argument of these events. As an example, assume that a service throws an `IllegalArgumentException` during the invocation of a service method. This method was called from within a Controller which defines a handler for this exception, like this

    class SampleService {
        void work() {
            throw new IllegalArgumentException('boom!')
        }
    }class SampleController {
        def sampleService    def someAction = {
            sampleService.work()
        }    def onUncaughtIllegalArgumentException = { iae ->
            // process exception
        }
    }

As mentioned before, the name of an event handler matches the type of the exception it will handle, polymorphism is not supported. In other words, you wont be able to handle an `IllegalArgumentException` if you declare a handler for `RuntimeException`. You can however, rely on the second event triggered by this mechanism. Be aware that every single exception will trigger 2 events each time it is caught. It is best to use a synchronization approach to keep track of the last exception caught, like so

    import groovy.transform.Synchronizedclass SampleController {
        private lastCaughtException    @Synchronized
        void onUncaughtRuntimeException(RuntimeException e) {
            lastCaughtException = e
            // handle runtime exception only
        }    @Synchronized
        void onUncaughtExceptionThrown(e) {
            if(lastCaughtException == e) return
            lastCaughtException = e
            // handle any other exception types
        }
    }

As a final remark, any exceptions that might occur during the handling of the events wont trigger `GriffonExceptionHandler` again, they will simply be logged and discarded instead.

## 5.6 Swing specific

The following features are available to Swing based applications only.

## 5.6.1 WindowManager

The `WindowManager` class is responsible for keeping track of all the windows managed by the application. It also controls how these windows are displayed (via a pair of methods: show, hide). WindowManager relies on an instance of `WindowDisplayHandler` to actually show or hide a window. The default implementation simple shows and hide windows directly, however you can change this behavior by setting a different implementation of `WindowDisplayHandler` on the application instance.

#### WindowManager DSL

Starting with Griffon 0.9.2 there's a new DSL for configuring show/hide behavior per window. This configuration can be set in `griffon-app/conf/Config.groovy`, and here is how it looks

    swing {
        windowManager {
            myWindowName = [
                show: {window, app -> … },
                hide: {window, app -> … }
            ]
            myOtherWindowName = [
                show: {window, app -> … }
            ]
        }
    }

The name of each entry must match the value of the Window's name: property. Each entry may have the following options

- show - used to show the window to the screen. It must be a closure that takes two parameters: the window to display and the current application.
- hide - used to hide the window from the screen. It must be a closure that takes two parameters: the window to hide and the current application.
- handler - a custom `WindowDisplayHandler`.

The first two options have priority over the third one. If one is missing then the WindowManager will invoke the default behavior. There is one last option that can be used to override the default behavior provided to all windows

    swing {
        windowManager {
            defaultHandler = new MyCustomWindowDisplayHandler()
        }
    }

You can go a bit further by specifying a global show or hide behavior as shown in the following example

    swing {
        windowManager {
            defaultShow = {window, app -> … }
            // defaultHide = {window, app -> … }
            someWindowName = [
                hide: {window, app -> … }
            ]
        }
    }

#### Custom WindowDisplayHandlers

The following example shows how you can animate all managed windows using a dropIn effect for show() and a dropOut effect for hide(). This code assumes you have installed the Effects plugin.

In `src/main/Dropper.groovy`

    import java.awt.Window
    import griffon.swing.SwingUtils
    import griffon.swing.DefaultWindowDisplayHandler
    import griffon.core.GriffonApplication
    import griffon.effects.Effectsclass Dropper extends DefaultWindowDisplayHandler {
        void show(Window window, GriffonApplication app) {
            SwingUtils.centerOnScreen(window)
            app.execOutsideUI {
                Effects.dropIn(window, wait: true)
            }
        }    void hide(Window window, GriffonApplication app) {
            app.execOutsideUI {
                Effects.dropOut(window, wait: true)
            }
        }
    }

Notice that the effects are executed outside of the UI thread because we need to wait for them to finish before continuing, otherwise we'll hog the UI thread.

The second step to get this example to work is to inform the application it should use Dropper to display/hide windows. This a task that can be easily achieved by adding an application event handler, for example in `griffon-app/conf/Events.groovy`

    // No windows have been created before this step
    onBootstrapEnd = { app ->
        app.windowDisplayHandler = new Dropper()
    }

> Custom `WindowDisplayHandler` implementations set in this manner will be called for all managed windows. You'll loose the ability of using the WindowManager DSL.

Alternatively, you could specify an instance of `Dropper` as the default handler by changing the `WindowManager`'s configuration to

    swing {
        windowManager {
            defaultHandler = new Dropper()
        }
    }

The `WindowDisplayHandler` interface also defines show/hide methods that can manage `JInternalFrame` instances.

#### Starting Window

Previous to Griffon 0.9.2 the first window to be displayed during the Ready phase was determined by a simple algorithm: picking the first available window from the managed windows list. With 0.9.2 however, it's now possible to configure this behavior by means of the WindowManager DSL. Simply specify a value for `swing.windowManager.startingWindow`, like this

    swing {
        windowManager {
            startingWindow = 'primary'
        }
    }

This configuration flag accepts two types of values:

- a String that defines the name of the Window. You must make sure the Window has a matching name property.
- a Number that defines the index of the Window in the list of managed windows.

If no match is found then the default behavior will be executed.

## 5.7 Artifact API

The Artifact API provides introspection capabilities on the conventions set on each artifact type. The following sections explain further what you can do with this API.

## 5.7.1 Evaluating Conventions

Every Griffon application exposes all information about its artifacts and addons via a pair of helper classes

- `AddonManager` - used for all installed addons
- `ArtifactManager` - used for all remaining artifacts

#### ArtifactManager

The `ArtifactManager` class provides methods to evaluate the conventions within the project and internally stores references to all classes within a GriffonApplication using subclasses of GriffonClass class.

A `GriffonClass` represents a physical Griffon resources such as a controller or a service. For example to get all `GriffonClass` instances you can call:

    app.artifactManager.allClasses.each { println it.name }

There are a few "magic" properties that the `ArtifactManager` instance possesses that allow you to narrow the type of artifact you are interested in. For example if you only need to deal with controllers you can do:

    app.artifactManager.controllerClasses.each { println it.name }

Dynamic method conventions are as follows:

- `get*Classes` - Retrieves all the classes for a particular artifact type. Example `app.artifactManager.getControllerClasses()`.
- `*Classes` - Retrieves all the classes for a particular artifact type. Example `app.artifactManager.controllerClasses`.
- `is*Class` - Returns true if the given class is of the given artifact type. Example `app.artifactManager.isControllerClass(ExampleController)`

The `GriffonClass` interface itself provides a number of useful methods that allow you to further evaluate and work with the conventions. These include:

- `newInstance` - Creates a new instance of the enclosed class.
- `getName` - Returns the logical name of the class in the application without the trailing convention part if applicable
- `getClazz` - Returns the artifact class
- `getType` - Returns the type of the artifact, i.e "controller"
- `getTrailing` - Returns the suffix (if any) of the artifact, i.e "Controller"

For a full reference refer to the javadoc API.

#### AddonManager

The `AddonManager` class is responsible for holding references to all addons (which are of type griffon.core.GriffonAddon), as well as providing metainformation on each addon via an addon descriptor. The latter can be used to know at runtime the name and version of a particular addon, useful for building a dynamic About dialog for example.

All addons have the same behavior which is explained in detail in section 12.6 Addons.

## 5.7.2 Adding Dynamic Methods at Runtime

For Griffon managed classes like controllers, models and so forth you can add methods, constructors etc. using the ExpandoMetaClass mechanism by accessing each controller's MetaClass:

    class ExampleAddon {
        def addonPostInit(app) {
            app.artifactManager.controllerClasses.each { controllerClass ->
                 controllerClass.metaClass.myNewMethod = {-> println "hello world" }
            }
        }
    }

In this case we use the `app.artifactManager` object to get a reference to all of the controller classes' MetaClass instances and then add a new method called `myNewMethod` to each controller. Alternatively, if you know before hand the class you wish add a method to you can simple reference that classes `metaClass` property:

    class ExampleAddon {
        def addonPostInit(app) {
            String.metaClass.swapCase = {->
                def sb = new StringBuffer()
                delegate.each {
                    sb << (Character.isUpperCase(it as char) ?
                           Character.toLowerCase(it as char) :
                           Character.toUpperCase(it as char))
                }
                sb.toString()
            }        assert "UpAndDown" == "uPaNDdOWN".swapCase()
        }
    }

In this example we add a new method `swapCase` to `java.lang.String` directly by accessing its `metaClass`.

## 5.7.3 Artifact Types

All Griffon artifacts share common behavior. This behavior is captured by an interface named griffon.core.GriffonArtifact. Additional interfaces with more explicit behavior exist per each artifact type. The following is a list of the basic types and their corresponding interface

- Model -> griffon.core.GriffonModel
- View -> griffon.core.GriffonView
- Controller -> griffon.core.GriffonController
- Service -> griffon.core.GriffonService

Starting with Griffon 0.9.1 the compiler will make sure that each artifact implements its corresponding interface via AST injection. This feature can be very useful when accessing artifacts from languages other than Groovy (see section 13.1 Dealing with Non-Groovy Artifacts to learn more about this kind of artifacts).

> AST injection is always enabled unless you disable it as explained in section 4.7.2 Disable AST Injection.

Additionally to each artifact type you will find a companion GriffonClass that is specialized for each type. These specialized classes can be used to discover metadata about a particular artifact. The following is a list of the companion GriffonClass for each of the basic artifacts found in core

- Model -> griffon.core.GriffonModelClass
- View -> griffon.core.GriffonViewClass
- Controller -> griffon.core.GriffonControllerClass
- Service -> griffon.core.GriffonServiceClass

Be aware that additional artifacts provided by plugins (such as Charts and Wizards) may provide their own interface and companion GriffonClass. These too will be available when querying the `ArtifactManager`.

## 5.8 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

So, if your company requires all applications to be built following the same template and basic behavior then you can create an archetype that enforces those constraints. Archetypes are simple zip files with an application descriptor and templates. Despite this, Griffon provides a few scripts that let you manage archetypes

- create-archetype
- package-archetype
- install-archetype
- uninstall-archetype

Archetypes are installed per Griffon location under `$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 archetype

    import 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.8.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 command

    griffon 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 snippet

    import 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)

This archetype overrides the default templates for Model, View and Controller that will be used for the initial MVC group. It also creates 4 additional files inside `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 under `templates/artifacts` that matches each one of the specified artifact types, in other words we need the following files

MainModel.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)}"
        }
    }

MainController.groovy

    @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'
        }
    }

MainView.groovy

    @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')
    }

MainActions.groovy

    @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'
       )
    }

MainMenuBar.groovy

    @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)
           }
       }
    }

MainContent.groovy

    @artifact.package@label('Main content')

MainStatusBar.groovy

    @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 invocations

    griffon 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 this

    griffon create-app sample --archetype=fancy

This command should generate the following files in the application directory

- griffon-app

- controllers

- sample

- `SampleController`

- models

- sample

- `sampleModel`

- views

- sample

- `SampleActions`
- `SampleContent`
- `SampleMenuBar`
- `SampleStatusBar`
- `SampleView`

If you inspect the `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.

## 5.9 Platform Specific

The following sections outline specific tweaks and options available for a particular platform.

## 5.9.1 Tweaks for a Particular Platform

Griffon will automatically apply tweaks to the application depending on the current platform. However you have the option to specify a different set of tweaks. For example, the following configuration in `Config.groovy` specifies a different handler for `macosx`:

    platform {
        handler = [
            macosx: 'com.acme.MyMacOSXPlatformHandler'
        ]
    }

Now you only need to create such handler, like this:

    package com.acmeimport griffon.core.GriffonApplication
    import griffon.util.PlatformHandlerclass MyMacOSXPlatformHandler implements PlatformHandler {
        void handle(GriffonApplication app) {
            System.setProperty('apple.laf.useScreenMenuBar', 'true')
            …
        }
    }

The following platform keys are recognized by the application in order to locate a particular handler: `linux`, `macosx`, `solaris` and `windows`.

## 5.9.2 MacOSX

Applications that run in Apple's MacOSX must adhere to an strict set of rules. We recommend you to have a look at Apple's (Human Interface Guidelines).

Griffon makes it easier to integrate with MacOSX by automatically registering a couple of System properties that make the applicaiton behave like a native one

- `apple.laf.useScreenMenuBar` - if set to true will force the application's menu bar to appear at the top. Griffon sets its value to true.
- `com.apple.mrj.application.apple.menu.about.name` - sets the name that will appear next to the `About` menu option.

Java applications running on MacOSX also have the option to register handlers for `About`, `Preferences` and `Quit` menu options. The default handlers will trigger an specific application event each. These events can be disabled with a command flag set in `griffon-app/conf/Config.groovy`. The following table outlines the events, flags and the default behavior when the flags are enabled

Event | Fired when | Flag | Default behavior
--- | --- | --- | ---
OSXAbout | user activates About menu | osx.noabout | Default about dialog is displayed
OSXPrefs | user activates Preferences menu | osx.noprefs | No Preferences menu is available
OSXQuit | user activates Quit menu | osx.noquit | Application shutdowns immediately