14. Deployment and Build System

14.1. Deployment

All plugins files should be created in a special separate plugin directory - webapp/plugins.

Each plugin or widget should have one separate directory. For example,*Spreed* plugin has the following items inside:

  • js - folder.
    • data - folder //all classes realted to working with data are stored here.
    • dialogs - folder //all classes realted to dialogs and ui should be placed here.
    • SpreedPlugin.js //cannot be sorted properly being the main plugin class and is separate.
  • php - folder.
    • data - folder //data stored here like list of languages and timezones.
    • inc - folder //php classes stored here.
  • resources - folder.
    • css - folder //css resources places here.
    • icons - folder // different icons stored here.
  • build.xml //for building spreed plugin (discussed further in chapter Build System).
  • config.php //defined php constants.
  • manifest.xml //manifest file.

Example widget hierarchy let be end of world widget:

  • js - folder.
    • FBWidget.js //widget class.
  • resources - folder.
    • css - folder //css files for widget placed here.
  • images - folder //images for widget go here.
    • facebook.png
  • build.xml
  • manifest.xml

If you want your plugin to be enabled/disabled using Zarafa Settings menu you should create a new folder in [WebApp root folder]/plugins directory with the name of your plugin e.g. plugins/facebook, plugins/spreed. There you should create at least two files:

  • manifest.xml
  • plugin.facebook.php

You may also create config.php file to set default value for your plugin settings. Here goes the example of FB plugin config.php file.

The subfolder names and hierarchy can be changed, but it still should stay intuitively understandable.

Manifest is a file, where all the files of your plugin are described. The structure should be strict:

<?xml version="1.0"?>
<!DOCTYPE plugin SYSTEM "manifest.dtd">
<plugin version="2">

        //First block represents the common info about plugin
        <info>
                <version>0.1</version>
                <name>facebook</name>
                <title>Zarafa Facebook Integration</title>
                <author>Zarafa</author>
                <authorURL>http://www.zarafa.com</authorURL>
                <description>Zarafa Facebook Integration, allows you to import your Facebook events to Zarafa calendar.</description>
        </info>

        //Second block describes where to find config file of your plugin
        <config>
                <configfile>config.php</configfile>
        </config>

        //Third block describes files that are used in your plugin
        <components>
                <component>
                        <files>
                        <server>
                                <serverfile>php/plugin.facebook.php</serverfile>
                        </server>
                        <client>
                                // loaded client files should have an attribute 'load', which can take one of three values:
                                //source, debug and release. Source are files that you created during development, debug - the one file,
                                //compiled from all your files, and the release is the compressed debug file.
                                <clientfile load="release">js/facebook.js</clientfile>
                                <clientfile load="debug">js/facebook-debug.js</clientfile>
                                <clientfile load="source">js/FacebookEventsPlugin.js</clientfile>
                                <clientfile load="source">js/FbEventSelectionDialog.js</clientfile>
                                <clientfile load="source">js/FbIntegrationDialog.js</clientfile>
                                <clientfile load="source">js/FbEventSelectionGrid.js</clientfile>
                                <clientfile load="source">js/FbIntegrationPanel.js</clientfile>
                                <clientfile load="source">js/data/FbEventDataReader.js</clientfile>
                                <clientfile load="source">js/data/FbEventProxy.js</clientfile>
                                <clientfile load="source">js/data/FbEventRecord.js</clientfile>
                                <clientfile load="source">js/data/FbEventStore.js</clientfile>
                        </client>
                        <resources>
                                //here are css files needed in your plugin
                                <resourcefile load="release">resources/css/facebook.css</resourcefile>
                                <resourcefile load="source">resources/css/plugin.facebookstyles.css</resourcefile>
                        </resources>
                </files>
                </component>
        </components>
</plugin>

14.2. Build System

The WebApp is a relatively complex application consisting of a server part, written in PHP, and a client part written in JavaScript. Tasks such as building, deploying, and testing the application, and also generating documentation are automated in a build system. The tool we use is Ant.

An important note here is that the build system is something that Zarafa company use, but it is not really mandatory for all plugin developers to use it too. Zarafa provides the required tools in the source package, but not in the normal installation packages. Plugin developers do not require the source package to create plugins, so the presence of build.xml is also completely optional and only can be present if plugin developers want to use Zarafa building system.

14.2.1. Getting Started

Prerequisites for using the build system is a Java 6 JDK and Ant. Other libraries and tools are kept in svn either as binaries or as source.

14.2.1.1. Linux

On most distributions both Java 6 and Ant should be in the repositories. Make sure you don’t get GNU Java (gcj) but get the sun jdk or openjdk. On Ubuntu, simply type:

sudo apt-get install sun-java6-jdk ant ant-optional
update-alternatives --auto java

Especially the last line is important since multiple versions of Java can be installed side by side on a system, and the default has to be selected explicitly. Ant should be installed and configured properly by your package manager.

14.2.1.2. Windows, Mac OSX

These platforms have not been tested, but should work. The Java 8 JDK can be downloaded from Oracle.

To test if everything works as it should, go to the root of you WebApp 7 folder and simply type ant. Your system should build the tools, build the client application, and run the test suite.

14.2.2. Ant Introduction

Ant is an XML-based build system written in Java, and is quite well known in the Java community. We have chosen Ant to build our application because many of the tools that we use to process our JavaScript code were written in Java, such as the ext-doc documentation tool, our own JsConcat concatenation tool and others.

Ant build files are XML files, usually called build.xml. They define a project with several nested properties, typedefs, and tasks. Here’s a partial example.

<project name="example" default="all">
        <property name="foo" value="bar"/>

        <target name="all" depends="compile"/>

        <target name="init">
                <!-- do something here -->
        </target>

        <target name="compile" depends="init">
                <!-- do something here -->
        </target>
</project>

The target tag defines a target. Targets have nested tasks, like calling a compiler, creating an output directory etc. The property tag acts like key=value in make, with the exception that properties are defined only once and become immutable. Any redefinition of the property is ignored. The following example illustrates the use of properties and how redefinitions are ignored:

<project name="example2" default="all">
        <property name="foo" value="bar"/>
        <property name="foo" value="not bar"/>
        <!-- Will output 'bar' -->
        <echo message="${foo}"/>
</project>

This mechanism is used by ant build files calling other build files. If an ant file calls another ant file, to build a sub project for instance, the caller may override properties in the callee to set configuration switches, output directories, and so forth. Properties in ant build files may also be overridden from the command line. Running the above example with and -Dfoo=foo would cause ant to echo foo.

Ant is a build system that can be both powerful and frustrating, and it is certainly quite different from tools like make or scons. For more information, please refer to the Ant manual.

14.2.3. Tools

The build system uses several tools to accomplish various tasks. Some of these are third-party, and some of these are custom.

14.2.3.1. JsConcat

Large Ext JS applications tend to be made up of many individual files. Our naming convention dictates that most classes are defined in their own files. When the application is deployed all these files are bundled together by concatenating them into a single JavaScript file, which is then minimised.

A standard concat ant task exists that concatenates a set of files. The file order is important because files may depend on one or more global variables declared other files. Specifically in Ext JS applications, if some class Foo extends another class Bar, bar.js must be included before foo.js. It is possible to specify this inclusion order by hand, but considering the large number of files to manage, this is a maintenance nightmare. Therefore JsConcat was created, a concatenation task that scans the input files and determines the proper inclusion order automatically.

Inclusion Order

There are three ways to influence the inclusion order. First, there are explicit dependencies that you can enter in your file:

/*
 * This file needs to be included after bar.js
 * #dependsFile /foo/bar.js
 */

Dependencies are also extracted from @class and @extends:

/**
 * Foo extends Bar, so the file in which Bar is defined should come before this file.
 * @class Foo
 * @extends Bar
 */

Finally, formatted as a comma-separated list of regular expressions, the prioritise argument can be used to move groups of files up the list. Files that have classes defined in them have those full class names matched against the regexps. Files that match the first priority group have the highest priority, files that match the second group come after that, and so on. We use this mainly to move the core and common packages to the top of the list.

For example,”+, Foo.bar.*” will move all files which have classes in the root package (i.e. Date, Foo) to the top of the list, after wich come all files which have classes in Foo.bar or any of its descending packages, and finally all the files that match neither of these criteria.

Example Build File

<!-- Define the 'jsconcat' task -->
<taskdef name="jsconcat" classname="com.zarafa.jsconcat.JsConcatTask">
        <classpath path="JsConcat.jar"/>
</taskdef>

<!-- Concatenates JavaScript files with automatic dependency generation -->
<target name="concat">
        <jsconcat verbose="false" destfile="${debugfile}" prioritize="\w+, Foo.bar.*">
                <fileset dir="${sourcedir}" includes="**/*.js"/>
        </jsconcat>
</target>

14.2.3.2. Ext-doc

Ext JS comes with a JavaDoc inspired code documentation tool that generates nice HTML documentation. There is a fork of this tool in the svn that supports extra tags to document insertion points. More information can be found at the ext-doc google project page.

14.2.3.3. Closure Compiler

The Closure Compiler is a Javascript minimisation tool from Google. It will compile a concatenated JavaScript file. It supports multiple compile modes, only whitespace guarantees to only change the whitespaces and minimise the Javascript file without changing the code itself. The other compilation modes will change the code itself (for example, rename variables, make functions inline, etc).