Faria Rehman April 27, 2018
Common Mistakes Developers Make In Their RAML Files
Commonly Observed Mistakes Developers Make When Converting RAML Files on Transformer

RESTful API Modeling Language more commonly known as RAML has been around for quite some time now (more than 4 years). As its name suggests, it is an API Modeling language used by plenty of developers to design their APIs from scratch. It offers features like reusable libraries, traits, etc. that are not yet available in other popular API description formats.

In this blog, I will highlight some of the frequently seen mistakes in RAML files (for both versions 0.8 and 1.0). If you have read my previous blog about the common mistakes developers make in their OpenAPI 3 files, you may notice some similarities which is to do with the fact that these API description formats, although serving their own distinct purposes, have a lot in common.

Trying to Reference Components That Don’t Exist

The biggest portion of the RAML failures associated with developer mistakes are ones in which certain components are referenced but these references fail to get resolved. Common causes are discussed below:

Externally referenced files not provided

RAML allows developers to split their API description file into multiple files and reference the components across these files using the !include tag. Depending on the size of the API, a RAML file is usually split into a large number of files e.g. the main RAML file, schema files, schema JSON example files, etc.

Plenty of developers upload only their main RAML file but do not provide the other referenced files. In general, a ZIP is required or a base URL from which relative files can be loaded. Sometimes even when these are provided, the failures can still occur if there are files referenced that are not present in the uploaded ZIP file or could not be loaded relatively from the URL. Our Transformer tool performs validation of URLs/ZIP files to help indicate any such missing files. Keep an eye out for the warnings when performing your conversion to avoid failures due to missing files.

Incorrect paths/Invalid file names

Some common scenarios observed where developers face conversion failures in such cases is when:

  • The file they are trying to reference (e.g. IAmAFile.raml) exists with a different name (e.g. IAmAFile_Version2.raml).
  • The file exists in a different directory (e.g. Directory1/IAmAFile.raml) to the one in which they are trying to locate the file (e.g. Directory2/IAmAFile.raml).
  • The file path is a URL like http://example.com/files/IAmAFile.raml but the URL is either broken/not publicly accessible.

RAML components (Types, Resource Types, Traits, etc.) referenced but not defined

As discussed previously, RAML processing generally involves plenty of files. Developers bring in files that reference a component (like a type definition, resource type, or a trait) in another file (e.g. a library) but the component is not defined in that file. It is possible that the component exists with a slightly different name or is located in some other file. This issue can occur in a single-file RAML as well.

#%RAML 1.0
title: Hello world
mediaType: application/json
/helloworld:
  post:
    body:
      type: HelloMessage

In the above example, the request body of the POST method references type HelloMessage but this type is not declared anywhere. Since it is not a RAML primitive type, it MUST be declared under the types section as follows:

#%RAML 1.0
title: Hello world
mediaType: application/json
types:
  HelloMessage:
/helloworld:
  post:
    body:
      type: HelloMessage

Similarly, if a library type is referenced the developer needs to ensure that the definition for the type resides in that library.

You can’t reference a RAML type in a JSON Schema

A very interesting mistake noted in RAML 1.0 files was that several developers try referencing RAML types from within a JSON schema definition e.g. in the following example the body schema contains a property input that tries referencing a RAML type HelloMessage(defined using RAML types component).

#%RAML 1.0
title: Hello world
mediaType: application/json
types:
  HelloMessage:
    properties:
      message: string
/helloworld:
  post:
    body:
      type: |
      {
        "$schema": "http://json-schema.org/draft-04/schema",
        "properties": {
          "input": {
            "type": "HelloMessage"
           }
         },
        "type": "object"
       }

This is invalid as a JSON schema definition is completely independent of the RAML specification and any types that need to be used must be defined in the root definitions of the schema itself.

Invalid YAML Means Invalid RAML

RAML uses YAML as its underlying format. So a RAML file has to abide by the rules set by both YAML and RAML specifications. A large number of developers upload files with invalid YAML content. Some of the common causes are discussed below.

Using tab spacing which is not allowed

That is correct. YAML does not allow tabs but a lot of developers still use it for the indentation of their RAML files.

Treating YAML as case-insensitive

YAML is case-sensitive. Developers try referencing types named IAmAType as iamatype which is invalid as they both are different.

Missing space between property key and value

When defining a property, YAML requires that there be a space between the property key and the value. Developers still try and define the property like:

property1:propertyValue

This is invalid as the correct way is:

property1: propertyValue

Improper nesting

Every nested item must be indented with two spaces inside the parent one e.g. a property property2 nested inside property1 must be declared as follows:

property1:
  property2:

This is not followed by most of the developers.

Unescaped strings

A lot of developers forget to escape strings that contain reserved characters e.g. the following is invalid as the description field containing the reserved character : is not escaped properly.

/helloworld:
  post:
    body:
      description: Testing: 123

The description must be escaped using quotes as follows:

/helloworld:
  post:
    body:
      description: 'Testing: 123'

Incorrect Usage of RAML Libraries

RAML introduced its users to libraries in version 1.0. Developers make certain mistakes when applying these libraries.

Declaring library content inline

A library must be defined in a RAML fragment file which is separate from the files that will reference it. The file referencing it (a master RAML file or some other fragment file) must use the 

uses:
  file-type: file-type.raml
 property to specify a name and path to the library as shown below:

 

uses:
  file-type: file-type.raml

However, it is seen that a lot of developers try and define the library inline where otherwise a library path is expected:

uses:
  file-type:
    types:
      File:

This is invalid and likely to cause failures.

Using !include to load the libraries

Since all external files are referenced in RAML by adding the !include tag before the path, it is a common mistake to do the same for when loading external libraries. This is, therefore, invalid:

uses:
  file-type: !include file-type.raml

The !include tag is not applicable for applying libraries. Instead, the library path must be specified directly as follows:

uses:
  file-type: file-type.raml

Composition of Library Namespaces

RAML does not allow the composition of namespaces using . across multiple libraries. Developers try to reference types across multiple libraries (files, file-type) as follows which is invalid:

type: files.file-type.File

Trouble Caused by a Missing Colon ‘:’

So small and insignificant it is and yet, surprisingly, one of the reasons behind so many failures that developers make. When defining response bodies plenty of developers specify it as follows:

responses:
  200:
    body:
      application/json

Do you see the missing colon at the end of application/json? It is what changes the meaning of the whole definition because it implies that the response body is of type application/json i.e. application/json is treated as a string value. Since the types defined in your file will definitely not contain a type named application/json, the file throws an error and fails to convert. To give this value back its original role as a media type/content type name you need to restore the colon as follows:

responses:
  200:
    body:
      application/json:

Now it’s a media type with an empty type declaration which is allowed and won’t cause errors.

Missing/Invalid Required RAML Version Comment Line

Relatively less frequent but common, nevertheless, are the issues that developers face when trying to convert their RAML files that do not start with the YAML comment indicating the RAML version. RAML specifications declares them mandatory for both RAML 0.8 and RAML 1.0.

For RAML 0.8, it is specified as:

#%RAML 0.8

For RAML 1.0, it is specified as:

#%RAML 1.0

These comment lines are important because they help us distinguish your RAML files from any other YAML files. Also, any other versions specified (like 2.03.0) are invalid because the only available versions are 0.8 and 1.0. This is, therefore, incorrect:

#%RAML 3.0

Need Array Parameters? Choose RAML 1.0 not 0.8

The support for array parameters is available for only request/response body definitions through JSON schema specification. For all other cases (query, header, form or URI parameters) the only available types are: stringnumberintegerfiledate and boolean. A lot of developers try to use array type for their query parameters which is not supported and in such cases, it is recommended to use RAML 1.0 which has full support for array parameters.

Incorrect Usage of Primitive Types Available

  • The null type is available as nil in RAML 1.0. A lot of developers still try to use null instead.
  • The primitive date type available in RAML 0.8 is date while RAML 1.0 offers multiple primitive date types: date-onlytime-onlydatetime-onlydatetime. Developers tend to confuse both and try using date in RAML 1.0 and date-only in RAML 0.8.
  • Floating-point numbers are defined by setting type to number and format to float. Developers, however, sometimes try to set type as float directly which is invalid.

Nonconformance to RAML Specification

Failing to follow the RAML specification in any way may result in failures when using any tool. A property stated to be an object but declared as an array can cause failures. Common mistakes that fall in this category are listed below:

  • The specification for RAML 0.8 states that the protocols property MUST be an array of strings. A lot of developers still declare it as a simple string. Similarly, the specification for RAML 1.0 declares property scopes as a list of strings and yet plenty of developers declare it as a simple string.
  • RAML 0.8 allows named parameters to have multiple types that can be specified as follows:
file:
  - type: string
  - type: file

Developers sometimes make the mistake of declaring property type as an array instead which is invalid e.g.

file:
  type:
    - string
    - file

Conclusion

RAML is a format that comes bundled with plenty of features and with a large feature set comes more complexity. It is very important that the specification documents are detailed, try to cover all cases, and are free from ambiguities. Given the number of mistakes seen above, perhaps there is a need to improve the specifications currently available or a need to increase the number of tooling available for RAML to facilitate users to validate their files and fix potential issues.

Have RAML files of your own that you want to convert? Please head over to Transformer and start converting for free!

Thanks to Adeel Ali.