-
Notifications
You must be signed in to change notification settings - Fork 15
The Server side AMD Config file
The server-side AMD configuration is a JavaScript object that closely mirrors the client-side AMD configuration as detailed on the RequreJS web site and defines the paths and packages that relate AMD module identifiers to JavaScript and other resources, however, instead of specifying web resources, the server-side AMD config specifies URIs to resources on the server. The config file itself is specified as a resource URI. If the URI is not absolute (i.e. protocol specified), then the it is assumed to reside in the OSGi bundle that contains the plugin.xml defining the servlet.
Server-side resources are specified using Universal Resource Identifiers (URIs) as specified by the java.net.URI class. The Aggregator provides support for URIs using the standard file
protocol for files that reside on the server's file system, and the non-standard, Aggregator defined, namedbundleresource
protocol for resources residing in OSGi bundles.
The URI to the server-side AMD config file is specified using the config
servlet init-param in the <servlet>
element defining the servlet.
The namedbundleresource
protocol allows resources to be specified using the bundle symbolic name that the resource is contained in. A namedbundleresource
URI looks similar to the following:
namedbundleresource://com.ibm.jaggr.sample.dojo/WebContent/dojo-release-1.8.0-src/dojo
which specifies the resource path /WebContent/dojo-release-1.8.0-src/dojo
within the OSGi bundle with the symbolic name com.ibm.jaggr.sampled.dojo
. URIs specified using the namedbundleresource
protocol are not universal because multiple resources residing in different bundles using the same symbolic name may exist, and which resource the URI resolves to depends on the behavior of the OSGi class loader as it relates to resolving bundles. This ambiguity violates the rules governing URIs. It is, never the less, convenient to be able to specify resources that reside in named bundles using the URI syntax, so the Aggregator supports the use of the namedbundleresource
protocol for URIs specified within the server-side AMD config file. The ambiguity around which bundle to use is dealt with by ensuring that the class loader of the application's bundle (the bundle containing the plugin.xml defining the servlet) is always used to load the bundle whose name is specified in the host part of the URI.
The Aggregator may be extended using the com.ibm.jaggr.service.resourcefactory extension point to support additional URI protocols, providing the ability to extend support to include resources residing within jar files, databases, etc. The default file
and namedbundleresource
protocols are supported using classes that implement this extension.
Strings of the form ${propertyName}
may appear anywhere within the config JavaScript and will be replaced with the value of the named property. The value is obtained by calling BundleContext.getProperty()
using the BundleContext of the contributing bundle, or if the named property is not defined there, then by calling any registered OSGi services that support the com.ibm.jaggr.service.IVariableResolver interface. Variable property substitution is performed before script evaluation. If a value cannot be found for a named property, then the string is left un-modified.
When the server-side config javascript is being evaluated, the following JavaScript variables are defined and in scope, and may be referenced by JavaScript expressions in your config:
- initParams
- An object of the name-value pairs defined in the servlet-init-params
- options
- An object of the name-value pairs defined in the Aggregator options
- headers
- An object of the name-value pairs specified in the bundle manifest for the contributing bundle (i.e. the bundle that instantiated the servlet)
- console
- An object containing logging methods such as error, warn, info and log. These methods can be used to write messages to the server logs from javascript code in the config
- getProperty
- A function that returns the value of the named property. This function can be used as an alternative to Variable Property Substitution. The only difference is in when the evaluation is performed (script execution time vs. config file load time) and the result when the property does not have a value (null vs. the original string).
- getBundleVersionsHash (version 1.2)
-
A function that returns an MD5 hash of the bundle header properties (default: Bundle-Version) for the specified bundles. If the first argument is an array, then the array specifies the list of bundle header properties to include, followed by the bundle names. Syntax is:
getBundleVersionsHash('com.acme.bundle1', 'com.acme.bundle2', ...);
It is convenient to assign the value returned by the function to the cacheBust config property because the value will automatically change whenever the values of any of the bundle headers in any of the specified bundles changes.getBundleVersionsHash(['Bundle-Version', 'Bnd-LastModified'], 'com.acme.bundle1', 'com.acme.bundle2', ...);
The function recognizes a period when used as a bundle name to indicate the current, or contributing bundle. This is the bundle who's plugin.xml contains the servlet tag that instantiated the aggregator.
See the sample application's server-side AMD config file, testaggr-config.js for example usage of this property.
This function is new in version 1.2.
In addition to the functions and properties listed above, the config scope may be extended by third parties using the com.ibm.jaggr.core.config.IConfigScopeModifier interface. Implementations of this interface are registered with the OSGi service registry either through application code or via the com.ibm.jaggr.service.serviceprovider extension point. The getBundleVersionsHash()
function is implemented this way and may be used as an example of how to extend the config scope.
This feature is new in version 1.2
The baseUrl
, paths
and location
properties specify resource URIs which may be either a string value, or a two element array of strings specifying primary and override URIs. The idea behind override URIs is to facilitate product customization by supporting a location on the file system where customized resources may be placed. Resources that exist in the override locations will be used instead of the corresponding resources in the location specified by the primary URI. In this scenario, the primary URI typically specifies an OSGi bundle, using the namedbundleresource URI scheme, while the override URI specifies a customization area on the server's file system.
Property Name | Description |
---|---|
baseUrl |
The base URI to use for all relative URIs specified in this config. If baseUrl is not absolute, then it is assumed to be relative to the root of the bundle defining the servlet. Note that the property name specifies Url, with a lower-case L, instead of URI with an upper-case i, to maintain symmetry with the client-side config. This property may specify a single URI or primary and override URIs as described in Override URIs.
Files and folders located under the folder specified by baseUrl are not scanned when the Aggregator builds the module dependency map used for require list expansion unless the depsIncludeBaseUrl property is specified with a value of true.
|
paths |
Path mappings for module names to resource URIs. The path URIs are assumed to be relative to baseUrl , unless the URI starts with a "/" or specfies a protocol. If the path URI starts with a "/", then the path is assumed to be relative to the root of the bundle defining the servlet. Path entries may specify a single URI or primary and override URIs as described in Override URIs. |
packages |
Defines the packages for the application. A package can be assocated with a module name/prefix. The package config can specify the following properties for a specific package:
|
aliases |
Specifies an array of vector pairs with alias mappings. Each array entry is a two element array with the first element specifying the string to replace, and the second element specify the replacement. Two forms of alias mappings are supported. The first form is a simple string substitution mapping with the first entry specifying the string to replace and the second specifying the string to replace it with. For example:
aliases: [ ["text", "dojo/text"] ] The second form allows for regular expression pattern mapping and the specification of the replacement as a string or as a function, For replacement functions, the has() function may be called to query the feature set specified in the request. Note that unlike the aliases: [ [/^(.*)\/foo\/(.*)$/, "$1/bar/$2"] [/^(.*)\/backend\/(.*)$/, function($0,$1,$2){ return $1+(has("foo")? "/foo/":(has("bar")? "/bar/":"/backend/"))+$2; } ] ] Server-side aliases are provided in support of client-side aliases, which are supported by some AMD loaders including the Dojo loader. In general, server-side and client-side aliases should produce the same mappings. Because client-side aliases are resolved on the client before modules are requested, server-side aliases are not used to find requested modules. Instead, they are used in dependency expansion, in order to locate dependent modules so that they can be expanded within a list of Regular expressions specified in alias mappings are evaluated using Java regular expression classes for performance reasons, so you need to be aware of the subtle differences between java and javascript regular expressions. In addition to the JavaScript variables defined in Scoped variables above, the following variables are defined and in scope and may be referenced by your alias resolver function:
|
depsIncludeBaseUrl |
Optional. If specified with a value of true, then the files and folders under the directory specified by baseUrl will be scanned when the Aggregator builds the module dependency map used for Require list expansion. If false, then only the paths specified by the paths and packages properties are scanned. The default value is false. |
depScanIncludeExtensions |
Optional. Specifies the file extensions, as an array of strings, of resources to include when scanning for dependencies and building the module id name map. The extensions js , html and css are included by default and don't need to be specified.Module id name mapping is used to encode requested modules in Aggregator URLs. If a requested module is not included in the module id name map, then it will be requested by name. Requesting modules by name consumes much more URL space than requesting modules using mapped id, so adding the extensions of resource requested by your application using aggregator supported loader plugins can reduce URL lengths and eliminate request splitting due to URL length limits being exceeded. |
expires |
Optional. Specifies the number of seconds in the future that cached responses in third-party caches should be validated by the server. Specifically, it specifies the value of the Cache-Control:max-age header that is returned with Aggregator responses. If this property is not specified, then no Cache-Control:max-age header is returned in the response. |
coerceUndefinedToFalse | If true, then the Aggregator will treat undefined features as if they were defined with a value of false. This applies to has.js feature trimming of javascript code. If this value is false, then has.js conditionals for undefined features are left unchanged. If the value is true, then conditionals involving undefined features are trimmed based on the value of the feature evaluating to false. The default value for this option is false. |
cacheBust | An arbitrary string specified by the application that is associated with the serialized meta-data for Aggregator caches and the module dependency maps. When these data structures are de-serialized on server restarts, the saved value is compared against the value that is read from the current config, and if the values don't match, then the de-serialized data is discarded and the caches and dependency maps are deleted and rebuilt. |
notice |
Specifies a URI to a resource containing arbitrary text that is included at the beginning of every Aggregator response. The notice text should be in the form of a JavaScript block comment. The Aggregator does not do any processing on the notice text. If the URI is relative, it is assumed to be relative to the location of the config file. |
textPluginDelegators | Specifies an array of loader plugin module ids that delegate to the default text loader plugin. When performing server-side layer expansion of dependencies, dependencies that specify plugins included in this list will be expanded in the response as if they were required by the text plugin. |
jsPluginDelegators |
Specifies an array of loader plugin module names that delegate to the AMD loader for javascript modules. An example of such a plugin is the i18n loader plugin. When performing server-side layer expansion of dependencies, dependencies that specify plugins included in this list will be expanded in the response. Note: Starting with version 1.2.1, the i18n plugin is no longer included in this property by default. |
cachePrimerBundleName |
Specifies the bundle symbolic name of an optional [cache-primer bundle](Caching#the-cache-primer-bundle). If specified, then the Aggregator will attempt to load the bundle at startup and use the contents of the bundle to prime the Aggregator cache if it is empty or stale. This property was introduced in version 1.3 |
compilerOptions |
Specifies Google Closure Compiler options to use when compiling JavaScript files. The options are specified as a property map of name/value pairs. The property names correspond to property names supported by the CompilerOptions class. The names can be any property which is either declared as a public field or has a setter method which can be mapped to the property name using standard JavaBean property naming convention. The value is an array who's number and types of elements matches the number and types of the formal parameters defined by the setter method. If the setter method takes exactly one parameter, or the property is a public field which has no setter method, then the array notation may be dispensed with and the single parameter may be specified directly as in the following examples: compilerOptions: { /* * calls * setDefineToBooleanLiteral("defineName", true); */ defineToBooleanLiteral:['defineName', true] } compilerOptions: { /* * this is identical to acceptConstKeyword:[true]. * Both will invoke setAcceptConstKeyword(true); */ acceptConstKeyword:true } compilerOptions: { /* * setAliasableStrings takes a java.util.Set, so * need to use a nested array so that the string * set will be passed as a single parameter. */ aliasableStrings:[['foo', 'bar']] } The following JavaScript to Java property value conversions will be performed when attempting to match the provided values to the value types declared by the class:
compilerOptions: { /* * This invokes * setCheckGlobalThisLevel(CheckLevel.WARNING); */ checkGlobalThisLevel:'WARNING' } This property was introduced in version 1.3.7. |
Aggregator extensions may support additional properties. For example, the CSS module builder supports config properties for controlling in-lining of image references and imported CSS. |
{ /* * Paths are relative the WebContent folder of the bundle containing this config. */ baseUrl: ['WebContent', '${MYAPP_CUSTOMIZATIONS}'],packages: [ { name: 'dojo', location: ['namedbundleresource://org.dojo-1.8.res/WebContent/dojo', 'dojo'], lib: '.' }, { name: 'dijit', location: ['namedbundleresource://org.dojo-1.8.res/WebContent/dijit', 'dijit'], lib: '.' }, { name: 'dojox', location: ['namedbundleresource://org.dojo-1.8.res/WebContent/dojox', 'dojox'], lib: '.' } ], paths: { "css": "js/css" // uses override path derived from baseUrl (i.e. ${MYAPP_CUSTOMIZATIONS}/js/css) }, expires: 3153600, cacheBust: headers["Bundle-Version"]
}
The following example shows how you can define a JavaScript function that can later be called from within an alias resolver function:
(function() { /* Define transform function in config scope */ function transform(a, b, c) { a+(has("foo")?"/foo/":(has("bar")?"/bar/":c))+b }; return { baseUrl: '...', packages: [...], aliases: [ [/^(.*)\/backend\/(.*)$/, function($0,$1,$2){return transform($1, $2, '/backend/');}], ], }; })();