# 8. Controllers and Services

This section describes the artifacts that hold the logic of a Griffon application.

## 8.1 Controllers

Controllers are the entry point for your application's logic. Each controller has access to their model and view instances from their respective MVC group.

Controller actions are usually defined using a closure property form, like the following one

    class MyController {
        def someAction = { evt = null ->
            // do some stuff
        }
    }

It is also possible to define actions as methods, however the closure property form is preferred (but not enforced). The caveat is that you would need to translate the method into a MethodClosure when referencing them form a View script. In the following example the action 'action1' is defined as a closure property, whereas the action 'action2' is defined as a method

    application(title: 'Action sample', pack: true) {
        gridLayout(cols: 2, rows: 1) {
            button 'Action 1', actionPerformed: controller.action1
            button 'Action 2', actionPerformed: controller.&action2
        }
    }

Actions must follow these rules in order to be considered as such:

- must have public (Java) or default (Groovy) visibility modifier.
- name does not match an event handler, i.e, it does not begin with `on`.
- must pass `GriffonClassUtils.isPlainMethod()` if it's a method.
- must have `void` as return type if it's a method.
- value must be a closure (including curried method pointers) if it's a property.

Controllers can perform other tasks:

- listen to application events.
- create and destroy MVC groups via a pair of methods (createMVCGroup, destroyMVCGroup).
- react to MVC initialization/destruction via a pair of methods (mvcGroupInit, mvcGroupDestroy).
- hold service references.

## 8.1.1 Threads and Actions

A key aspect that you must always keep in mind is proper threading. Often times controller actions will be bound in response to an event driven by the UI. Those actions will usually be invoked in the same thread that triggered the event, which would be the UI thread. When that happens you must make sure that the executed code is short and that it quickly returns control to the UI thread. Failure to do so may result in unresponsive applications.

The following example is the typical use case that must be avoided

    class BadController {
        def badAction = {
            def sql = Sql.newInstance(
                app.config.datasource.url,
                model.username,
                model.password,
                app.config.datasource.driver
            )
            model.products.clear()
            sql.eachRow("select * from products") { product ->
                model.products << [product.id, product.name, product.price]
            }
            sql.close()
        }
    }

There are two problems here. First the database connection is established inside the UI thread (which takes precious milliseconds or even longer), then a table (which could be arbitrarily large) is queried and each result sent to a List belonging to the model. Assuming that the list is bound to a Table Model then the UI will be updated constantly by each added row; which happens to be done all inside the UI thread. The application will certainly behave slow and sluggish, and to top it off the user won't be able to click on another button or select a menu item until this actions has been processed entirely.

Chapter 9 will discuss with further detail the options that you have at your disposal to make use of proper threading constructs. Here's a quick fix for the previous controller

    class GoodController {
        def goodAction = {
            execOutsideUI {
                def sql = null
                try {
                    sql = Sql.newInstance(
                        app.config.datasource.url,
                        model.username,
                        model.password,
                        app.config.datasource.driver
                    )
                    List results = []
                    sql.eachRow("select * from products") { product ->
                        results << [product.id, product.name, product.price]
                    }
                    execInsideUIAsync {
                        model.products.clear()
                        model.addAll(results)
                    }
                } finally {
                    sql?.close()
                }
            }
        }
    }

However starting with Griffon 0.9.2 you're no longer required to surround the action code with `execOutsideUI` as the compiler will do it for you. This feature breaks backward compatibility with previous releases so it's possible to disable it altogether. Please refer to section 4.7.5 Disable Threading Injection. This feature can be partially enabled/disabled too. You can specify with absolute precision which actions should have this feature enabled or disabled, by adding the following settings to `griffon-app/conf/BuildConfig.groovy`

    compiler {
        threading {
            sample {
                SampleController {
                    action1 = false
                    action2 = true
                }
                FooController = false
            }
            bar = false
        }
    }

The compiler will evaluate these settings as follows:

- the action identified by `sample.SampleController.action1` will not have automatic threading injected into its code, while `sample.SampleController.action2` (and any other found in the same controller) will have it.
- all actions belonging to `sample.FooController` will not have automatic threading injected.
- all actions belonging to all controllers in the `bar` package will not have threading injected.

> Automatic threading injection only works for Groovy based controllers. You must add appropriate threading code to controller actions that are written in languages other than Groovy.

## 8.2 Services

Services are responsible for the application logic that does not belong to a single controller. They are meant to be treated as singletons, injected to MVC members by following a naming convention. Services are optional artifacts, and as such there is no default folder created for them when a new application is created.

Services must be located inside the `griffon-app/services` directory with a `Service` suffix. The create-service command performs this job for you; also adding a unit test for the given service.

Let's say you need to create a Math service, the command to invoke would be

    griffon create-service math

This results in the following files being created

- `griffon-app/services/MathService.groovy` - the service class.
- `test/unit/MathServiceTests.groovy` - service unit test.

A trivial implementation of an addition operation performed by the MathService would look like the following snippet

    class MathService {
        def addition(a, b) { a + b }
    }

Using this service from a Controller is a straight forward task. As mentioned earlier services will be injected by name, which means you only need to define a property whose name matches the uncapitalized service name, for example

    class MyController {
        def mathService    def action = {
            model.result = mathService.addition model.a, model.b
        }
    }

The type of the service class is optional as basic injection is done by name alone.

> Service injection is trivial, it does not provide a full blown DI, in other words further service dependencies will not be resolved. You will need a richer DI solution in order to achieve this, fortunately there is a Spring plugin that does this and more.

Given that services are inherently treated as singletons they are also automatically registered as application event listeners. Be aware that services will be instantiated lazily which means that some events might not reach a particular service if it has not been instantiated by the framework by the time of event publication. It also discouraged to use the @Singleton annotation on a Service class as it will cause trouble with the automatic singleton management Griffon has in place.

Lastly, all services instances will become available through an instance of type `griffon.core.ServiceManager`. This helper class exposes available services via a Map. You can query all currently available services in the following manner

    app.serviceManager.services.each { name, instance ->
       // do something cool with services
    }

You can also query for a particular service instance in the following way

    def fooService = app.serviceManager.findService('foo')

It's worth mentioning that the previous method will instantiate the service if it wasn't available up to that point.

All services are instantiated lazily by default. You can change this behavior by adding a configuration flag to `Config.groovy`

    griffon.services.eager.instantiation = true