eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Introduction

In our first two articles on RAML – the RESTful API Modeling Language – we introduced some basic syntax, including the use of data types and JSON schema, and we showed how to simplify a RAML definition by extracting common patterns into resource types and traits.

In this article, we show how you can break your RAML API definition into modules by making use of includes, libraries, overlays, and extensions.

2. Our API

For the purpose of this article, we shall focus on the portion of our API involving the entity type called Foo.

Here are the resources making up our API:

  • GET /api/v1/foos
  • POST /api/v1/foos
  • GET /api/v1/foos/{fooId}
  • PUT /api/v1/foos/{fooId}
  • DELETE /api/v1/foos/{fooId}

3. Includes

The purpose of an include is to modularize a complex property value in a RAML definition by placing the property value in an external file.

Our first article touched briefly on the use of includes when we were specifying data types and examples whose properties were being repeated inline throughout the API.

3.1. General Usage and Syntax

The !include tag takes a single argument: the location of the external file containing the property value. This location may be an absolute URL, a path relative to the root RAML file, or a path relative to the including file.

A location starting with a forward slash (/) indicates a path relative to the location of the root RAML file, and a location beginning without a slash is interpreted to be relative to the location of the including file.

The logical corollary to the latter is that an included file may itself contain other !include directives.

Here is an example showing all three uses of the !include tag:

#%RAML 1.0
title: Baeldung Foo REST Services API
...
types: !include /types/allDataTypes.raml
resourceTypes: !include allResourceTypes.raml
traits: !include http://foo.com/docs/allTraits.raml

3.2. Typed Fragments

Rather than placing all the types, resource types or traits in their own respective include files, you can also use special types of includes known as typed fragments to break each of these constructs into multiple include files, specifying a different file for each type, resource type or trait.

You can also use typed fragments to define user documentation items, named examples, annotations, libraries, overlays, and extensions. We will cover the use of overlays and extensions later in the article.

Although it is not required, the first line of an include file that is a typed fragment may be a RAML fragment identifier of the following format:

#%RAML 1.0 <fragment-type>

For example, the first line of a typed fragment file for a trait would be:

#%RAML 1.0 Trait

If a fragment identifier is used, then the contents of the file MUST contain only valid RAML for the type of fragment being specified.

Let’s look first at a portion of the traits section of our API:

traits:
  - hasRequestItem:
      body:
        application/json:
          type: <<typeName>>
  - hasResponseItem:
      responses:
          200:
            body:
              application/json:
                type: <<typeName>>
                example: !include examples/<<typeName>>.json

In order to modularize this section using typed fragments, we first rewrite the traits section as follows:

traits:
  - hasRequestItem: !include traits/hasRequestItem.raml
  - hasResponseItem: !include traits/hasResponseItem.raml

We would then write the typed fragment file hasRequestItem.raml:

#%RAML 1.0 Trait
body:
  application/json:
    type: <<typeName>>

The typed fragment file hasResponseItem.raml would look like this:

#%RAML 1.0 Trait
responses:
    200:
      body:
        application/json:
          type: <<typeName>>
          example: !include /examples/<<typeName>>.json

4. Libraries

RAML libraries may be used to modularize any number and combination of data types, security schemes, resource types, traits, and annotations.

4.1. Defining a Library

Although usually defined in an external file, which is then referenced as an include, a library may also be defined inline. A library contained in an external file can reference other libraries as well.

Unlike a regular include or typed fragment, a library contained in an external file must declare the top-level element names that are being defined.

Let’s rewrite our traits section as a library file:

#%RAML 1.0 Library
# This is the file /libraries/traits.raml
usage: This library defines some basic traits
traits:
  hasRequestItem:
    usage: Use this trait for resources whose request body is a single item
    body:
      application/json:
        type: <<typeName>>
  hasResponseItem:
    usage: Use this trait for resources whose response body is a single item
    responses:
        200:
          body:
            application/json:
              type: <<typeName>>
              example: !include /examples/<<typeName>>.json

4.2. Applying a Library

Libraries are applied via the top-level uses property, the value of which is one or more objects whose property names are the library names and whose property values make up the contents of the libraries.

Once we have created the libraries for our security schemes, data types, resource types, and traits, we can apply the libraries to the root RAML file:

#%RAML 1.0
title: Baeldung Foo REST Services API
uses:
  mySecuritySchemes: !include libraries/security.raml
  myDataTypes: !include libraries/dataTypes.raml
  myResourceTypes: !include libraries/resourceTypes.raml
  myTraits: !include libraries/traits.raml

4.3. Referencing a Library

A library is referenced by concatenating the library name, a dot (.), and the name of the element (e.g. data type, resource type, trait, etc) being referenced.

You may recall from our previous article how we refactored our resource types using the traits that we had defined. The following example shows how to rewrite our “item” resource type as a library, how to include the traits library file (shown above) within the new library, and how to reference the traits by prefixing the trait names with their library name qualifier (“myTraits“):

#%RAML 1.0 Library
# This is the file /libraries/resourceTypes.raml
usage: This library defines the resource types for the API
uses:
  myTraits: !include traits.raml
resourceTypes:
  item:
    usage: Use this resourceType to represent any single item
    description: A single <<typeName>>
    get:
      description: Get a <<typeName>> by <<resourcePathName>>
      is: [ myTraits.hasResponseItem, myTraits.hasNotFound ]
    put:
      description: Update a <<typeName>> by <<resourcePathName>>
      is: [ myTraits.hasRequestItem, myTraits.hasResponseItem, myTraits.hasNotFound ]
    delete:
      description: Delete a <<typeName>> by <<resourcePathName>>
      is: [ myTraits.hasNotFound ]
      responses:
        204:

5. Overlays and Extensions

Overlays and extensions are modules defined in external files that are used to extend an API. An overlay is used to extend non-behavioral aspects of an API, such as descriptions, usage directions, and user documentation items, whereas an extension is used to extend or override behavioral aspects of the API.

Unlike includes, which are referenced by other RAML files to be applied as if they were being coded inline, all overlay and extension files must contain a reference (via the top-level masterRef property) to its master file, which can be either a valid RAML API definition or another overlay or extension file, to which they are to be applied.

5.1. Definition

The first line of an overlay or extension file must be formatted as follows:

RAML 1.0 Overlay

And the first line of an overlay file must be formatted similarly:

RAML 1.0 Extension

5.2. Usage Constraints

When using a set of overlays and/or extensions, all of them must refer to the same master RAML file. In addition, RAML processing tools usually expect the root RAML file and all overlay and extension files to have a common file extension (e.g. “.raml”).

5.3. Use Cases for Overlays

The motivation behind overlays is to provide a mechanism for separating interface from implementation, thus allowing the more human-oriented parts of a RAML definition to change or grow more frequently, while the core behavioral aspects of the API remain stable.

A common use case for overlays is to provide user documentation and other descriptive elements in multiple languages. Let’s rewrite the title of our API and add some user documentation items:

#%RAML 1.0
title: API for REST Services used in the RAML tutorials on Baeldung.com
documentation:
  - title: Overview
  - content: |
      This document defines the interface for the REST services
      used in the popular RAML Tutorial series at Baeldung.com.
  - title: Copyright
  - content: Copyright 2016 by Baeldung.com. All rights reserved.

Here is how we would define a Spanish language overlay for this section:

#%RAML 1.0 Overlay
# File located at (archivo situado en):
# /overlays/es_ES/documentationItems.raml
masterRef: /api.raml
usage: |
  To provide user documentation and other descriptive text in Spanish
  (Para proporcionar la documentación del usuario y otro texto descriptivo
  en español)
title: |
  API para servicios REST utilizados en los tutoriales RAML
  en Baeldung.com
documentation:
  - title: Descripción general
  - content: |
      Este documento define la interfaz para los servicios REST
      utilizados en la popular serie de RAML Tutorial en Baeldung.com.
  - title: Derechos de autor
  - content: |
      Derechos de autor 2016 por Baeldung.com.
      Todos los derechos reservados.

Another common use case for overlays is to externalize annotation metadata, which essentially are a way of adding non-standard constructs to an API in order to provide hooks for RAML processors such as testing and monitoring tools.

5.4. Use Cases for Extensions

As you may infer from the name, extensions are used to extend an API by adding new behaviors and/or modifying existing behaviors of an API. An analogy from the object-oriented programming world would be a subclass extending a superclass, where the subclass can add new methods and/or override existing methods. An extension may also extend an API’s non-functional aspects.

An extension might be used, for example, to define additional resources that are exposed only to a select set of users, such as administrators or users having been assigned a particular role. An extension could also be used to add features for a newer version of an API.

Below is an extension that overrides the version of our API and adds resources that were unavailable in the previous version:

#%RAML 1.0 Extension
# File located at:
# /extensions/en_US/additionalResources.raml
masterRef: /api.raml
usage: This extension defines additional resources for version 2 of the API.
version: v2
/foos:
  /bar/{barId}:
    get:
      description: |
        Get the foo that is related to the bar having barId = {barId}
      typeName: Foo
      queryParameters:
        barId?: integer
        typeName: Foo
        is: [ hasResponseItem ]

And here is a Spanish-language overlay for that extension:

#%RAML 1.0 Overlay
# Archivo situado en:
# /overlays/es_ES/additionalResources.raml
masterRef: /api.raml
usage: |
  Se trata de un español demasiado que describe los recursos adicionales
  para la versión 2 del API.
version: v2
/foos:
  /bar/{barId}:
    get:
      description: |
        Obtener el foo que se relaciona con el bar tomando barId = {barId}

It is worth noting here that although we used an overlay for the Spanish-language overrides in this example because it does not modify any behaviors of the API, we could just as easily have defined this module to be an extension. And it may be more appropriately defined as an extension, given that its purpose is to override properties found in the English-language extension above it.

6. Conclusion

In this tutorial, we have introduced several techniques to make a RAML API definition more modular by separating common constructs into external files.

First, we showed how the include feature in RAML can be used to refactor individual, complex property values into reusable external file modules known as typed fragments. Next, we demonstrated a way of using the include feature to externalize certain sets of elements into reusable libraries. Finally, we extended some behavioral and non-behavioral aspects of an API through the use of overlays and extensions.

To learn even more about RAML modularization techniques, please visit the RAML 1.0 spec.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Next »
Define Custom RAML Properties Using Annotations
« Previous
Eliminate Redundancies in RAML with Resource Types and Traits
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LS – NPI (cat=REST)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)