Configuration

You can specify the properties and behavior of a IBM® WebSphere® sMash application in configuration files.

WebSphere sMash configuration file: zero.config

The configuration of a WebSphere sMash application is set in the config zone of the global context. Values are set to the config zone by way of configuration files. Configuration files for the application, and its dependencies, are processed when the application is started. Configuration files are essentially scripts that set and append values into the config zone. The syntax is based upon a simple grammar of global context URIs and JSON data structures. While processing configuration files, entries in the config zone are handled with a "first one wins" strategy:
  • Set values once. Subsequent attempts to set a value at an existent global context URI are denied.
  • Append values to arrays.
  • Append key/value pairs to objects, provided that the key is not already set in that object.
After processing the configuration files, the config zone is read-only. Although you can change the values by application code, not all changes affect the running application. For example, you must restart the application to apply changes in /config/http/port.

The zero.config file is shown in the following example:

# Value set
/config/http/port = 8080

# List set
/config/resources/defaultExtensions = [".groovy"]

# List append
/config/bindings/.groovy += ["zero.core.groovysupport.bindings.DefaultBindings"]

# Map set
/config/test/map = { "a" : "b", "c" : "d" }

# Map append
/config/test/mapappend += { "a" : "b", "c" : "d" }
/config/test/mapappend += { "x" : "y", "w" : "z" }

# Event handler
/config/handlers += [{
  "events" : "GET",
  "handler" : "custom.Handler.class"
}]

# Value reference (insert value read at config-load time)
/config/property/myPrefix = "/foo/bar"
/config/test/value = "${/config/property/myPrefix}/bat"

# Variable set/value reference
myPrefix = "/foo/bar"
/config/test/value = "${myPrefix}/bat"

# Include
@include "${/config/dependencies/zero.core}/config/security/form.config"
{ "formLoginPage" : "/login" }

Configuration syntax

Syntax Description Example
GC_URI = JSON_value Set a value at global context URI
See zput for details
/config/http/port = 8080
GC_URI += JSON_value Set or append a value at global context URI
See zpost for details
/config/bindings/.groovy += ["zero.core.groovysupport.bindings.DefaultBindings"]
variable = JSON_value Variable set myPrefix = "/foo/bar"
${GC_URI} Global context value reference
Value is read at configuration-load time
/config/longname = "Application:  ${/config/name}"
${variable} Variable value reference /config/contextRoot = ${myPrefix}
@include JSON_string [JSON_object] Process another configuration file, with optional variables specified as a JSON_object @include "${/config/dependencies/zero.core}/config/security/form.config"
{ "formLoginPage" : "/login" }
# comment Comments # This is a comment

JSON_value can be any of the valid JSON types: object, array, string, number, true, false, and null.

GC_URI is of the form /<zone>/<path>. variable consists of alphanumeric characters (a-z, A-Z, 0-9) and underscore. You can use value references, such as variable and global context, anywhere a JSON object is expected, such as /config/contextRoot = ${myPrefix}. You can embed value references that refer to string types within a JSON string, such as /config/longname = "Application:  ${/config/name}".

Resolved dependency locations

Root directories of resolved dependencies are available as global context value references. The location is ${/config/dependencies/moduleName}, where the module name of the dependency matches the name specified in the corresponding ivy.xml files, such as zero.core.

You can obtain the root directory for each dependency from the global context:
List<String> listOfDependencies = zget("/config/dependencies");
for (String dependency : listOfDependencies) {
    String dependencyRoot = zget("/config/dependencies/" + dependency);
     // Operate on the dependencyRoot (load files)
}

Include

WebSphere sMash processes includeFile as a configuration file, as shown in the following example:

@include "${/config/dependencies/zero.core}/config/security/form.config"

includeFile can be an absolute or relative file reference. Relative references are relative to the including file. Included files are now virtualized, so you can rewrite the preceding example as @include "security/form.config", which resolves to form.config in the config/security sub-directory of a dependent project.

You can pass optional arguments as a JSON_Object.

@include "${/config/dependencies/zero.core}/config/security/form.config"
{ "formLoginPage" : "/login" }

Configuration properties set within includeFile are scoped to that file and any files included by it. Properties are immutable within their scope, so the first takes priority.

Comments

Lines that begin with a hash (#) are comments.

Storage formats

The following table describes how JSON types from configuration files are stored in the global context:

JSON type Stored in the GC as a Java instance of ...
JSON object Map<String, Object>
JSON array List<Object>
string String ('$' is reserved; literal value escaped as '$$')
number long or double
true true
false false
null null

Event-handler registration

Event handlers are registered by way of configuration files. The complete syntax has the following form:
/config/handlers += [{
  "events" : JSON_string or JSON_array(JSON_string),
  "handler" : JSON_string,
  "conditions" : JSON_string,
  "instanceData" : JSON_object
}]
where
  • events is the name, or list of names, of the events handled by this handler
  • handler is the name of the handler, including a suffix that must match a registered Interpreter type. The default list of registered types is:
    • .class for Java. The value is the fully-qualified class name with a ".class" suffix, such as "your.pkg.Handler.class".
    • .groovy for Groovy scripts, which are searched in app/scripts. Use slashes for path delimiters, such as "foo/bar/handler.groovy".
    • .gt for Groovy templates, which are searched in app/views. Use slashes for path delimiters, such as "foo/bar/handler.gt".
    • .php for PHP scripts, which are searched in app/scripts. Use slashes for path delimiter, such as "foo/bar/handler.php".
  • conditions is optional. The value of the conditions is computed during run time. If not specified, then the handler is always a match for the corresponding event.
  • instanceData is optional. This data is provided to the handler in the event zone.

Condition operators

global context URI
true only if the global context contains the specified key.
For example, "conditions" : "/request/status"
==
Selector pattern match. Named groups are specified as {name}. Matches can be qualified, such as {name:any}. Values of named groups are set in the event zone for the handler.
For example, "/request/path == /foo/bar/{next}]. The value of next is available to the invoked handler in the global context at /event/next contains value. The following list contains the qualifiers:
any
Matches to the end.
For example, if /request/path == /a/b/c, then "/request/path == /a/{remainder:any}" evaluates to true, and the handler is invoked with /event/matchedURI == /a and /event/remainder == b/c.

The pipe character | also matches to the end of the URI and, additionally, sets /event/pathInfo.
For example, if /request/path == /a/b/c, then "/request/path == /a|" evaluates to true and the handler is invoked with /event/matchedURI == /a and /event/pathInfo == /b/c.
Note: | is valid only as the last character in the selector pattern or last except for right brackets. For example, "/request/path == /a/b|" and "/request/path == /a[/b|]" are valid; "/request/path == /a|/b" is not.
element
Matches to the next slash.
digit
Matches one or more digits: [0-9].
word
Matches one or more word characters: [a-zA-Z_0-9].
=~
Regex pattern match, based upon the regular expression support in the JDK.
For example, "/request/path =~ /foo/.*"
Example: "/event/resolvingEvent =~ (GET|POST|DELETE|PUT)"
!
Negates the condition value; placed before the operator it modifies.
Example: "!(/request/status)"
!=
Not URI matches
Example: "/request/path != /a/b"
!~
Not matches
Example: "/event/resolvingEvent !~ (GET|POST)"
&&
Logical AND
Example: "(/request/path != /a/b) && (/event/resolvingEvent !~ (GET|POST))"
||
Logical OR Example: "(/request/path == /a/b) || (/event/resolvingEvent =~ (GET|POST))"

Configuration templates

You can use a combination of @include and configuration properties to build configuration templates. For example, security support in zero.core uses configuration templates. Configuration template example: config/security/rule.config
authType=""
users=[]
groups=[]
roles=[]
requireSSL=false
csrfProtect=true


@include "requireSSL.config"{
	"conditions": ${conditions},
	"requireSSL": ${requireSSL},
	"authType" : ${authType},
	"csrfProtect" : ${csrfProtect}
}

/config/handlers += [{
	"events" : "authorize",
	"handler" : "zero.core.security.authorization.AuthorizationHandler.class",
	"conditions": ${conditions},
	"instanceData" : {
						"groups" : ${groups},
						"users" : ${users},
						"roles" : ${roles}
	}						
}]
Using a configuration template
@include "security/rule.config"{
   "conditions" : "(/request/path =~ /formauth/getonly(/.*)?) && (/request/method == GET)",
   "authType" : "Form",
   "groups" : ["ALL_AUTHENTICATED_USERS"]
}

Type-handler registration

Type handlers are registered by way of configuration files or programmatically. Each new type handler is registered by appending it to the list.
/config/typeHandlers += {
   "zero.core.context.types.commands.Command" : "zero.core.context.types.CommandTypeHandler"
}

Order of processing

WebSphere sMash enforces a "first one wins" strategy with configuration processing to ensure consistency throughout the application. As a result, you might need to understand the order in which configuration files are processed in cases that involve overwrites. By default, WebSphere sMash first processes <apphome>/config/zero.config, then processes config/zero.config for each dependency. The order in which dependencies are processed is described in Virtualized directories section. Although the config directory is not a virtualized directory, the order of processing configuration files is identical to the search order through dependencies within a virtualized directory.

Pre- and post-configuration files

Use pre- and post-configuration files to override application configuration settings without modifying any of the application files. Pre- and post- refer to the main configuration processing step: pre- occurs before the main configuration processing and post- occurs after. In Eclipse, you specify an alternate configuration file by modifying the Run profile for that WebSphere sMash application to set the program arguments to: [-pre <preConfigFile>] [-post <postConfigFile>] <applicationRootDirectory> From the command line:
zero run [-args "-pre <preConfigFile>"]
<configFile> can be an absolute or relative file reference. Relative file references are relative to the current working directory.

Version 1.1.0.0.21442