KAURI CONCEPTS

This documents gives an overview of the core concepts and technologies provided by Kauri. See Getting started for a practical guide to start using Kauri.

Kauri is a web application framework. See wikipedia in case you don't know what a web application or a framework is.

Adhering to Web architecture

Kauri does not try to work around the constraints imposed by the Web, but embraces them. Kauri wants you to think about resources, URIs, correct use of the HTTP methods, response codes, caching, and so on. In one word, it supports RESTful development. Or if you prefer, ROA and WOA.

For this reason, Kauri does not use the classic Servlet API, but the Restlet API. Many things in Restlet will be familiar for Servlet developers: it is still about requests and responses. But at a more detailed level, its design matches better with REST and HTTP concepts. This in turn will help you to write better Web applications.

Kauri, like Restlet, does not have sessions as known in the Servlet world. Things that you might have traditionally stored in sessions, can often be rethought as resource state, kept in the client, or else stored as (preferably client-controlled) temporary resources.

Routing and resource classes

A RESTful design starts with thinking about the resources you want to expose and their URIs. Kauri thus has very good support for routing requests based on the request URI.

Kauri provides a flexible routing component. It is configured through a simple Groovy DSL. You do not have to know Groovy for this purpose. Below is a small example, you can probably guess what it does (if not, don't worry, it is all explained in the docs).

builder.router {
  directory(uri: "/resources", root: "module:/resources/")
  resource(uri: "/persons/{id}.html", ofClass: "com.foobar.Person")
}

The routing will eventually bring the request up to the Java class that will handle it. Such a class, which implements a resource, is called a resource class. In case the URI is not recognized by the system, a 404 Not Found response will be produced.

You can manually implement resource classes based on the Restlet API or the JAX-RS API. That last one is an API defined through the JSR process, and is based on annotations, providing a practical and consice means to implement a resource class. Here is an example to give an idea:

@Path("/persons/{id}.html")
public class PersonResource {

    @GET
    @Produces("text/html")
    public KauriRepresentation getPerson(@PathParam("id") String idParam) {
        ....
    }
}

Kauri also includes a component to automatically expose a database model (implemented using JPA) as RESTful resources.

The Kauri Runtime: modules

Modularization is a core tool of software engineering to keep the complexity low. By dividing an application into modules, that communicate through well-defined interfaces, a big application stays manageable.

An application can not only consist of custom-developed modules, but will often make reuse of modules provided by Kauri or other parties. Examples of modules included with Kauri are the routing module, the templating module, the forms module, and so on.

While you might not find your own application big and complex enough to bother splitting it into modules, you will still benefit from the modularization by being able to reuse existing modules. Since modules are properly encapsulated, you can do so without having to worry about their internal workings.

The core of Kauri, which manages the modules, is called the Kauri Runtime. The Kauri Runtime manages the startup and teardown of modules, the wiring of services between them, and the classloading of the modules.

The description of what modules form a certain application, and how to wire them together, is done in a file which we call the kauri.xml.

Technically, a module is a jar file containing a KAURI-INF directory which can contain:

  • Spring bean container configuration

  • classloader configuration (by default, auto-generated from your Maven pom)

  • other resources: template files, Javascript, CSS, images, ...

At startup, Kauri reads the classloader configuration of all modules and builds the classloader setup. Then it starts the modules, which comes down to booting the Spring container of each module. The service wiring is done by making available the dependencies as beans in the Spring container.

Up to here, nice, but nothing exceptional. The differences come from Kauri Runtime's support for REST-services and the Maven repository.

REST-services

REST-services are similar to classic Java services: a module can provide REST-services, and depend on REST-services. A REST-service can answer to REST-style requests (i.e. GET/POST/PUT/... on an URI-identified resource), not just for a single URI but an entire URI-space. When a module depends on a REST-service, you can either wire it to a REST-service provided by another module, or to an arbitrary URI.

In fact, everything you want to make available over HTTP should be provided by a module as a REST-service and is then mounted on a specific path.

Maven repository

The Kauri Runtime loads all modules and their classpath needs from Maven-style repositories. A Maven repository is a repository containing artifacts, which typically are jar files. By using the Maven repository, the jars are clearly identified by ID and version, rather than relying on file names. Another advantage is that after building your project using Maven, you can immediately run it. There is no no need for additional copying, as is the case with wars.

Internal protocols

The Kauri Runtime provides two special protocols for use within modules: The “module:” protocol to load resources from the module jar, and the “service:” protocol to access REST-services.

Templates

As most other web frameworks, Kauri has a template language, in which you will find the familiar constructs.

It is not the kind of template language like JSP, in which you can embed arbitrary (Java) code, but rather a restricted one in which you can use a limited set of constructs like loops, if's and expressions. We do reuse JSP's expression language (EL).

Kauri's template language is a standalone, reusable library not tied to any other parts of Kauri.

XML-based

The template language is XML-based. Each template file has to be a well-formed XML file. The advantage of this is that the template output will always be well-formed markup (start and end tags match, proper escaping of special characters), common formatting rules are enforced (an empty script tag should have a close tag, things like that), and the output is produced as SAX-events instead of characters, allowing to connect it to other XML transformation components (such as XSLT) in an efficient way.

Template inheritance

To support a common layout across pages, we support template inheritance, inspired by Django's template language. With template inheritance, you can define a base template in which there are regions which can be overridden by child templates.

As an example, take this base template:

<?xml version="1.0"?>
<html xmlns:t="http://kauriproject.org/template">

  <head>
    <title>
      <t:block name="title">The title</t:block>
    </title>
  </head>

  <body>
    <t:block name="main">Main content</t:block>
  </body>
</html>

The listing below shows a template inheriting from this base template. Notice the t:inherit attribute on the root element. The content of the t:block elements will replace that of the base template. All content outside the t:block's will be ignored. This allows to add body tags etc. so that the inherited template can be viewed stand-alone too.

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns:t="http://kauriproject.org/template"
      t:inherit="module:/templates/layout/layout.xml">

  <t:block name="title">My page</t:block>

  <t:block name="main">My interesting content</t:block>

</html>

Multiple inheritance, calling the “super” block and cross-block initialization are supported.

Link translation

A module does not know on beforehand where in the URI space its resources will end up. In case it reuses REST-services from other modules, it will even less know where those will end up in the URI-space. Therefore, the template langauge has a special publicUri() function to translate from internal paths to public paths. REST-services are internally addressed using a service protocol, so a publicUri() call looks like:

<a href="publicUri('service:/main/person/john.html')">John</a>

Forms

Forms play an important role in web applications. Plain HTML forms are rather basic and don't offer a lot of help with common issues such as data validation, custom controls, composite and collection structures, and so on. Kauri Forms solves these problems for you.

In contrast to the forms support of many web application frameworks, Kauri Forms is a Javascript library which runs in the browser. It is not a Java framework which manages a server-side model of your form. Kauri Forms makes the radical assumption that Javascript is available.

The form-controller sits in the browser, and directly GETs and POSTs/PUTs data to resources.

Besides the usual basic widgets, you will find things such a Google Maps widget or an Ajax-enabled upload widget.

A form's structure can be defined in Javascript (JSON), but it can also be implictly derived from annotations on a HTML form.

Below we show an example of a Javascript-defined form. A form consists of widgets, which have an ID and extend from build-in widgets. In the sample below, the IDs of the widgets are name, email and birthday. The email widget has a special property “+validators”, which means we add the listed validators to those of the base type, rather than replacing them.

var fconf = {
    createURI: "${publicUri('service:/data/contact/')}",
    type: {
        members: {
            name: "string",
            email: {
                base: "string",
                "+validators": { isEmail: {} },
                label: "e-mail"
            },
            birthday: {
                base: "date",
                yearRange: "-100:+0",
                label: "What is your date of birth?"
            },
        }
}};

In the HTML page, you put placeholders where the widgets should be inserted. These placeholders use special 'kauri-' attributes to refer back to the form module, like this:

<label kauri-role="label" kauri-idref="name"/>
<input kauri-idref="name"/>

Holistic approach

Besides supporting RESTful design, another important goal of Kauri is to support all players and all steps of a web application project, as described in more detail in the vision document.

Prototyping

The holistic vision is in part realized by the "prototyping mode" of Kauri. In prototyping mode, the focus is on designing the web front-end.

The development of a Web front-end is an iterative process. Often starting from a napkin wireframe, some first HTML pages are designed. The static HTML pages might be replaced with executable templates to support extracting the common layout and other reusable snippets. Feedback from the client is used to refine the design. Up to here, nothing too special.

The prototyping mode of Kauri allows you to turn your HTML page mockups into a real working prototype. The effort involved in this is not lost, as the development of the real application will re-use the same artifacts.

Here are some of the tools offered for prototyping:

  • You can split off the data used in the template in “mockup data entities”. These are JSON files that can be made available as a variable in the template. This allows reuse of the same data across pages, helps you gradually design your data model, and also makes that the templates will later be usable with non-mock data objects. Kauri has a component called DbMock which provides a complete RESTful interface (with CRUD and query operations) based on a directory structure containing JSON files.

  • You can support a dynamic URI space by making use of filesystem-defined routing. Simply create file names with {variables} in them (yes, you can use { and } in file names), and these will be treated as URI-matching patterns (URI templates).

  • No “throw over the wall”: the templates files created during the initial prototyping serve as a basis for the final ones, no need to restart from scratch.

  • You can switch back to prototyping mode at any time. In prototyping mode, templates are executed directly, fetching their data from the mockup data entities. In production mode, the templates will typically be called as the result of the processing in a resource class, which is also responsible for passing the data to the template.

There is no fixed line between what is possible in a prototype, and what not. A prototype can make use of Kauri Forms and Ajax.

As an example, suppose we have a resource person which we want to make available in the URI space as person/{id}.html

For this we create a template file at src/main/kauri/pages/person/{id}.html.xml1. During prototyping, template files are executed directly, without going through a resource class. This is sometimes refered to as Model 1 or PHP-style.

<?xml version="1.0"?>
<html xmlns:t="http://kauriproject.org/template">
  <t:variable name="person"
              src="service:/data/persons/${request.attributes.id}"
              overwrite="false"
              accept="application/json"/>

  <body>
    <h1>Person: ${person.name}</h1>

    <p>City: ${person.city}</p>
  </body>
</html>

Pay attention to the t:variable instruction: rather then defining the value of the variable using an expression, we tell it to load its data from a URI.

The person data is defined by creating a file src/main/kauri/mockdata/persons/1.json

{
  "name": "Mr Foo Bar",
  "city": "Foobar City"
}

Technology choices

We think it is useful if some choices have not to be made over and over for each project. Therefore, we have made a selection of third-party technologies which we push forward as the default solution to use in Kauri. This comes without obligation, but it will be useful to reduce learning curve, increase developer familiarity, and increase reuse of dependencies among modules.

More specifically, we have selected jQuery as the Javascript library.

As CSS framework, we use Blueprint CSS.

Developer convenience

Quick test cycle

When working on things which require lots of interactive testing, such as templates, CSS, etc. you can immediately try changes without having to rerun your build. With a simply command line switch, you let Kauri know that it should read module resources directly from your source tree, rather than from the compiled jar.

Project templates

Project templates (Maven archetypes) generate the basic structure for new projects.

Open Source

Kauri is available for free with source code included. The sources are released under the business-friendly Apache license.

Other

  • Packaging: Kauri includes a Maven plugin which can package your application together with all its dependencies so that it can be deployed or distributed. The package plugin can also generate a traditional Servlet webapp for deployment in legacy environments.

  • Security (coming soon)

  • Configuration (coming soon)