5.6 Application Features - Reference Documentation
Authors: Andres Almiray
Version: 1.2.0
Table of Contents
5.6 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
- Threading
5.6.1 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 versionimport 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']}" }
getApplicationName()
- same result asmeta['app.name']
getApplicationVersion()
- same result asmeta['app.version']
getApplicationToolkit()
- same result asmeta['app.toolkit']
getGriffonVersion()
- same result asmeta['app.griffon.version']
getGriffonStartDir()
- returns the value of'griffon.start.dir'
from the System propertiesgetGriffonWorkingDir()
- 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.6.2 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 thegriifon.util.Environment
enum.The following example enhances the previous one by displaying the current running environmentimport 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.6.3 Running Mode
Applications can run in any of the following modes: STANDALONE, WEBSTART or APPLET. Thegriffon.util.RunMode
enum allows access to the current running mode.This example extends the previous one by adding information on the current running modeimport 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.6.4 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 thegriffon.core.ShutdownHandler
interface and register themselves with the application instance.The contract of a ShutdownHandler
is very simple
boolean canShutdown(GriffonApplication app)
- returnfalse
to abort the shutdown sequence.void onShutdown(GriffonApplication app)
- called if the shutdown sequence was not aborted.
5.6.5 Application Phase
All applications have the same life-cycle phases. You can inspect in which phase the application is currently on by calling thegetPhase()
method on an application instance. Valid values are defined by the ApplicationPhase enum : INITIALIZE
, STARTUP
, READY
, MAIN
and SHUTDOWN
.
5.6.6 Application Locale
Starting with Griffon 0.9 applications have a boundlocale
property that is initialized to the default Locale. Components can listen to Locale changes by registering themselves as PropertyChangeListeners on the application instance.The value of this property can be changed at any time. Doing so will also update the value of the default Locale used in the currently running JVM process.You may specify a configuration flag in Application.groovy
that can be used as the initial value for this property, like thisapplication {
title = 'Sample'
startupGroups = ['foo'] locale = 'es // Should Griffon exit when no Griffon created frames are showing?
autoShutdown = true // If you want some non-standard application class, apply it here
//frameClass = 'javax.swing.JFrame'
}
java.util.Locale
or java.util.String
with the following formats:
language
language_country
language_country_variant
5.6.7 Default Imports
Since Griffon 0.9.1 default imports per artifacts are supported. All Groovy based artifacts will resolve classes from thegriffon.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' } }
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
META-INF/griffon-default-imports.properties
with the following format<artifact_type> = <comma_separated_package_list>
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.
5.6.8 Startup Arguments
Command line arguments can be passed to the application and be accessed by callinggetStartupArgs()
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 modegriffon run-app arg0 arg1 argn
griffon dev package jar
java -jar dist/jars/app.jar arg0 arg1 argn
5.6.9 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
error
level. Should you choose to disable logging but still have some output when an exception occurs then configure the following flaggriffon.exception.output = true
- Uncaught<exception.class.simpleName>
- UncaughtExceptionThrown
IllegalArgumentException
during the invocation of a service method. This method was called from within a Controller which defines a handler for this exception, like thisclass SampleService { void work() { throw new IllegalArgumentException('boom!') } }class SampleController { def sampleService def someAction = { sampleService.work() } def onUncaughtIllegalArgumentException = { iae -> // process exception } }
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 soimport 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 } }
GriffonExceptionHandler
again, they will simply be logged and discarded instead.