(Quick Reference)

Hooks

This page gives specific examples and reference for implementing hooks in MWS. For more information and a description of hooks, see the hooks section in the user guide.

Available Hooks

The following table lists the available hooks for each resource with their associated HTTP method and description.

NameHTTP MethodDescription
beforeListGETRuns before an API call that lists resources. ex: GET /rest/jobs
afterListGETRuns after an API call that lists resources.
beforeShowGETRuns before an API call that returns a single resource. ex: GET /rest/jobs/job.1
afterShowGETRuns after an API call that returns a single resource.
beforeSavePOSTRuns before an API call that saves a new resource. ex: POST /rest/jobs
afterSavePOSTRuns after an API call that returns a single resource.
beforeUpdatePUTRuns before an API call that returns a single resource. ex: PUT /rest/jobs/job.1
afterUpdatePUTRuns after an API call that returns a single resource.
beforeDeleteDELETERuns before an API call that returns a single resource. ex: DELETE /rest/jobs/job.1
afterDeleteDELETERuns after an API call that returns a single resource.

If a resource does not support a certain operation, any hooks for that operation will simply be ignored, such as beforeSave and afterSave hooks for the Node resource, where saving is not supported.

Available Properties

The following table lists the properties, objects, and methods available in all hooks. Note that although it is possible to directly call the render* methods in the after hooks, it is not recommended. Please see the user guide for more information.

NameTypeDescription
paramsMapContains all URL parameters as well as the body of the request as parsed JSON.
requestHttpServletRequestContains properties of the HTTP request.
responseHttpServletResponseContains properties of the HTTP response which can be modified directly.
sessionHttpSessionContains the session parameters which can be modified directly.
flashMapTemporary storage that stores objects within the session for the next request only.
controllerNameStringThe name of the controller responding to the request. Only available in before hooks.
actionNameStringThe name of the action to be run on the controller. Only available in before hooks.
apiVersionStringThe API version for the current request (i.e. 1 for 7.0 and 7.1, 2 for 7.2).

The parsed JSON may be accessed in before hooks as a simple groovy Map with params[controllerName].

In addition, several methods are available to the hooks. These are described in the following sections.

Redirect

The redirect method may be used to redirect the request to another API call or an arbitrary URL.

redirect(uri:'/rest/jobs')	// uri is used for internal redirection within MWS
redirect(url:'http://adaptivecomputing.com')	// url is used for external redirection
redirect(uri:'http://adaptivecomputing.com', params:[lang:'en'])	// params may be used for URL parameters

The redirect method will use the GET HTTP method for the resulting redirected request.

See the redirect method's documentation for more information.

Rendering Objects, Lists, or Messages

There are several render* methods available to handle any case where objects or lists are desired to be rendered directly from the hook without continuing to the API call. Three different methods may be used depending on the desired output object type:

Render Object
// Object that should be rendered as JSON
def objectToRender = …
// HTTP response code (bad request)
def responseCode = 400

// Render a simple object renderObject(objectToRender) // Render a simple object with a custom response code renderObject(objectToRender, responseCode)

Render List
// List that should be rendered as JSON
def listToRender = …
// If the totalCount property differs from resultCount, use this value instead
def totalCount = …
// HTTP response code (bad request)
def responseCode = 400

// Render a simple list // Dynamically adds "resultCount" and "totalCount" properties based on the size of the input list renderList(listToRender) // Render a simple list with a custom "totalCount" renderList(listToRender, totalCount) // Render a simple list without changing the "totalCount" but with a custom response code renderList(listToRender, null, responseCode) // Render a simple list with a custom "totalCount" and response code renderList(listToRender, totalCount, responseCode)

Render Message(s)
// Messages
def messageToRender = "Single message"
def messagesListToRender = ["Message 1", "Message 2"]
// HTTP response code (bad request)
def responseCode = 400

// Render messages as an object with a property of "messages" containing a list of the messages passed in renderMessages(messageToRender) renderMessages(messageToRender, responseCode) // Supports either a single String or list of Strings renderMessages(messagesListToRender) renderMessages(messagesListToRender, responseCode)

It is not recommended to call any of these methods from an after hook.

Render

Less commonly used, the render method is also available directly. This may be used to render text directly, change the content-type of the output, and many other functions. See the render method's documentation for more information.

It is not recommended to call this method from an after hook.

Serialize Objects

The serializeObject and serializeList methods may be used to convert a custom object or list respectively into a format usable for returning in the after hooks. Simply pass in the object or list and a serialized version will be returned from the method.

def afterShow = {
	def objectToRender = …
	def serializedObject = serializeObject(objectToRender)
	return serializedObject
}

def afterShow = {
	def listToRender = [...]
	def serializedList = serializeList(listToRender)
	return serializedList
}

Error Handling

Error handling is only available in after hooks by using the following check:

if (!isSuccess()) {
	// Handle error
	return … // False or modified object/list to render
}

Usage Examples

Override an API Call

The following hook would serve to override an entire API call, the list call in this case, and return a messages list containing a single element of "Action is not supported" and a HTTP response code of 405 (Method Not Allowed):

def beforeList = {
	renderMessages("Action is not supported", 405)
	return false
}

To be even more specific and disallow the deletion of virtual machines, the following may be used as the vms.groovy file:

def beforeDelete = {
	renderMessages("Virtual Machine deletion is not allowed", 405)
	return false
}

Add An Additional Property During Job Creation

To add an additional property to a job definition during creation, create a beforeSave hook in the jobs.groovy file as follows:

def beforeSave = {
	// params[controllerName] is equivalent to params["job"] or params.job
	params[controllerName].user = "myuser"
}

This would cause the created job to have a user of myuser.

Redirect Based on URL Parameter

To redirect an API call if a certain URL parameter exists, create a beforeSave hook in the jobs.groovy file as follows:

def beforeSave = {
	if (params.external) {
		redirect(url:'http://example.com/create-job')
		return false;	// Stop API call
	}
}

This would cause an API call of PUT /rest/jobs?external=1 to redirect to GET http://example.com/create-job.

Remove a Property From Getting a Single Job

To remove a property from the output of getting a single job, create an afterShow hook in the jobs.groovy file as follows:

def afterShow = { o ->
	o.discard("group")
	return o
}

This will cause the resulting JSON to be missing the group property of the job resource. Note again that these calls must use the JSONArray and JSONObject classes as mentioned in the user guide.

Filter List Items

To filter the items in a list nodes request based on user provided query parameter in the URL, use the following in the nodes.groovy file. A sample request that would activate the filter is http://localhost/mws/rest/nodes?filter-power=On.

def afterList = { o ->
	// Do not filter if the user did not ask for it
	if (!params['filter-power'])
		return o

// o = {resultCount: x, totalCount: x, results:[...]}

// Using a built-in groovy method findAll to return all // list items that return true from the block def results = o.results.findAll { node -> // Includes the node only if the power equals the user input return params['filter-power'].equalsIgnoreCase(node.power) }

// Sets the results on the return object and updates the counts o.element("results", results) o.element("resultCount", results.size()) return o }

To filter the items in a list nodes request based on values within the list itself, such as variable values, use the following in the nodes.groovy file.

def afterList = { o ->	
	// o = {resultCount: x, totalCount: x, results:[...]}

// Using a built-in groovy method findAll to return all // list items that return true from the block def results = o.results.findAll { node -> // Includes the node only if the variable "included" is set to "true" return node.variables?.included=="true" }

// Sets the results on the return object and updates the counts o.element("results", results) o.element("resultCount", results.size()) return o }