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.
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 correspondingivy.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 processesincludeFile 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" }
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
}]
- 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
Interpretertype. The default list of registered types is:-
.classfor Java. The value is the fully-qualified class name with a ".class" suffix, such as"your.pkg.Handler.class". -
.groovyfor Groovy scripts, which are searched inapp/scripts. Use slashes for path delimiters, such as"foo/bar/handler.groovy". -
.gtfor Groovy templates, which are searched inapp/views. Use slashes for path delimiters, such as"foo/bar/handler.gt". -
.phpfor PHP scripts, which are searched inapp/scripts. Use slashes for path delimiter, such as"foo/bar/handler.php".
-
- conditions is optional. The value of the
conditionsis 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
eventzone.
Condition operators
-
global context URI -
trueonly 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 theeventzone for the handler.
For example,"/request/path == /foo/bar/{next}]. The value ofnextis available to the invoked handler in the global context at/event/nextcontains 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 totrue, and the handler is invoked with/event/matchedURI==/aand/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==/aand/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}
}
}]
@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 theRun 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.