5.269 Exposing Web Services

Any number of methods may be exposed as public, custom web services by satisfying several criteria:

Parameters and request body

The Map argument will contain all parameters passed into the web service by the client. See Accessing Plugin Web Services for additional details.

Parameters may be passed into the web service call as normal URL parameters such as ?param=value&param2=value2, as key-value pairs in the POST body of a request, or as JSON in the body.

For the first two cases, the parameters will be available on the Map argument passed into the web service call as key value pairs matching those of the request. Note that in these cases all keys and values will be interpreted as strings. However, the parameters object has several helper methods to convert from Strings to simple types, such as Booleans, integers, doubles, floats, and lists. If the value is not a valid simple type, null is returned.

Finally, note that the client may optionally include an objectId as the last part of the URL. When this is done, the id field will be set to this value in the Map argument to the web service.

GET <webServiceUrl>?key=value&key2=true&key3=5&list=1&list=2

def serviceMethod(Map params) {
	assert params.key=="value"
	assert params.key2=="true"
	assert params.bool('key2')==true
	assert params.key3=="5"
	assert params.int('key3')==5
	assert params.list('list')==[1, 2]

	// Null is returned if the conversion is invalid
	assert params.int('key')==null
}

When the body possesses JSON, the parsed JSON object or array will be available within a parameter called body in the Map argument. In this scenario, the types of the values are preserved by the JSON format.

POST <webServiceUrl> with JSON body of
{"key":"value","key2":true,"key3":5}

def serviceMethod(Map params) {
	assert params.body.key=="value"
	assert params.body.key2==true
	assert params.body.key3==5
}

Unsecured web services

There are times when it is desirable to create a plugin with a publicly available web service that does not require a valid application account in order to access it (for details, see Access Control). In these cases, the Unsecured annotation may be used on the plugin web service method. No authentication will be performed on Unsecured web services. An example of using the annotation is given below.

Sample unsecured custom web service
------------------------------------

@Unsecured
def retrievePublicData(Map params) {
	return [data:["data item 1", "data item 2"]]
}

Be cautious in using this annotation as it may potentially present a security risk if sensitive data is returned from the web service.

Returning errors

In order to signify an error occurred or invalid data was provided, the WebServiceException class may be thrown from any custom web service. This exception contains constructors and fields for a list of messages and a HTTP response code. For example, suppose that the user provided inadequate information. The web service could use the following code to notify the user and prompt them to take action with custom messages.

def service(Map params) {
	// Handle invalid input
	if (!params.int('a'))
		throw new WebServiceException("Invalid parameter 'a' specified, please specify an integer!", 400)
	// Use params.a correctly …
}

For the example above, a 400 response code (bad request) would be returned with a response body as follows:

{
  "messages":[
	"Invalid parameter 'a' specified, please specify an integer!"
  ]
}

If any other exception is thrown from a web service (ie Exception, IllegalArgumentException, etc.), a 500 response code will be returned with the following response body:

{
  "messages":[
	"A problem occurred while processing the request",
	"Message provided in the exception constructor"
  ]
}

See Responses and Return Codes for more information on error formats in MWS.

Accessing the HTTP Request Method

The HTTP method used for the request is available from the Map parameters argument. The key used to access it is stored as a static field in PluginConstants called WEB_SERVICES_METHOD. The value is a string which can be GET, POST, PUT, or DELETE. The following example demonstrates how this could be used with the WebServiceException to create a REST API with a plugin.

def serviceMethod(Map params) {
	// Check to make sure that this request used the HTTP GET method
	// Throw a 405 error (method not supported) if not
	if (params[PluginConstants.WEB_SERVICES_METHOD]!="GET")
		throw new WebServiceException("Method is not supported", 405)
}

Related Topics 

© 2016 Adaptive Computing