In addition to defining and issuing requests at the
physical level,
requests may be declared at the logical level using the
standard declarative request syntax and issued
by a variety of
tools and services.
Syntax
The standard declarative request is an XML fragment which
can be included within XML documents used by tools
and service configurations.
It must have a root element which is usually
request (alternates include setup
and
teardown
in
XUnit)
and it must have an identifier child element.
<request>
<identifier />
</request>
The request may have the
verb,
representation,
argument and
varargs
child elements.
identifier
The request identifier element may be either a resource identifier:
<request>
<identifier>res:/resources/readme.txt</identifier>
</request>
or, with the meta: prefix, a logical endpoint identifier:
<request>
<identifier>meta:xrl:widget-box</identifier>
</request>
If a logical endpoint identifier is used then a request
with the META verb is issued to retrieve the grammar of
the logical endpoint.
That grammar then guides the construction of a
resource identifier to be used in the request.
The identifier may contain Argument Subsitutions.
verb
The optional verb child element must have the text value
SOURCE, SINK, NEW, EXISTS, DELETE, META or TRANSREPT.
If the verb child element it is omitted, the request uses the SOURCE verb.
For example, the following request specifies the SINK verb:
<request>
<identifier />
<verb>SINK</verb>
</request>
representation
The optional representation child element specifies the required
representation type (Java class or interface) of the returned representation.
For example, the following request specifies that the returned representation
must be a object of the type
java.lang.String:
<request>
<identifier />
<representation>java.lang.String</representation>
</request>
argument
Request arguments are included by using the argument child element
which must have a name attribute specifying the name of the argument.
argument contents
Argument elements may contain one of three types of content:
pass by reference string literal - this string is used as the argument value and is substituted into the constructed identifier. These string literals may contain Argument Subsitutions.
For example, the following defines a request for the toUpper service with the named
argument operand specifying the resource to be converted to upper case:
<request>
<identifier>active:toUpper</identifier>
<argument name="operand">res:/resources/readme.txt</argument>
</request>
pass by value literal - when the argument element contains a child literal element a representation is constructed and is added as a pass-by-value argument.
For more details see the literals section. For example:
<request>
<identifier>active:toUpper</identifier>
<argument name="operand">
<literal type="string">This is a String!</literal>
</argument>
</request>
request - (advanced) when the argument element contains a child request element a request is constructed and is added as a pass-by-request argument.
For example:
<request>
<identifier>active:toUpper</identifier>
<argument name="operand">
<request>
<identifier>active:generateRandomString</identifier>
<argument name="length">
<literal type="integer">80</literal>
</argument>
</request>
</argument>
</request>
Using pass-by-request is useful for explicit chaining of requests and also has the advantage of lazy evaluation
which can be useful if that argument may never need to be evaluated due to some conditional
processing. However when using pass-by-request it is very easy to inhibit cachability of your resources.
This is due the the complexity of the
request scope that can occur with deeply nested sub-requests.
Therefore it is not recommended to use pass-by-request for anything other than prototyping unless you really know what you
are doing! Using
DPML is good alternative which allows for nested requests in a declarative way and
has been optimised to enable good cachability.
argument method
By default the way an argument is added to the request is dependent upon how that argument is specified, i.e. whether it is
specified as a string literal, pass-by-value literal or a request. However it is possible to override this default behaviour using
a method attribute on the argument element. When an argument is specified as a request it is not possible to specify a method.
When an argument is specified as a literal the only valid method is "data-uri".
| Method |
Description |
| value |
The string literal is treated as a resource identifier and SOURCEd before being added as a pass-by-value argument. |
| data-uri |
The argument's representation is converted into a data URI and passed by reference. If
the argument is specified as an identifier it is first SOURCEd. |
| as-string |
This method is useful for converting an incoming pass-by-reference arguments to pass-by-value. Incoming
arguments are the arguments that are received by the endpoint which is constructing the declarative request.
The string value of the argument is converted to a string representation and added as a pass-by-value argument to the request.
It is only meaningful to use this method with arg: identifiers, for example if we have an incoming request with the following identifier:
res:/customer/1234
and our grammar is:
<grammar>res:/customer/ <group name="customerId"> <regex type="number" /> </group> </grammar>
then this declarative request:
<request> <identifier>active:groovy</identifier> <argument name="customerId" method="as-string">arg:customerId</argument> <argument name="operator">retrieveCustomerDetails.gy</argument> </request>
will parse the string "1234" from the incoming request and add it as a pass-by-value argument on the call to groovy.
|
| from-string |
This method is the inverse of as-string and as such it is useful for converting an incoming pass-by-value argument
into a pass-by-reference argument. The argument is treated as an identifier reference and SOURCEd as a string. This
string is then passed-by-reference on the constructed requests identifier. |
tolerant
By default any runtime errors whilst trying to add an argument will cause the declarative request to fail. These errors are usually caused by failing to SOURCE an identifier when method="value" or method="data-uri". Or referencing arguments that don't exist.
By specifying a tolerant attribute with a value of "true" on an argument can cause any errors to be tolerated, e.g.
<argument name="a" method="value" tolerant="true">res:/not-exists</argument>
varargs
The varargs element is used to add any arguments from inbound request the context (context.getThisRequest()) on to the constructed request. It will attempt to add all arguments
that haven't otherwise been specified with explicit argument tags. It will be tolerant of an errors
adding arguments in a similar way to the tolerant attribute on argument tags.
substitution
The string literal identifier used in declarative request argument or identifier may be composed using arguments
obtained from arguments from the incoming request.
For example, this argument uses part of a REST path parsed by a grammar:
<argument name="operand">res:/resource/[[arg:partpath]]/data.txt</argument>
and this example uses the resource name parsed by a grammar:
<identifier>res:/resource/[[arg:resourcename]].txt</identifier>
Primary argument
An argument can be specified to be the primary argument of a request
(for a TRANSREPT or SINK request) by using the reserved argument name
"primary".
When an identifier is used with the primary argument, its representation
is retrieved with a separate request using the SOURCE verb
and the returned representation is then used as a pass-by-value argument:
<argument name="primary">res:/resource/data.txt</argument>
literals
An arguments value maybe a literal. This is specified inline and when processed
the literal value is passed-by-value with the request. Optionally the method="data-uri"
attribute may be specified with a literal argument.
<argument name="operand">
<literal type="string">abc</literal>
</argument>
In addition to string , all the Java primitive types plus others are supported by the declarative request:
| Type | Description |
| xml | In-line XML document fragment (DOM is generated) |
| hds | In-line HDS document fragment |
| string | String object set to the specified value |
| boolean | Boolean object set to the specified value |
| char | Character object set to the specified value |
| integer | Integer object set to the specified value |
| byte | Byte object set to the specified value |
| long | Long object set to the specified value |
| float | Float object set to the specified value |
| double | Double object set to the specified value |
| Java class | Creates an instance of the specified class with optional constructor arguments declared by nested literals |
XML literals can be specified, they are created as a DOM representation:
<argument name="operand">
<literal type="xml">
<abc>def</abc>
</literal>
</argument>
HDS literals with one or more root nodes can be specified:
<argument name="operand">
<literal type="hds">
<abc />
<def />
</literal>
</argument>
If the type is not one of the above specified values the type is assumed to be the class of a representation and
an instance of this representation will be constructed. Argument to the constructed representation may be
specified with additional nested literals. Construction arguments are passed to the constructor in the order
they are declared and they must match a valid public constructor for that representations class.
<argument name="operand">
<literal type="java.net.URI">
<literal type="string">http://www.1060.org/</literal>
</literal>
</argument>
The standard request syntax is used by the
mapper overlay,
pluggable overlay,
XRL,
XUnit
and other technologies.