Support for OpenAPI and AsyncAPI Interfaces
REpresentational State Transfer (REST) is an architectural style for the design of network-based architectures. It guides the design of APIs that can be accessed over network.
CommaSuite supports REST in the following way:
-
Generation of API specifications from an interface or a group of interfaces following OpenAPI and AsyncAPI standards
-
Translation of captured REST and WebSocket network traffic to CommaSuite trace format for the purpose of monitoring
-
Generation of adapters for REST interfaces for the purpose of online model-based testing with CommaSuite
The remaining part of this page describes in details each item.
Generation of OpenAPI and AsyncAPI specifications from interfaces
CommaSuite can generate OpenAPI and AsyncAPI specifications in YAML format from a single interface or from a compound interface (a group of interfaces).
The generator task can be specified in the following way:
Generate REST { task1 for compound interface IVendingMachine { API name: "VendingMachine" version: "1.0.0" OpenAPI server URL: "http://localhost:9998" AsyncAPI server: "server" URL: "ws://localhost:8026" protocol: "ws" paths: vmMappings } }
Here the compound interface IVendingMachine groups together two interfaces:
Compound Interfaces { IVendingMachine { version "0.1" description "Description" interfaces IService IUser } }
The paths attribute in the generation task specifies the paths for the API endpoints for all commands, signals, and notifications in interfaces. It is given in a separate block for path mappings:
Path Mappings { vmMappings { interface IUser: InsertCoin -> /VendingMachine/v1/IUser/InsertCoin ReturnMoney -> /VendingMachine/v1/IUser/ReturnMoney OrderProduct -> /VendingMachine/v1/IUser/OrderProduct/{prodName} interface IService: SwitchOn -> /VendingMachine/v1/IService/SwitchOn LoadProduct -> /VendingMachine/v1/IService/LoadProduct/{product} Reset -> /VendingMachine/v1/IService/Reset SwitchOff -> /VendingMachine/v1/IService/SwitchOff OutOfOrder -> /VendingMachine/v1/IService/OutOfOrder InventoryUpdate -> /VendingMachine/v1/IService/InventoryUpdate GetStatus -> /VendingMachine/v1/IService/GetStatus } }
Here the parameter segments in the paths are based on the parameters in the interface events and are surrounded by curly braces:
LoadProduct -> /VendingMachine/v1/IService/LoadProduct/{product}
'product' is a parameter in the command LoadProduct.
Commands and signals are mapped to HTTP GET or PUT operations in the resulting OpenAPI specification according to the following rules:
-
signals are mapped to PUT operations
-
commands of type void and without out parameters are mapped to PUT
-
commands that return result and/or have out parameters are mapped to GET
Inout parameters are not allowed in commands. In addition, a GET operation is defined for every notification that carries parameters.
It is possible to override the above rules and to map a command that returns result to PUT operation. This can be given in the path mappings:
OrderProduct -> put /VendingMachine/v1/IUser/OrderProduct/{prodName}
AsyncAPI specification is generated from the notifications in the source interfaces. Notifications are mapped to channels.
After executing the generator tasks for REST specifications, a folder 'rest' will be created under 'src-gen' that will contain the generated .yaml files:
/src-gen /rest /task1 /channels /datatypes /paths vendingmachine.errorresponses.yaml vendingmachine.event.yaml vendingmachine.rest.yaml
Here file vendingmachine.rest.yaml contains the OpenAPI specification and file vendingmachine.event.yaml contains the AsyncAPI specification. In addition, schema data types are generated from CommaSuite record and enumeration types. The YAML files are located in folder 'datatypes'.
The user is encouraged to study the provided example project VendingMachineREST to get familiar with the generated .yaml files.
Generation of CommaSuite traces from captured OpenAPI and AsyncAPI traffic
Once YAML files are obtained according to the OpenAPI and AsyncAPI standards, various open source tools can be used to generate code and to develop a REST application.
Users might be interested in monitoring the OpenAPI and AsyncAPI traffic to check if it adheres to the interface specification.
The network traffic can be captured by tools like Wireshark and tshark (part of the Wireshark package). CommaSuite supports translating captured REST and WebSocket traffic. Here, WebSocket is used as a technology to implement the AsyncAPI that carries information from the interface notifications.
Once the traffic is captured with Wireshark or tshark in a .pcapng file, the following filter can be used:
tshark -r <input file .pcapng> -F logcat-long -Tfields -eframe.time_epoch -eip.src -etcp.srcport -eip.dst -etcp.dstport -ehttp.request.method -ehttp.request.uri -ehttp.file_data (http or websocket) > result.txt
In this example, the result is stored in file result.txt.
The filtered content contained in the result file needs to be converted to one of the CommaSuite trace formats. The following generator task can be defined in the .prj file:
Generate REST Trace { task1 { component VendingMachine path mappings vmMappings trace file "trace.txt" } }
The task requires a component definition that exposes the REST interfaces on its provided ports and the used path mappings. trace.txt is the file with raw REST and WebSocket traffic (after filtering). Required ports in the given component are not supported yet.
After the execution of the task, a trace file is produced in JSONL format according to the CommaSuite trace format. It can be used for monitoring. The result is located as follows:
src-gen/ trace/ trace.jsonl
The interested user can find an example trace file and a generator task in the example project VendingMachineREST.
Generation of adapter for OpenAPI interfaces to perform online model-based testing
This section requires familiarity with the CommaSuite support for online model-based testing and the generation of test application.
An existing REST application for which a component model is available can be tested using CommaSuite. For this purpose, a test application can be generated. As explained in the section about test application, an adapter is required to translate the calls from the test application to REST calls and back. Such an adapter can be generated automatically using information from the component model and the path mappings.
The generation of the adapter is triggered with the following example generation task:
Generate REST Adapter { vmRESTAdapter for component VendingMachine { ports: vmUserPort vmServicePort task: task1 ports: vmCoinPort task: task2 } }
The generation task is defined only for component models. Interface models are not currently supported. The adapter generation creates infrastructure for both provided and required component ports.
In general, multiple interfaces exposed via provided or required component ports can be accessed via a single REST service. This information needs to be specified in the generation task. In the example above, the interfaces IUser and IService form a single compound REST interface VendingMachine. This REST interface is specified in task1 for generating REST specification. The two interfaces are exposed via ports vmUserPort and vmServicePort. The information in the generation task specifies that these two ports are accessed via a single REST service generated with task1. Similarly, the interface ICoinChecker is used via the required port vmCoinPort. Its REST service specification is generated via task2. The information in the REST specification generation tasks is needed in the adapter generator to access the path mappings and the URLs of the REST services.
Once the adapter generator task is executed, a Java implementation of the adapter is generated. The AsyncAPI support is implemented with the WebSocket technology.
The generated Java files are located in folder named after the adapter generator task:
src-gen/ vmRESTAdapter/ java/ org/ ...
All the generated classes are grouped in package org.eclipse.comma.restadapter.
Due to a limitation in the used implementation of the WebSocket technology, the following limitation in the adapter exists for interfaces accessed via required ports. The paths of notifications must have the same length in segments. The last two segments must have the name of the interface and the name of the notification respectively. Parameters in notification paths are not supported. This limitation is not imposed on interfaces accessed via provided ports.
A demo of the adapter generation is available in the example project VendingMachineTestApplicationRESTExample. In this project, an example implementation of a vending machine is made available via a REST service. Notifications from the vending machine are sent via a WebSocket channel. The coin checking functionality is accessed via a required port. The generated adapter connects the test application to the REST service. It also contains functionality for the required port: a REST service for the coin checker and a WebSocket service for the coin checker notifications.