Submit a java app

This document explains in detail, how to submit a JAVA application to Aalam apps server

File Format

The file to be uploaded is created by the Aalam’s maven plugin aalam-maven-plugin. When built using maven, the build plugin creates a file at target/aalam/package.tar.gz. This is the file that needs to be uploaded.

Framework Dependency in pom.xml

In the list of dependencies for the application, aalam-common should be included with the appropriate version, like

<dependency>
    <groupId>cm.aalam.common</groupId>
    <artifactId>aalam-common</artifactId>
    <version>An appriate version</version>
</dependency>

Build plugin in pom.xml

In the list of build plugins, one should add aalam-maven-plugin to create the uploadable file.

<build>
    <plugins>
        <plugin>
            <groupId>cm.aalam.maven</groupId>
            <artifactId>aalam-maven-plugin</artifactId>
            <version>An appropriate version</version>
            <configuration>
            </configuration>
        </plugin>
    </plugins>
</build>

Aalam build plugin configuration

Following are the configuration items for building.

entryPoint

This is mandatory.

The value refers to the entry point of the application code from the framework. Value of the entryPoint should in the following format

public.class.path:static_method_name

For example, if the entry point method is public static Callbacks app_entry(int state) is in cm/aalam/demo/TestApp.java the entry point will be

<entryPoint>
    cm.aalam.demo.TestApp:app_entry
<entryPoint>

staticsUrl

This is optional

The prefix of the url on which all the static files are served. For the static resources that are not served through urls starting with this prefix, has to have a URL route registered for the same.

Following this prefix, the URL should have the path to the file. Files will be looked up using getResources(). The resource name should be relative to that of the resources folder. For example, for a URL /aalam/base/s/contacts/script.js and a staticsUrl /aalam/base/s, the file will be looked up as getResources("/contacts/scripts.js").

With this setting, the application does not need to register explicit URLs to serve static resources. The framework will automatically control the response to these requests.

The value should be added to the configuration like

<staticsUrl>
    /aalam/base/s
</staticsUrl>

permissions

Permissions are configured with multiple items.

Permissions of an app are grouped under a name. Every permission name will have a group name. A permission of an app is identified by group-name/permission-name within the app. And the same is referred as provider-code/app-code/group-name/permission-name by other applications.

groups

This contains all the permission groups for this application. The child elements this elements are the name of permission groups. It will of the following format

<groups>
    <group>
        <name>PermissionGroupName1</name>
        <description>Description PermissionGroupName1</description>
    </group>
    <group>
        <name>PermissionGroupName2</name>
        <description>Description PermissionGroupName2</description>
    </group>
    .
    .
    <group>
        <name>PermissionGroupNameN</name>
        <description>Description PermissionGroupNameN</description>
    </group>
</group>

The permission group name and the permission name should abide by the following rules

  • Can contain only alpha numeric character and hyphen ‘-‘
  • Should not start with hyphen

permissions

This is optional

This contains a list of permission items which inturn contains the details of a permission item. Following is the format

<permissions>
    <permission>
        <code>permissionName11</code>
        <description>Description for permissionName11</description>
        <group>PermGroupName1</group>
    </permission>
    <permission>
        <code>permissionName12</code>
        <description>Description for permissionName12</description>
        <group>PermGroupName1</group>
    </permission>
    <permission>
        <code>permissionName21</code>
        <description>Description for permissionName21</description>
        <group>PermGroupName2</group>
    </permission>
</permissions>

Each permission item should have three children

  • code - Should have the name for the permission item
  • description - Shold hold the description for this permission item
  • group - Should be the name of the group. This name should be present in the permissionGroups

requires

This contains a list of permissions required by the application. These are the permissions of other application that this application needs to use to access the APIs of other applications.

Following is the format

<requires>
    <require>
        <app>providerCode1/appCode1</app>
        <group>PermissionGroupName1</group>
        <permission>permissionName1</permission>
    </require>
    <require>
        <app>providercode2/appcode2</app>
        <group>permissiongroupName2</group>
        <permission>permissionName2</permission>
    </require>
    .
    .
    <require>
        <app>providercode-n/appcode-n</app>
        <group>permissiongroupName-n</group>
        <permission>permissionName-n</permission>
    </require>
</requires>

Each children of requires are require which should have the following three items

  • app - Application identifier in the format provider-code/app-code
  • group - Name of the permission group that belongs to the app and contains the needed permission
  • permission - The name of the permission.

Everything put together will like below

<permissions>
    <groups>
        <group>
            <name>General</name>
            <description>Generic permission for the java application</description>
        </group>
    </groups>
    <permissions>
        <permission>
            <name>access</name>
            <description>Access the index page of the java testapp</description>
            <group>General</group>
        </permission>
        <permission>
            <name>create</name>
            <description>Create database entries</description>
            <group>General</group>
        </permission>
    </permissions>
    <requires>
        <require>
            <app>aalam/base</app>
            <group>Users</group>
            <permission>manage</permission>
        </require>
        <require>
            <app>aalam/base</app>
            <group>Contacts</group>
            <permission>create</permission>
        </require>
    </requires>
</permissions>

messages

This is optional

This contains a list of message items which contains the details of the message templates.

This item defines the list of message templates used while sending alerts. For example, when an app is installed in a portal an alert will be posted to some users with a fixed template.

Each key in the value refers to the name of a message group. Message can be grouped, so that it becomes easier for the users to follow/unfollow all the message in a group.

Each message template is identified by it’s index value. The index value should be unique across this message map.

Format is as below

<messages>
    <message>
       <index>1</index>
       <body>Template value 1, {dynamic_variable}</body>
       <group>MessageGroupName1</group>
    </message>
    <message>
       <index>2</index>
       <body>Template value 2, {dynamic_variable}</body>
       <group>MessageGroup1</group>
    </message>
    <message>
       <index>3</index>
       <body>Template value 3, a static template</body>
       <group>MessageGroupName2</group>
    </message>
</messages>

body contains the message template. Any dynamic value that needs to formatted on the template should be put within {}. The value for the dynamic variables will be given the application while posting the message. For example, when an application is stopped, the template can have the {app_name} as a dynamic variable and will supply the value for the {app_name} which is stopped, at the time of posting this message.

A real world example will be like

<messages>
    <message>
        <index>0</index>
        <body>
            Welcome to this portal. You are the administrator to this portal.
        </body>
        <group>WelcomeMessages</group>
    </message>
    <message>
        <index>1</index>
        <body>Welcome! You can check you permissions here.</body>
        <group>WelcomeMessages</group>
    </message>
    <message>
        <index>2</index>
        <body>New app - {app_name} is installed by {user}</body>
        <group>AppMessages</group>
    </message>
    <message>
        <index>3</index>
        <body>'{app_name}' is uninstalled by '{user}'</body>
        <group>AppMessages</group>
    </message>
</messages>

In the above example, we have two groups.

  • WelcomeMessages are the message that the application sends whenever a new user joing this portal. The index 0 mesage body is used for posted the owner and index 1 is posted for posting other users.
  • AppMessages are the message sent when any app is installed or uninstalled. Items with {} will be replaced by relavant values.

settings

This is optional

This item defines the list of settings variables for an application. settings are variables for which the user chooses the values.

These variable will be listed under the app in the Settings app.

A setting variable is of two type

  • Global
Global settings are variables that is applicable to the entire portal. To modify a global setting, a user needs to have aalam/base/Settings/modify-globals permission. Example, date and time format is a global setting.

The value of these settings is the same for all the users.

  • Personal
Personal settings are the variables that are varies with the user’s choice. A user doesn’t need any extra permission to modify personal settings. Example, choice of a colour theme is a personal setting.

The value of these settings varies with the user’s choice.

The settings format is as below

<settings>
    <setting>
        <code>short_form_description. See "Code Specification"</code>
        <name>Detailed name, which will be seen by the user</name>
        <default>The default value to use till user chooses a value</default>
        <property>number/text/choices. See "Property specification"</property>
        <numberMax>Maximum number to accept. Applicable only of property is 'number'</numberMax>
        <numberMin>Minimum number to accept. Applicable only of property is 'number'</numberMin>
        <textMaxLen>Maximum length of text value to accept. Applicable only of property is 'text'</textMaxLen>
        <choicesType>(single | multiple). Applicable only if property is 'choices'</choicesType>
        <choicesMethod>(dropdown | boxes). Applicable only if property is 'choices'</choicesMethod>
        <choicesValues>
            <!-- This list of choices for the user to choose from.
                 Applicable only if the property is 'choices' !-->
            <value>Choice value 1</value>
            <value>Choice value 2</value>
            .
            .
            <value>Choice value 3</value>
        </choicesValues>
        <type>Global or Personal</type>
        <help>Information on how to input the values</help>
        <validator>Method name to be invoked for validation. See "Method Specification"</validator>
    <setting>
    .
    .
</settings>

Code Specification

Settings code is a short for description for a setting variable. The code value will not displayed to the user, it is to identify the setting by the framework and other applications.

It should abide by the following rule.

  • Can contain only alpha numeric and hyphen - characters.
  • Should not start with hyphen character.
  • It should be unique for an application.

Property Specification:

Every setting can have following property type

  • number
Integer or decimal value
  • text
String
  • Choices

Let the user to choose from a list of choices. If the choice type and method are

  • single, dropdown: A listbox will be displayed to choose the value
  • single, boxes: A set of radio buttons will be displayed
  • multiple, dropdown: List box with support for multiple selection will be displayed
  • multiple, boxes: A set of check boxes will be displayed.

Method Specification:

This is the method that will invoked by the framework whenever this setting is altered. The method name should be of the format

public.class.path:method_name

The validator methods should accept two parameters

  1. Settings code The code of defined for a setting in the application’s settings map object.
  2. Input value The value that was inputted by the user, for this settings_code

The method should return either of the following

  • null When the method find the input_value to be valid for the settings_code
  • String message When the validator find an error with the input_value. This message will be displayed to the user, so it will help if it is more informative.

A sample validator can be seen below

public class SettingsValidators {
    public static String colorValidator(String settingsCode, String inputValue) {
        if (!Arrays.asList(new String[]{"red", "green", "blue"}).contains(inputValue)) {
            /* Invalid value, return a error message. */
            return "Value should be either 'red', 'green' or 'blue'"
        }
        /* Value is valid, so return null. */
        return null
    }
}

hooks

This lists the set of hooks that this application is interested in. Please see the framework documentation for more information on hooks.

Value contains just child elements

  • items
List of URLs on other applications that this application wants to hook.
  • restricts
List of URLs on this application that it desires to restrict being hooked by other applications. One can include exceptions to the restrictions. When restricted, a URL can not be hooked by other applications.

hooks format is as below.

<hooks>
    <items>
        <item>
            <app>The app to be hooked in the format provider-code/app-code</app>
            <url>Url to be hooked <!-- See Hook URL format !--></url>
            <type>A or B or BA (Before, After or Both)</type>
            <method>Method on the URL to be hooked</method>
            <handler>The callback method name <! -- See, Hook callback !--></handler>
        </item>
        <item>
            <!-- Same as above !-->
        </item>
    </items>
    <restricts>
        <restrict>
            <url>Url to be restricted <!-- See Hook URL format !--></url>
            <type>A or B or BA (Before, After or Both)</type>
            <method>URL method to be restricted</method>
            <exceptions>
                <!-- The list of apps excluded for this restriction !-->
                <exception>Application identification in the formation provider-code/app-code</exception>
                <exception><!--Another app, in the format same as above!--></exception>
            </exceptions>
        </restrict>
        <restrict>
            <!-- Same as above !-->
        </restrict>
    </restricts>
</hooks>

Hook url format

If the url needs to be matched statically, then a static url can be used. For example, if you want to hook GET /aalam/base/user/user@test.test, you can input URL path as is. But if you want to include a wildcard match you have to use

/aalam/base/user/*

The asterik * matches an element with the slashes /<matches-only-this-value/. For example, the above will match the following url

/aalam/base/user/user1@test.test
/aalam/base/user/user2@test.test

But will not match

/aalam/base/user/user1@test.test/status

Wherever you want to add a wildcard match, keep an asterik *. For exampl,

/aalam/base/*/user1@test.test/*

Will match the following urls

/aalam/base/user/user1@test.test/status
/aalam/base/user/user1@test.test/info
/aalam/base/permissions/user1@test.test/assign

Hook Callback

Method name should be like

public.class.path:method_name

Refer the java framework documentation for more information on the parameters and the return values of the hook callback methods.


libdeps

libdeps are the additional dependencies in the form other than Java maven packages. For example, if your app depends on some libraries like libjpeg or libz those dependencies can be listed under libdeps.

The libdeps is nothing but a listing of a set of commands which fetches or builds some program or library and it’s artifacts that will be used by your app.

The packager runs on a tiny core linux based distribution. You can use tce-load to install .tcz packages.

For example, let’s say your app has a dependency for some Java package which has a native library which inturn depends on libz.so and libjpeg.so. libz.so is available from the tiny core linux package zlib_base-dev.tcz and libjpeg.so is available from the package libjpeg-turbo-dev.tcz. For your app to run properly, you would need these libraries.

In such a case your libdeps should be like the following

<libdeps>
  <libdep>
    <name>
      libz
    </name>
    <actions>
      <value>tce-load -wic zlib_base-dev</value>
    </actions>
    <artifacts>
      <value>/usr/lib/libz.so</value>
    </artifacts>
  </libdep>
  <libdep>
    <actions>
      <value>tce-load -wic libjpeg-turbo-dev</value>
    </actions>
    <artifacts>
      <value>/usr/local/lib/libjpeg.so.62</value>
    </artifacts>
  </libdep>
</libdeps>

In the above example, you can just have one action/artifact object to install both the libraries in one command.

Alternatively, you can even build libraries from source using make and gcc. If the building process needs libraries like autoconf, libtool etc, you can add an action to install these required .tcz packages before running the actual command to build the app.

<libdeps>
  <libdep>
    <name>Compile from source</name>
    <actions>
      <value>tce-load -wic cmake autoconf libtool curl</value>
      <value>curl -v https://url.of.the.source.archive | tar -xz -C /tmp/source-path</value>
      <value>cd /tmp/source-path &amp;&amp; ./configure &amp;&amp; make</value>
    </actions>
    <artifacts>
      <value>/tmp/source-path/buid-dir/lib.so</value>
    </artifacts>
  </libdep>
</libdeps>

publicRootable

By setting this property to True, you mean that this web application can serve the '/' (slash/root) page for the public (anonymous) users. The users can choose one such public rootable app from their apps list to serve it as a website for the public users. Apps that are publicly rootable should have the routes register for the same.

For example, if your app is public rootable, then you should be having a route for '/'. These routes work only for the anonymous users. For users who are authenticated, these routes will never be used. For authenticated users, routes starting with /<provider-code>/<app-code>/ alone will work.

eval_rst .. note:: Except `'/'` all the other routes should begin with `'/_/'`. Only then the requests will be routes to the public rootable app.

The value should be added to the configuration like

<publicRootable>True</publicRootable>

This is optional


depends

When your application depends on other applications, those dependecies must be listed under this section.

These dependencies are used while installing or updating any application. Each dependency should be given in the following format.

<depends>
  <depend>
    <provider_code>Provider code of the dependee app</provider_code>
    <app_code>App code of the dependee app</app_code>
    <pattern>The version as is or a regex pattern to match more than one version</pattern>
  </depend>
<depends>

You can still use APIs for other apps from your application even without listing them under this section. But there is no guarentee that that API will be successfull. For example, the Aalam Invoicer application depends on Aalam Stock app. It lists the Stock app unders its depends section. But the Aaalam invoicer can call API of other app say a payment service application. Since the payment service app is not listed under it’s list of dependencies, there is no guarentee that the payment service is present or not, event it is present, there is not guarentee that it’s version is suitable for it’s version.