Development

Ease of development is crucial: Shows how to make development more productive. Introduces class-reloading also known as the "code – save – refresh – be happy" cycle. Explains testing and scaffold capabilities. Introduces the admin application.

Introduction

This chapter deals with development topics.

First we concentrate on ease of development.
We want to work with frameworks that support an elegant, fast and productive development mode.
Children would break out in tears if you would tell them about past J2EE application servers with 10++ minutes redeployment time just to see the effect of changing a single line of code.
Much has improved since, but there is still room for more. Here we describe several techniques to ease development. We especially describe Civilians class-reloading technique which can supercharge your development cycle.

Then we discuss how Civilian web applications can be tested, introduce the admin application and end with a topic which is at the very beginning of application development: Scaffold new applications.

Ease of development

From a developers perspective we want to see the effect of code changes immediately. Ideally we want just to hit refresh in the browser. PHP is not an option since we are Java pigheads.

Using Tomcats VirtualWebappLoader

For deployment in a servlet container you can always build a WAR archive of your application and deploy that.
Eclipse Dynamic Web Projects (and similar offers by other IDEs) do the packing and copying for you.

When using Apache Tomcat (7.0.54+) we take the opposite approach: Instead of deploying the application into Tomcats webapp directory, we instruct Tomcat to pick up the application from our IDE project, using Tomcats VirtualWebappLoader. (In Tomcat 8 configuration seems to have changed).

In $tomcat/conf/server.xml add a context entry for your application within the Host element:

<Host name="localhost" ...>
    ...
    <Context path="/myapp" docBase="c:\proj\myproj\web">
        <Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="
            c:\proj\base\bin;
            c:\proj\base\lib\*.jar;
            c:\proj\myproj\lib\*.jar;
            c:\proj\myproj\bin"/>
            <!-- jars in c:\proj\myproj\web\WEB-IN\lib ate automatically included -->
    </Context>
<Host>
Context/@path is the path of the ServletContext within Tomcat, Context/@docBase is the web applications root directory (containing the WEB-INF folder), Context/Loader/@virtualClasspath instructs Tomcat where to find your classes and libraries.

If you now start up Tomcat, it will serve your application without a deployment in its webapp folder.

Using Tomcat manager to reload applications

Some servlet containers are able to monitor application files and reload the application when they detect a change.
Using Tomcats manager application we can also reload applications but can precisely control when to do it. Please follow these instructions to enable Tomcats manager application on your development box and especially install a user whose role includes the manager-script role.

With that you can reload an application by sending its context path to the manager app:

http://localhost/manager/text/reload?path=/myapp
This is how we use this feature:
When running in development mode we typically integrate a reload button or link in our HTML pages. When clicked it will send an Ajax call to the manager application Please take a look at the CRM sample and the script civassets/dev/reload-tomcat.js in Civilians source how this can be implemented.

Now we can write and save code in our IDE, switch to the browser, click the reload button and immediately see the effect.
Note that this technique will reinitialize your application. If the application needs significant startup time, this will somewhat degrade the reload experience...

Running an embedded Jetty or Tomcat server

Another great way to avoid building WARs or copy classes to a servlet container is to start an embedded server.
The Jetty and Tomcat classes provide a small command line interface to start a Jetty or Tomcat server embedded in your program (see the Quickstart for an example).
(The Tomcat class right now is experimental – unfortunately Tomcats documentation about its embedded mode is not very detailed).

Class reloading

Civilians class reloading is a feature which when used in combination with the VirtualWebappLoader technique or with an embedded server enables the following development cycle:
  1. Code (save, compile).
  2. Hit refresh in the browser and immediately see the changes.
Unlike application reloading this does not reinitialize the application, so you now will see the changes without any delay.

When class reloading is turned on, Civilian is using a new classloader for each request to load your controller class and all classes used by the controller. Therefore on the next request you will see code changes immediately since now the new controller version is loaded and used.

To turn class reloading on, you need to add these configuration entries to your civilian.ini config file:

# turn on development mode
develop = true

# in your app config add this
app.myapp.dev.classreload = true
Class reloading can pick up any changes in all classes which were not touched during application startup. This usually includes controllers, templates, forms etc. By default only classes below the application class are included. With the .exclude and .include switches you can fine-tune what classes are reloadable:
app.myapp.dev.classreload.exclude = org.myapp.web.SessionUser,org.myapp.web.Constants
app.myapp.dev.classreload.include = org.myapp.util.*
If you create a new controller, you need to restart the application to see the changes.

Sometimes class reloading may not work as desired. In this case you can set the log level of org.civilian.classloader to trace to analyze if classes are loaded correctly.

Testing

Civilian allows to run requests and evaluate responses in a test environment without the overhead of HTTP calls or the need to start a servlet server.
Therefore it provides the TestContext class which implements Context. The context.test package contains a Context implementation which can be used for unit tests. The steps to run test request are:
  1. Create a TestContext instance.
  2. Either initialize the context using a civilina.ini config, or explicitly add application objects to the TestContext.
  3. Create a TestRequest object and set its properties.
  4. Run the request and assert that the returned TestResponse matches the expectations.
The Test sample demonstrates this technique.

Admin app

Civilian ships with a built-in admin application. Its gives you an overview of deployed applications, their configurations and resource URLs. It shows if your configurations work as expected, and which resource URLs are actually published. You can also inspect which controller is mapped to a resource and what action methods are available.

The admin app uses Civilians ability to run multiple applications in a Civilian context. When you start your application in development mode by default the admin app is also started and available under the path /civadmin below your context path.

The admin app can be configured via civilian.ini like your own applications. (It just uses the key prefix civ.admin instead of app.id).

Scaffold

The quickstart tutorial already introduced the Scaffold tool to generate a Civilian application. The manifest of civilian.jar declares it as Main-class. It prints a detailed help message when run without any arguments. Scaffold expects
  • optional parameters,
  • the directory where to put the generated files,
  • a prefix which will be prependeded to the name of core application classes.
java -jar civilian.jar param* directory class-prefix
for example
java -jar civilian.jar /proj/crm Crm
The parameters are
-eclipse also generates Eclipse project files
-enc encoding use the encoding for the generated files (default is UTF-8)
-locales list of locales comma separated list of supported locales (without spaces), default is simple en
-libs list of jar files copy the jar files to the generated WEB-INF/lib directory
-min create a minimal scaffold application
-package use the package as application package, default is "com." + lowercase(class-prefix)
-tomcat generates a snippet tomcat.server.xml which can be inserted into a Tomcat server.xml to deploy the application from it project directory.
-text creates empty resource bundle files for all supported locales
-v print verboses messages during scaffold