Internal Developer Platforms – Part 12: Backstage Entities and OpenAPI Example

Table of Contents:

Tags:

In the last blog post, we discussed the various entity types within Backstage’s Software Catalog. As the plain theory is sometimes quite abstract, we will continue with an concrete example and show how to publish the API of a simple Java Spring REST service in Backstage and publish its API in the OpenAPI specification format within Backstage.

The sample app

As we are using Spring Boot, we can simply create a simple application with Spring Initializr. We open the page https://start.spring.io and can provide the input as shown in the screenshot below:

The image shows the Spring Initializr web interface configured to create a new Spring Boot project. The project is set to use Maven for build automation, Java as the programming language, and Spring Boot version 3.2.5. Project metadata includes group ID 'cloud.sclabs.backstage', artifact ID 'sample-app', name 'sample-app', description 'Demo project for Spring Boot', and the package name 'cloud.sclabs.backstage.sample-app'. The project packaging is set to 'Jar' and the Java version is 17. Dependencies include 'Spring Web' for building web applications using Spring MVC.

Once unpacked we can write some simple logic for the RestController.

package cloud.sclabs.backstage.sampleapp;

import java.util.List;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
class EmployeeController {


  @GetMapping("/employees")
  List<String> all() {
    …;
  }
  
  @GetMapping("/employees/{id}")
  Employee one(@PathVariable Long id) {
    
    …
  }

  @PutMapping("/employees/{id}")
  Employee replaceEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {
    
    …
  }

  @DeleteMapping("/employees/{id}")
  void deleteEmployee(@PathVariable Long id) {
    …
  }
}

In order to create the OPEN API documentation, we simply add the following dependency on the classpath:

<dependency>
<groupId>org.springdoc</groupId>
       <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
       <version>2.5.0</version>
</dependency>

Once we have built and started our application (./mvnw clean spring-boot:run) , we can see the documentation when opening the following URL: http://localhost:8080/swagger-ui/index.html

Backstage Entities

Now it is time to write some YAML for the Backstage entities. We create a backstage folder within the repository and add the following directories and files (mkdocs will be explained within the next blog post):

The image shows a directory structure in a terminal for a project related to Spotify Backstage. The structure includes several YAML files and directories. At the root level, there are 'all-apis.yaml', 'all-components.yaml', and 'all.yaml'. There are also 'apis' and 'components' directories, each containing a respective YAML file: 'employees-api.yaml' in 'apis' and 'employees-component.yaml' in 'components'. Additionally, there is a 'docs' directory with Markdown files: 'architecture.md', 'employees.md', 'index.md', 'sample.md', and 'structure.md'. The root directory also contains 'mkdocs.yaml'.

Let’s take a look into the yaml files. Our entry point is the all.yaml:

apiVersion: backstage.io/v1alpha1
kind: Location
metadata:
  name: backstage-sample-app
  description: A collection of all Backstage entities
spec:
  targets:
    - ./all-apis.yaml
    - ./all-components.yaml

---
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
  name: backstage-sample-app
  annotations:
    backstage.io/techdocs-ref: dir:.
    github.com/project-slug: gsoeldner/backstage-sample-app
spec:
  owner: user:default/guido.soeldner

Within the YAML, we define a location and load the all-apis.yaml and the all-components.yaml.

The location entity all-apis.yaml covers the different APIs – in our case just simple one:

apiVersion: backstage.io/v1alpha1
kind: Location
metadata:
  name: event-sourcing-poc-apis
  description: A collection of all Backstage event-sourcing-poc APIs
spec:
  targets:
    - ./apis/employees-api.yaml

Finally, we have the employees-api.yaml:

apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: employees-api
  description: The employees API
  tags:
    - employees
    - query
    - rest
  links:
    - url: https://github.com/gsoeldner-sc/backstage-sample-app
      title: Server Root
      icon: github
spec:
  type: openapi
  lifecycle: experimental
  owner: user:default/guido.soeldner
  definition: |
	SPEC from Spring APP

The last line covers the Spring App OpenAI spec. The most easy way is to retrieve the API as JSON (http://localhost:8080/v3/api-docs) and replace the line in the sample.

Of course we also need to define the components:

apiVersion: backstage.io/v1alpha1
kind: Location
metadata:
  name: event-sourcing-poc-components
  description: A collection of all Backstage event-sourcing-poc components
spec:
  targets:
    - ./components/employees-component.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: employees-component
  description: command side of order aggregate
  annotations:
    backstage.io/source-location: url:https://github.com/gsoeldner-sc/backstage-sample-app
  links:
    - url: https://github.com/gsoeldner-sc/backstage-sample-app
      title: Server Root
      icon: github
spec:
  type: service
  lifecycle: experimental
  system: examples
  owner: user:default/guido.soeldner
  providesApis:
    - employees-api

Once, everything is done, we can easily import the definitions into the Software Catalog.

Once done, we can easily browse all the APIs, similar like if you go to some kind of Developer Pages like the Google API docs.

The image shows an interface of the Spotify Backstage plugin for managing an API called 'employees-api' under the Soeldner Consult brand. The interface is in the 'Definition' tab of the 'employees-api'. It displays the OpenAPI definition, version 0, compliant with OAS 3.0. The server URL is set to 'http://localhost:8080'. Below, it lists the endpoints for the 'employee-controller' with three methods: GET, PUT, and DELETE, each for '/employees/{id}', along with parameters required for the requests. The sidebar on the left includes options such as Home, APIs, Docs, Create, and Tech Radar.

Autor

Dr. Guido Söldner

Geschäftsführer

Guido Söldner ist Geschäftsführer und Principal Consultant bei Söldner Consult. Sein Themenfeld umfasst Cloud Infrastruktur, Automatisierung und DevOps, Kubernetes, Machine Learning und Enterprise Programmierung mit Spring.