A guide to OpenAPI components

In the vast world of software development, APIs serve as a way to connect different systems, applications, and services, enabling them to communicate and work together harmoniously. As the digital world continues to expand, the role of APIs has become more critical than ever, acting not just as connectors, but as the backbone of modern software applications.

That’s why there was a need to standardise them, especially in a RESTful world. A need that Swagger and now OpenAPI specification addressed. We noticed that with a clear standard at hand we could make integration with your services a piece of cake within Nussknacker – so we introduced the OpenAPI component which does exactly that.

What is OpenAPI and how does it help us?

In simple terms OpenAPI is a specification for describing RESTful web services. It acts as a universal language for APIs, bridging gaps between different technologies and facilitating a seamless exchange of data and functionalities. A service interface definition, written in YAML or JSON format, includes information about an API’s available endpoints, their operations, input and output parameters, authentication methods, and other details.

How can it benefit us?

OpenAPI wide adoption among big companies and smaller projects didn’t come out of thin air. Having a simple and clear specification for our services can greatly benefit us in many different ways. Its usefulness is further bolstered by a robust ecosystem of tools and community support. Just to name a few things it can help us with:

  • Interoperability – By having a common language for describing APIs, OpenAPI facilitates the integration of diverse services and systems.
  • Documentation – We can automatically generate documentation for our API. This makes it easier for people involved to see what endpoints are available, their methods, expected request formats, and the structure of response messages.
  • API Design and Mocking – We can approach our API development with an API-first approach where we design the specification before writing any line of code. Tools can then use it to mock the endpoints, allowing frontend developers to start coding against it even before the backend is ready.
  • API Testing – Tools can use our interface definitions to generate test cases for our endpoints, ensuring that our API behaves as expected.

Another reason for its high popularity is also its ability to offer a machine and human readable format for the interface definition, which can be easily shared among stakeholders, including developers, testers, and business analysts. This enhances communication and reduces inconsistencies during API development, thereby further accelerating the development cycle.

As I mentioned there is a plethora of useful commercial and open-source tools that you can use to leverage aligning your services with OpenAPI specification. This includes:

Highly recommend checking them out!

OpenAPI components in Nussknacker

As OpenAPI solves many of the problems that can be encountered during planning and development of our services, it is now a very popular solution. At Nussknacker we decided to take advantage of that and significantly ease enriching your data in scenarios with so-called OpenAPI components. All you have to do is provide an OpenAPI based interface definition of your service and magic will happen — Nu will automatically create components based on your interface definition and they will be ready to use! Nussknacker supports both 3.x and 2.x versions of OpenAPI specification.

OpenAPI component is available in the on-premise version of Nussknacker as well as in Nu Cloud. Let’s see how we can use them and how they can help you with enriching data in your scenarios.

Nussknacker on-premise

The configuration to use OpenAPI components is very straightforward and needs just one thing — OpenAPI interface definition of your service. It gives Nussknacker all important information such as: required parameters, returned values, endpoints’ paths and so on. However, we can add a few more lines of simple configuration if we need to. Let me show you how.

Component configuration

Below we have an example configuration for a service that can provide us with additional data about our customers’ profiles. It needs to be placed in the components section under the model configuration. For more information about Nussknacker configuration you check out our awesome docs!

components {  customerProfileOffers: {

      providerType: openAPI  

      url = "http://myservice.com/customerApi.yaml"

      rootUrl = "http://myservice.com/api"

      security {

          apikeySecuritySchema {

              type = "apiKey"

              apiKeyValue = "07568e0c-8f9f-49b6-afdf-cfb0f7ae9006"

          }

      }

      namePattern: "get.*"

      allowedMethods: ["GET"]

  }

}

 

As I mentioned, the OpenAPI based interface definition is the only part required that we have to provide. The rest is optional unless we require additional authentication to our API or service location was not provided in the interface definition. Let’s go through the configuration to see what each section does.

providerType – By assigning it to openAPI we state that Nussknacker should create OpenAPI components.

url – URL of the OpenAPI interface definition. It contains the definition of the service you want to interact with.

rootUrl – The URL of the service. If not specified, the URL of the service is taken from the OpenAPI interface definition.

security.*.type – Here we define the type of authentication to our service (in case we have one!). Currently, only apiKey is supported.

security.*.apiKeyValue – An API key which will be sent to the service for authentication purposes.

namePattern – Here we can provide a regex pattern for filtering operations in our OpenAPI interface definition. Pattern will be matched against defined operationId and components will be created only for the operations that pass this filter. It lets us control which operation we actually want to use.

allowedMethods – Here we can provide which methods will be allowed to send requests to the service. Usually we should only use GET requests as enriching components should rather only fetch data and not modify it.

And that’s pretty much it when it comes to configuring OpenAPI components! Now let’s take a look at our service’s interface definition so we can get down to the more practical stuff and see these components in action!

Our interface definition

For the demonstration purposes I created a simple OpenAPI based interface definition for a service with two endpoints:

/customer/{customerId}/profile – This endpoint simulates fetching additional data about our customer’s profile. 

/offers/{customerType} – And this one fetches offers prepared for certain customer types. We can get them from our first endpoint.

Below you can see the most important parts of the service’s interface definition for our OpenAPI components. There we define our operations — their paths, what parameters they require and what kind of responses they produce.

openapi: 3.0.0

...

paths:

  '/customer/{customerId}/profile':

    parameters:

      - schema:

          type: integer

        name: customerId

        in: path

        required: true

        description: Id of a customer.

    get:

      summary: Get customer profile by customer's ID

      externalDocs:

        url: http://myservice.com/docs/customerProfile

      responses:

        '200':

          description: Customer profile found

          content:

            application/json:

              schema:

                $ref: '#/components/schemas/CustomerProfile'

        '404':

          description: No customer profile found

      operationId: getCustomerProfile

      description: Get customer profile information by customer's ID.

...

components:

  schemas:

    CustomerProfile:

      title: CustomerProfile

      type: object

      properties:

        id:

          type: integer

          description: Profile's unique identifier.

        customerType:

          type: string

...

 

It's worth to take a look at a few things here:

  • parameters section – Here we define our service's parameters. They will be used as the component’s parameters at Nussknacker. In our case we'll see a customerId field that we should fill.
  • externalDocs – Link to the documentation of a certain service. If provided it could be used for a quick navigation between our new component and documentation.
  • operationId – This is a unique name of our operation. If provided it will be used as the component's name. In our case the component will be named getCustomerProfile.

For the backend of our services we will be using API mock created with an open-source solution called Mockoon (highly recommend it!). It will return random data that we will use in our scenario for decision-making. If you want to learn how you can use it in your project check out their tutorials!

Components in action!

After we provide Nussknacker with the interface definition and spin up the Designer we can create a new scenario. After that in the components’ palette on the left side we can immediately see that Nu has created ready to use components for us based on the provided file!

As I mentioned earlier their names, getCustomerProfile and getOffersForCustomerType, are based on operationId attributes that we provided in our OpenAPI based interface definition. If they were not present in the file Nussknacker would create these names based on the concatenation of the HTTP method, path and parameters to provide some component name uniqueness.

After that we can drag these components along with others to create a simple scenario where we make a decision on what adequate offer we should give to our customer based on what we receive from our newly created enrichers.

When we double-click on it we can see how Nussknacker generated it. We have standard component fields along with the customerId which was defined as a parameter in the provided interface definition that we saw earlier. Nussknacker automatically creates an enricher's parameters based on the operation parameters. 

Additionally, when we click on the component name and the externalDocs.url was defined in the interface definition we will be redirected to the linked documentation so we could take a quick look at what we may expect from that certain operation!

We expect to receive data from the service with 200 or 201 HTTP status code and the object returned from the service is the result of an enricher. If we get a 404 status code, the null value will be the result. With enriched data in hand we can use it in other nodes of our scenario to make the final decision. As you may notice input and output parameters of our enrichment components are typed ensuring more safety. 

OpenAPI data types are mapped to Nussknacker ones based on the type and format provided in the interface definition. The mapping is pretty straightforward with just a few cases to keep in mind regarding dates and numbers. OpenAPI strings that have a format defined as date-time will be translated to LocalDateTime on the Nussknacker side. Similarly, when numbers have float or double formats they will be mapped to a Double type.

And that’s what using OpenAPI components in Nussknacker looks like! If you want to try it for yourself you can take a look at our quickstart. You can run a streaming configuration which has an OpenAPI component defined with mocked responses. Try running it with docker/streaming/start.sh script and feel free to experiment with interface definitions for your services!

Nussknacker Cloud

Using OpenApi components in Nussknacker Cloud is really simple. Configuration is similar to the on premise version. However here we don’t have to directly modify configuration files. We can use simple and pleasant UI for this. 

After we create our cloud instance it will automatically start running. To make changes to it we have to stop it first and then enter the settings.

Once we’re there we will be presented with a variety of ready to go enrichers that we can use! This time however we’ll focus on the OpenAPI one. Clicking on its tile will get us to the configuration panel.

Here we provide the configuration that looks quite similar to the one we saw earlier. We have to enter the necessary enricher name and URL pointing to the OpenAPI based interface definition. For this example we’ll be using an awesome open-source holidays calendar API provided by Nager.Date project. After entering the URL we’ll see which operations will be used for the components creation.

After that we can start our instance again and use our new lovely components! They behave in the same way as in the on-premise version so all rules still apply. Feel free to check out OpenAPI components and Nu Cloud for yourself!

Summary

OpenAPI is as popular as ever and has become a standard as a specification in a RESTful world. By utilising Nussknacker’s OpenAPI components you can easily integrate your services within Nussknacker and enrich your data in scenarios. I hope you give it a try and check for yourself how easy (and powerful!) it is. Also, check out our GitHub and stay tuned for more content to come!