ICAT RESTful interface

Introduction

ICAT provides both a SOAP and a RESTful web service to communicate with the core ICAT code which makes calls to a relational DBMS. This document describes the RESTful interface but assumes some knowledge of ICAT as explained in the ICAT Java Client manual.

Notation

For each call the Java annotations in the server code are shown as these indicate precisely what is expected. @POST, @PUT, @DELETE and @GET denote the method and @Path shows the relative url path. They are all relative to "icat". The @Consumes and @Produces shows the expected format of the body of the message.

Error handling

In the case of an error from the ICAT code the returned json will be of the form: {"code":"BAD_PARAMETER", "message":"password too short", "offset":"0"} where the offset (which shows the offset to the entity which caused the error) will be omitted when it is not relevant. The status code will correspond to the type of the ICAT exception as shown by the code value. In the case of any other error, the code field will always be "INTERNAL", the offset will always be omitted and the status code will be 500 ("Internal Server Error"). Clients should always check the status code and if status/100 is not 2 then an error has occured.

Testing

The @GET calls can be tried on a web browser and curl can be used to make any of the calls. For example a url of the form: https://example.com:443/icat/version will return some json such as {"version":"4.4.0"}

Structure

This document is divided into sections covering

Session management

login

To obtain a new session.

@POST
@Path("session")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)

The form parameter is:

jsonString
which takes the form {"plugin":"db", "credentials[{"username":"root"}, {"password":"guess"}]}
The returned json is of the form {"sessionId","0d9a3706-80d4-4d29-9ff3-4d65d4308a24"}

getSession

To obtain information about a session.

@GET
@Path("session/{sessionId}")
@Produces(MediaType.APPLICATION_JSON)

The path parameter is:

sessionId
which takes the form 0d9a3706-80d4-4d29-9ff3-4d65d4308a24
The returned json is of the form {"userName":"db/root","remainingMinutes":117.87021666666666}

refresh

To refresh a session.

@PUT
@Path("session/{sessionId}")

The path parameter is:

sessionId
which takes the form 0d9a3706-80d4-4d29-9ff3-4d65d4308a24

logout

To logout - i.e. delete a session.

@DELETE
@Path("session/{sessionId}")

The path parameter is:

sessionId
which takes the form 0d9a3706-80d4-4d29-9ff3-4d65d4308a24

Entity management

create

To create one or more entities in ICAT

@POST
@Path("entityManager")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON) public String

The form parameters are:

sessionId
which takes the form 0d9a3706-80d4-4d29-9ff3-4d65d4308a24
entities
which takes the form [{"InvestigationType":{"facility":{"id":12042},"name":"ztype"}},{"Facility":{"name":"another fred"}}] . It is a list of objects where each object has a name which is the type of the entity and a value which is an object with name value pairs where these names are the names of the attributes and the values are either simple or they may be objects themselves. In this case two entities are being created an InvestigationType and a Facility with a name of "another fred". The InvestigationType being created will reference an existing facility with an id of 12042 and will have a name of "ztype". For references to existing objects only the "id" value need be set otherwise if child objects are to be created at the same time then the "id" should not be set but the other desired attributes should.
The returned json is of the form [125, 126] and is a list of the ids of the objects created.

search

To search for information in ICAT. This includes the functionality of both search and get calls in the SOAP web service.

@GET @Produces(MediaType.APPLICATION_JSON)
@Path("entityManager")

The query parameters are:

sessionId
which takes the form 0d9a3706-80d4-4d29-9ff3-4d65d4308a24
query
which takes the form SELECT f FROM Facility f
id
which takes the form 732 and is used when the functionality of get is required in which case the query must be as described in the ICAT Java Client manual.
The returned json is of the form [{"Facility":{"id":126, "name":"another fred"}}] and is a list of the objects returned and takes the same form as the data passed in for create. If an id value is specified then only one object can be returned so the outer square brackets are omitted.

Import and Export

The import and export calls make use of a special format to represent ICAT data efficiently. The file may contain line starting with a # sign. The first non-comment line contains the version number of the file format with major and minor parts. Each entity type is preceded by a blank line line followed by a one line entity descriptor and then a line for each entity of that type. For example:

 #  Version of file format
 1.0
 
 Facility ( name:0, daysUntilRelease:1, createId:2, createTime:3)
 "Test port facility", 90, "Zorro", 1920-05-16T16:58:26.12Z
 
 InvestigationType (facility(name:0), name:1)
 "Test port facility", "atype"
 "Test port facility", "btype"
 
 Investigation(facility(name:0), name:1, visitId:2, type(facility(name:0), name:3), title:4)
 "Test port facility", "expt1", "one", "atype", "a title"

The entity descriptor starts with the name of the entity type followed by a comma separated list attribute of field names held inside parentheses. It is not necessary to include those which you don't wish to set as any that are not present and are allowed to be null will be set to null when importing. So we see that this file will create a Facility with fields: name, daysUntilRelease, createId and createTime. Following the field name is a colon and an integer showing the offset to the data field in each of the next set of rows. So a facility will be created with a name of "Test port facility" and with 90 daysUntilRelease. All strings must be enclosed in double quotes and to represent a double quote within the string then two double quotes must be used. True, false and null literals are not case sensitive. The last two fields of the facility are createId and createTime. If you specify that you want all attributes and you are a "root user" then the values of createId and createTime will be respected otherwise the current time is used and the id is that of the user doing the import. Timestamps literals follow ISO 8601 and support fractional seconds and time zones. If the time zone is omitted it is interpreted as local time.

Now consider the InvestigationType for which we need to specify the facility to which it belongs and its name. The facility cannot be descibed by its id because we don't know what it is. So instead we list in parentheses the field names that define it. So name:0 is the name of the facility and name:1 is the name of the InvestigationType.

The next line shows the convenience of this syntax. The investigation has a facility (identified by its name:0) and the name:1 of the investigation and the visitId but it also has a type which is identified a facility (identified by its name:0) and by the name:3 of the type. Finally it has a title:4 field. Note that name:0 is used twice as in this case the inverstigation belongs to the same facility as its type. This works fine as long as we deal with entity types which have key fields. This is shown in the next snippet from an import file:

 DataCollection(?:0)
 "a"
 "b"
 "c"
 
 DataCollectionDatafile(datafile(dataset(investigation(facility(name:0), name:1, visitId:2), name:3), name:4), dataCollection(?:5))
 "Test port facility", "expt1", "one", "ds1", "df1",  "a"
 "Test port facility", "expt1", "one", "ds1", "df2",  "b"
 
 Job(application(facility(name:0), name:1, version:2), inputDataCollection(?:3), outputDataCollection(?:4))
 "Test port facility", "aprog", "1.2.3", "a", "b"
Here we have the DataCollection which we imagine to be indentified by the anonymous variable "?". This section of the file will create three DataCollection entries which we shall remember for the duration of the import process as "a", "b" and "c". DataCollectionDatafiles are then associated with DataCollections "a" and "b" and a job is created with one DataCollection as input and one as output. When performing export the same format is used however some values will be repeated - for example the facility name will appear many times in most rows.

import

Import data into ICAT

@Path("port")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)

The multipart form data starts with a form parameter with a ContentType of TEXT_PLAIN and a name of "json" and is followed by the data to be imported with a ContentType of APPLICATION_OCTET_STREAM.

The json takes the form: "{sessionId", "0d9a3706-80d4-4d29-9ff3-4d65d4308a24", "duplicate", "THROW", "attributes", "USER"} . The value "duplicate" if not specified defaults to "THROW". It is not case sensitive and it defines the action to be taken if a duplicate is found:

THROW
throw an exception
IGNORE
go to the next row
CHECK
check that new data matches the old - and throw exception if it does not.
OVERWRITE
replace old data with new
The value "attributes" if not specified defaults to "USER". It is not case sensitive and it defines which attributes to consider:
USER
values for modId, createId, modDate and createDate provided in the input will be ignored.
ALL
all field values specified will be respected. This option is only available to those specified in the rootUserNames in the icat.properties file.

export

Export data from ICAT

@Path("port")
@GET @Path("port")
@Produces(MediaType.TEXT_PLAIN)

The query parameter is:

json
which takes the form {"sessionId":"0d9a3706-80d4-4d29-9ff3-4d65d4308a24","query":"Facility", , "attributes":"ALL" where query if specified is a normal ICAT query which may have an INCLUDE clause. This is used to define the metadata to export. If not present then the whole ICAT will be exported.

The value "attributes" if not specified defaults to "USER". It is not case sensitive and it defines which attributes to consider:

USER
values for modId, createId, modDate and createDate will not appear in the output.
ALL
all field values will be output.

The response is the requested export data.

Miscellaneous

version

Return the version of the ICAT server

@Path("version")
@GET @Produces(MediaType.APPLICATION_JSON)

The returned json is of the form: {"version":"4.4.0"}