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 itemdescription
- Shold hold the description for this permission itemgroup
- Should be the name of the group. This name should be present in thepermissionGroups
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 formatprovider-code/app-code
group
- Name of the permission group that belongs to theapp
and contains the needed permissionpermission
- 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 haveaalam/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
- Settings code The code of defined for a setting in the application’s settings map object.
- 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 theinput_value
to be valid for thesettings_code
String message
When the validator find an error with theinput_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 && ./configure && 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.