Setting up your project

Directory layout

We'll follow the directory layout proposed by the Gaelyk template project:

/
+-- src
    |
    +-- main
    |   |
    |   +-- groovy
    |   +-- java
    |   +-- webapp
    |       |
    |       +-- index.gtpl
    |       +-- css
    |       +-- images
    |       +-- js
    |       +-- WEB-INF
    |           |
    |           +-- appengine-web.xml
    |           +-- web.xml
    |           +-- plugins.groovy      // if you use plugins
    |           +-- routes.groovy       // if you use the URL routing system
    |           +-- classes
    |           |
    |           +-- groovy
    |           |    |
    |           |    +-- controller.groovy
    |           |
    |           +-- pages
    |           |    |
    |           |    +-- view.gtpl
    |           |
    |           +-- includes
    |           |    |
    |           |    +-- footer.gtpl
    |           |
    |           +-- lib
    |               |
    |               +-- appengine-api-1.0-sdk-x.y.z.jar
    |               +-- appengine-api-labs-x.y.z.jar
    |               +-- gaelyk-x.y.z.jar
    |               +-- groovy-all-x.y.z.jar
    |
    +-- test
        |
        +-- groovy
        +-- java

At the root of your project, you'll find:

In the WEB-INF directory, you'll find:

Note: You may decide to put the Groovy scripts and includes elsewhere, but the other files and directories can't be changed, as they are files App Engine or the servlet container expects to find at that specific location.

The template project comes with initial support for Eclipse project files, allowing you to open the project easily within Eclipse.

Warning: If you're using the Eclipse GAE plugin, be careful with the libraries that the plugin automatically adds to your WEB-INF/lib. They are not needed for a Gaelyk project, and may cause sometimes some strange compilation errors.

Configuration files

With the directory layout ready, let's have a closer look at the configuration files: the standard web.xml and App Engine's specific appengine-web.xml:

appengine-web.xml

    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
        <!-- Your application ID -->
        <application>myappid</application>

        <version>1</version>

        <!-- If all your templates and groovlets are encoding in UTF-8 -->
        <!-- Please specify the settings below, otherwise weird characters may appear in your templates -->
        <system-properties>
            <property name="file.encoding" value="UTF-8" />
            <property name="groovy.source.encoding" value="UTF-8" />

            <!-- Define where the logging configuration file should be found -->
            <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
        </system-properties>

        <!-- Uncomment this section if you want your application to be able to receive XMPP messages -->
        <!-- Similarily, if you want to receive incoming emails -->
        <!--
        <inbound-services>
            <service>xmpp_message</service>
            <service>mail</service>
        </inbound-services>
        -->

        <static-files>
            <exclude path="/WEB-INF/**.groovy" />
            <exclude path="**.gtpl" />
        </static-files>
    </appengine-web-app>

The sole thing which is peculiar here is the fact we're excluding the files with a .groovy and .gtpl extensions, as these files are non-static and correspond respectively to the Gaelyk Groovlets and templates. We instruct App Engine to not serve these files as mere resource files, like images or stylesheets.

Note: You may decide to use different extensions than .groovy and .gtpl, if you prefer to have URLs with extensions which don't leak the underlying technologies being used. Or make sure to use the flexible URL routing system.

web.xml

    <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
        <!-- A servlet context listener to initialize the plugin system -->
        <listener>
            <listener-class>groovyx.gaelyk.GaelykServletContextListener</listener-class>
        </listener>

        <!-- The Gaelyk Groovlet servlet -->
        <servlet>
            <servlet-name>GroovletServlet</servlet-name>
            <servlet-class>groovyx.gaelyk.GaelykServlet</servlet-class>
        </servlet>

        <!-- The Gaelyk template servlet -->
        <servlet>
            <servlet-name>TemplateServlet</servlet-name>
            <servlet-class>groovyx.gaelyk.GaelykTemplateServlet</servlet-class>
        </servlet>

        <!-- The URL routing filter -->
        <filter>
            <filter-name>RoutesFilter</filter-name>
            <filter-class>groovyx.gaelyk.routes.RoutesFilter</filter-class>
        </filter>

        <!-- Specify a mapping between *.groovy URLs and Groovlets -->
        <servlet-mapping>
            <servlet-name>GroovletServlet</servlet-name>
            <url-pattern>*.groovy</url-pattern>
        </servlet-mapping>

        <!-- Specify a mapping between *.gtpl URLs and templates -->
        <servlet-mapping>
            <servlet-name>TemplateServlet</servlet-name>
            <url-pattern>*.gtpl</url-pattern>
        </servlet-mapping>

        <filter-mapping>
            <filter-name>RoutesFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

        <!-- Define index.gtpl as a welcome file -->
        <welcome-file-list>
            <welcome-file>index.gtpl</welcome-file>
        </welcome-file-list>
    </web-app>

In web.xml, we first define a servlet context listener, to initialize the plugin system. We define the two Gaelyk servlets for Groovlets and templates, as well as their respective mappings to URLs ending with .groovy and .gtpl. We setup a servlet filter for the URL routing to have nice and friendly URLs. We then define a welcome file for index.gtpl, so that URLs looking like a directory search for and template with that default name.

Note: You can update the filter definition as shown below, when you attempt to forward to a route from another Groovlet to keep your request attributes. Without the dispatcher directives below the container is issuing a 302 redirect which will cause you to lose all of your request attributes.
    <filter-mapping>
        <filter-name>RoutesFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

Using the template project

You can use the template project offered by Gaelyk. It uses Gradle for the build, and for running and deploying applications, and Spock for testing your groovlets. Please have a look at the template project section to know more about it.