Views and controllers

Now that our project is all setup, it's time to dive into groovlets and templates.

Tip: A good practice is to separate your views from your logic (following the usual MVC pattern). Since Gaelyk provides both view templates and Groovlet controllers, it's advised to use the former for the view and the later for the logic.

Gaelyk builds on Groovy's own Groovlets and template servlet to add a shorcuts to the App Engine SDK APIs.

Note: You can learn more about Groovy's Groovlets and templates from this article on IBM developerWorks. Gaelyk's own Groovlets and templates are just an extension of Groovy's ones, and simply decorate Groovy's Groovlets and templates by giving access to App Engine services and add some additional methods to them via Groovy categories.

Variables available in the binding

A special servlet binding gives you direct access to some implicit variables that you can use in your views and controllers:

Eager variables

Note: The params map always contains values of type String (for single parameter) or String[] (for multiple parameters). To cast them to expected type, use as keyword. If single value is expected (e.g. params.limit as int) but multiple parameters are submitted the first one is used. If multiple values are expected, use params.tags as String[] to guarantee you obtain String array instead of single String.

Lazy variables

Note: The eager variables are pre-populated in the binding of your Groovlets and templates. The lazy variables are instantiated and inserted in the binding only upon the first request.

GAE specific variables

Beyond those standard Servlet variables provided by Groovy's servlet binding, Gaelyk also adds ones of his own by injecting specific elements of the Google App Engine SDK:

Note: Regarding the app variable, this means you can access those values with the following syntax in your groovlets and templates:
        app.id
        app.version
        app.env.name
        app.env.version
        app.gaelyk.version
    
Note: You can learn more about the environment and system properties Google App Engine exposes.

Thanks to all these variables and services available, you'll be able to access the Google services and Servlet specific artifacts with a short and concise syntax to further streamline the code of your application.

Injecting services and variables in your classes

All the variables and services listed in the previous sections are automatically injected into the binding of Groovlets and templates, making their access transparent, as if they were implicit or global variables. But what about classes? If you want to also inject the services and variables into your classes, you can annotate them with the @GaelykBindings annotation.

    import groovyx.gaelyk.GaelykBindings

    // annotate your class with the transformation
    @GaelykBindings
    class WeblogService {
        def numberOfComments(post) {
            // the datastore service is available
            datastore.execute {
                select count from comments where postId == post.id
            }
        }
    }

The annotation instructs the compiler to create properties in your class for each of the services and variables.

Note: Variables like request, response, session, context, params, headers, out, sout, html are not bound in your classes.
Note: If your class already has a property of the same name as the variables and services injected by this AST transformation, they won't be overriden.

Templates

Gaelyk templates are very similar to JSPs or PHP: they are pages containing scriptlets of code. You can:

Let's have a closer look at an example of what a template may look like:

    <html>
        <body>
            <p><%
                def message = "Hello World!"
                print message %>
            </p>
            <p><%= message %></p>
            <p>${message}</p>
            <ul>
            <% 3.times { %>
                <li>${message}</li>
            <% } %>
            </ul>
        </body>
    </html>

The resulting HTML produced by the template will look like this:

    <html>
        <body>
            <p>Hello World!</p>
            <p>Hello World!</p>
            <p>Hello World!</p>
            <ul>
                <li>Hello World!</li>
                <li>Hello World!</li>
                <li>Hello World!</li>
            </ul>
        </body>
    </html>

If you need to import classes, you can also define imports in a scriplet at the top of your template as the following snippet shows:

    <% import com.foo.Bar %>
Note: Of course, you can also use Groovy's type aliasing with import com.foo.ClassWithALongName as CWALN. Then, later on, you can instanciate such a class with def cwaln = new CWALN().
Note: Also please note that import directives don't look like JSP directives (as of this writing).

As we detailed in the previous section, you can also access the Servlet objects (request, response, session, context), as well as Google App Engine's own services. For instance, the following template will display a different message depending on whether a user is currently logged in or not:

    <html>
        <body>
            <% if (user) { %>
                <p>You are currently logged in.</p>
            <% } else { %>
                <p>You're not logged in.</p>
            <% } %>
        </body>
    </html>

Includes

Often, you'll need to reuse certain graphical elements across different pages. For instance, you always have a header, a footer, a navigation menu, etc. In that case, the include mechanism comes in handy. As adivsed, you may store templates in WEB-INF/includes. In your main page, you may include a template as follows:

    <% include '/WEB-INF/includes/header.gtpl' %>

    <div>My main content here.</div>

    <% include '/WEB-INF/includes/footer.gtpl' %>

Redirect and forward

When you want to chain templates or Groovlets, you can use the Servlet redirect and forward capabilities. To do a forward, simply do:

    <% forward 'index.gtpl' %>

For a redirect, you can do:

    <% redirect 'index.gtpl' %>

Precompilation

Since version 1.2 you can precompile your templates using Gradle Gaelyk Plugin. If you are facing issues with precompiled templates in production you can set preferPrecompiled init parameter of the Gaelyk Template Servlet to true. Precompiled templates will be served as in production if available.

Groovlets

In contrast to view templates, Groovlets are actually mere Groovy scripts. But they can access the output stream or the writer of the servlet, to write directly into the output. Or they can also use the markup builder to output HTML or XML content to the view.

Let's have a look at an example Groovlet:

    println """
        <html>
            <body>
    """

    [1, 2, 3, 4].each { number -> println "

${number}

" } def now = new Date() println """ <p> ${now} </p> </body> </html> """

You can use print and println to output some HTML or other plain-text content to the view. Instead of writing to System.out, print and println write to the output of the servlet. For outputing HTML or XML, for instance, it's better to use a template, or to send fragments written with a Markup builder as we shall see in the next sessions. Inside those Groovy scripts, you can use all the features and syntax constructs of Groovy (lists, maps, control structures, loops, create methods, utility classes, etc.)

Note:Don't forget to declare packages for Groovlets when you use Gradle Gaelyk Plugin to build the application. Otherwise they will be placed in wrong destination folders!

Using MarkupBuilder to render XML or HTML snippets

Groovy's MarkupBuilder is a utility class that lets you create markup content (HTML / XML) with a Groovy notation, instead of having to use ugly printlns. Our previous Groovlet can be written more cleanly as follows:

html.html {
    body {
        [1, 2, 3, 4].each { number -> p number }

        def now = new Date()

        p now
    }
}
Note: You may want to learn more about MarkupBuilder in the Groovy wiki documentation or on this article from IBM developerWorks.

Delegating to a view template

As we explained in the section about redirects and forwards, at the end of your Groovlet, you may simply redirect or forward to a template. This is particularly interesting if we want to properly decouple the logic from the view. To continue improving our previous Groovlets, we may, for instance, have a Groovlet compute the data needed by a template to render. We'll need a Groovlet and a template. The Groovlet WEB-INF/groovy/controller.groovy would be as follows:

    request['list'] = [1, 2, 3, 4]
    request['date'] = new Date()

    forward 'display.gtpl'
Note: For accessing the request attributes, the following syntaxes are actually equivalent:
    request.setAttribute('list', [1, 2, 3, 4])
    request.setAttribute 'list', [1, 2, 3, 4]
    request['list'] = [1, 2, 3, 4]
    request.list = [1, 2, 3, 4]

The Groovlet uses the request attributes as a means to transfer data to the template. The last line of the Groovlet then forwards the data back to the template view display.gtpl:

    <html>
        <body>
        <% request.list.each { number -> %>
            <p>${number}</p>
        <% } %>
            <p>${request.date}</p>
        </body>
    </html>

Logging messages

In your Groovlets and Templates, thanks to the log variable in the binding, you can log messages through the java.util.logging infrastructure. The log variable is an instance of groovyx.gaelyk.logging.GroovyLogger and provides the methods: severe(String), warning(String), info(String), config(String), fine(String), finer(String), and finest(String).

The default loggers in your groovlets and templates follow a naming convention. The groovlet loggers' name starts with the gaelyk.groovlet prefix, whereas the template loggers' name starts with gaelyk.template. The name also contains the internal URI of the groovlet and template but transformed: the slashes are exchanged with dots, and the extension of the file is removed.

Note: The extension is dropped, as one may have configured a different extension name for groovlets and templates than the usual ones (ie. .groovy and .gtpl).

A few examples to illustrate this:

URI Logger name
/myTemplate.gtpl gaelyk.template.myTemplate
/crud/scaffolding.gtpl gaelyk.template.crud.scaffolding
/WEB-INF/templates/aTemplate.gtpl gaelyk.template.WEB-INF.templates.aTemplate
/upload.groovy
(ie. /WEB-INF/groovy/upload.groovy)
gaelyk.groovlet.upload
/account/credit.groovy
(ie. /WEB-INF/groovy/account/credit.groovy)
gaelyk.groovlet.account.credit

This naming convention is particularly interesting as the java.util.logging infrastructure follows a hierarchy of loggers depending on their names, using dot delimiters, where gaelyk.template.crud.scaffolding inherits from gaelyk.template.crud which inherits in turn from gaelyk.template, then from gaelyk. You get the idea! For more information on this hierarchy aspect, please refer to the Java documentation.

Concretely, it means you'll be able to have a fine grained way of defining your loggers hierarchy and how they should be configured, as a child inherits from its parent configuration, and a child is able to override parent's configuration. So in your logging.properties file, you can have something like:

# Set default log level to INFO
.level = INFO

# Configure Gaelyk's log level to WARNING, including groovlet's and template's
gaelyk.level = WARNING

# Configure groovlet's log level to FINE
gaelyk.groovlet.level = FINE

# Override a specific groovlet familty to FINER
gaelyk.groovlet.crud.level = FINER

# Set a specific groovlet level to FINEST
gaelyk.groovlet.crud.scaffoldingGroovlet.level = FINEST

# Set a specific template level to FINE
gaelyk.template.crud.editView.level = FINE

You can also use the GroovyLogger in your Groovy classes:

    import groovyx.gaelyk.logging.GroovyLogger
    // ...
    def log = new GroovyLogger("myLogger")
    log.info "This is a logging message with level INFO"

It is possible to access any logger thanks to the logger accessor, which is available in the binding under the name logger. From a Groovlet or a Template, you can do:

    // access a logger by its name, as a property access
    logger.myNamedLogger.info "logging an info message"

    // when the logger has a complex name (like a package name with dots), prefer the subscript operator:
    logger['com.foo.Bar'].info "logging an info message"

Additionally, there are two other loggers for tracing the routes filter and plugins handler, with gaelyk.routesfilter and gaelyk.pluginshandler. The last two log their messages with the CONFIG level, so be sure to adapt the logging level in your logging configuration file if you wish to troubleshoot how routes and plugins are handled.