Since RAML was introduced to the world in its infant version 0.8 state, it has gained huge interest in the community. There has been adoption by large companies like Oracle and Amazon, and support for it now exists in popular tools like SoapUI, PostMan, Restlet, and RAMLfications.
Today we are excited to announce the release of RAML 1.0 GA (release notes).
The new feature set is extremely powerful and makes the case for RAML 1.0 really compelling. Modularization now comes in the shape of libraries which can be centralized outside of your API definition and thus reused across projects. Data type declarations are now written in YAML and are independent of the media types in use. Examples can now form part of the data type definitions, thus allowing you to keep your resource and operation declarations concise. Annotations give you tremendous new possibilities of client and server side processing of the API definition. They also represent a means to document your API in a concise and consistent manner. Overlays and extensions are modules which allow you to revisit your API definition in a separate document in order to modify and / or enhance either the resources and operations or merely information about them.
In the next section, we will introduce all the different new features in the context of an example.
We have a fictitious e-commerce retail company: Álainn Cosmetics who builds a Mobile Shopping API that we focus our attention on in the next sections. Take a glance at the main definition.
Note the #%RAML 1.0 header.
We make use of the powerful module usage feature with the uses node. This allows us to make reference to (local or remote) modules and apply namespaces to their usage in the document. Here we import traits and security definitions, which you are already familiar with. However, now we must alias the references with the keys tra and sec. You choose your alias and use it to qualify the reference throughout the document.
Note how we prefix the reference to the searchable and imageable traits with tra. This helps avoid name conflicts as you could use multiple modules from various sources each with similarly named nodes. Reuse of type definitions, examples, resource types and traits are possible with modules.
Here, the whole traits section is defined in a separate Library. Note the #%RAML 1.0 Library declaration at the top. Remember, these must now be referenced using the namespace prefixes defined in the document which uses the Library. RAML 1.0 is completely modularized. Modules can use other modules.
RAML now allows us to declare all body types in YAML format. We can declare custom types which are objects, arrays or scalars. Properties are like the fields in a Java class. They describe the members of custom object types that we define. Object types can extend other object types and multiple inheritance is allowed. Every declaration you make whether it be of type object, array or scalar can be constrained with facets. The minLength facet, for example, can restrict possible values of a string scalar to only those whose length matches minLength.
The GetItemsResponse type is an object with two properties: links and collection. The type of links is ResourceLink, an array of the elsewhere defined ResourceLink type. The type of collection is declared inline. It is an object with the properties size and items. The type of the items property is an array of Item.
Before we look at the ResourceLink and Item definitions, watch how we use parameterization to resolve the reference to GetItemsResponse. The resource type of /items is read-only-collection. We can use convention over configuration to determine the types of responses from each operation defined in the resource types.
Because this extends base, the type of the response for the get operation is resolved dynamically by use of the <<resourcePathName | !uppercamelcase>> function. This means we have a consistent and concise way to reference each of the data types we have defined.
Returning to the definitions of ResourceLink and Item, watch how we elaborate on property definitions with the use of facets underneath them.
Note how optionality of properties is stated with the ? qualifier at the end of the property name. Using the default facet, we can supply default values for optional properties. The possible values of a string property can be restricted with the enum facet. Type expressions allow us to combine types. The type of the links property in Item is defined as (ResourceLink | ImageLink). This means that links is an array of either ResourceLink or ImageLink.
We can now centralize all examples and couple them with their corresponding type definitions. Regardless of the media type in use, we define the examples in the same YAML format as the types.
Note how arrays are declared using a hyphen - . When the items in an array are objects, the hyphen is followed by the first property declaration with subsequent ones declared immediately below. The benefit of the approach we have adopted thus far (the combination of the dynamic resolution of types in resource type definitions based on a simple naming convention) is that we can have a very concise definition of the main part of the API. We can see all the resources and operations at a glance!
RAML 1.0 allows us to enhance the vocabulary of RAML itself with annotations. We exploit this feature here to inform the developers of the iPhone app about where to find hypermedia in the JSON responses we send back, and how their software should process them. Annotation types are defined in the same way as data types. The usage of annotations throughout the document is constrained by the values of the allowedTargets facet.
Here we constrain the usage of the hypermedia-plan annotation so that it can only appear globally for the entire API or underneath a resource declaration. It is possible to declare annotations of a particular type like hypermedia-plan by surrounding the declaration in parentheses ().
Overlays and Extensions
We now have a well-defined API with resources and operations, the types of their requests and responses as well as examples. We have the option to lace the declarations of the operations on the resources with the (hypermedia-control) annotation. Instead, we'll exploit a feature in RAML 1.0 that allows us to revisit all or part of the document and modify or enhance the definitions. This is done by extending the main definition with either an Overlay or an Extension. Overlays change only the non-behavioral aspects of the API definition, like documentation and descriptions. Extensions add to the behavior or an API definition. We can define more resources or add operations to existing ones with an extension.
We exploit the Overlay module as a clean way of applying our hypermedia annotations to the API. Note how we are free to choose which nodes we want to extend. We are not obliged to revisit and redefine every node in the base definition.
We have given you a glance at the enhanced power of RAML 1.0. We encourage you to take a look at some of the capabilities in depth by reading through the spec. You can see the console for the RAML we defined in this blog here and the full RAML in our new raml-examples repository.