Almost six months have passed since my introductory post about AsyncAPI , which is already an eternity in our fast-moving IT world. 😉 Shortly after publishing said post, more precisely in September last year, version 2.2.0 of the specification was released. At the beginning of February this year there was another so-called minor release to AsyncAPI version 2.3.0. Both versions are backward compatible with regard to the written API description, so that an update of the existing version value for the key asyncapi
shouldn’t be a problem and the description is still valid afterwards.
I would also like to use the previously used description again, which has been optimized a bit in the meantime, and use it to perform the migrations to version 2.3.0 of the specification.
1asyncapi: '2.1.0' 2info: 3 title: Order Service 4 version: 1.0.0 5 description: The service is in charge of processing orders 6 contact: 7 name: Daniel Kocot 8 email: daniel.kocot@codecentric.de 9 license: 10 name: Apache 2.0 11 url: https://www.apache.org/licenses/LICENSE-2.0.html 12servers: 13 rabbitmqInStaging: 14 url: rabbitmq-staging.codecentric.de:{port} 15 description: RabbitMQ Broker in staging environment 16 protocol: amqp 17 protocolVersion: '0.9.1' 18 variables: 19 port: 20 default: '5672' 21 enum: 22 - '5672' 23 - '15672' 24 rabbitmqInProd: 25 url: rabbitmq.codecentric.de:{port} 26 description: RabbitMQ Broker in production environment 27 protocol: amqp 28 protocolVersion: '0.9.1' 29 variables: 30 port: 31 default: '5672' 32 enum: 33 - '5672' 34 - '15672' 35channels: 36 orderProcessed: 37 publish: 38 operationId: orderProcessedPub 39 description: Payload of processed order 40 message: 41 $ref: '#/components/messages/orderProcessed' 42 bindings: 43 $ref: '#/components/messageBindings/amqp/bindings' 44 subscribe: 45 operationId: orderProcessedSub 46 description: Payload of processed order 47 message: 48 $ref: '#/components/messages/orderProcessed' 49 bindings: 50 $ref: '#/components/messageBindings/amqp/bindings' 51 bindings: 52 amqp: 53 $ref: '#/components/channelBindings/amqp' 54components: 55 schemas: 56 OrderPayload: 57 type: object 58 properties: 59 id: 60 type: integer 61 format: int64 62 description: ID of received order 63 customerReference: 64 type: string 65 description: Reference for the customer according the order 66 messages: 67 orderProcessed: 68 name: orderProcessed 69 title: Order Processed 70 summary: Inform about a new processed order in the system 71 contentType: application/json 72 payload: 73 $ref: '#/components/schemas/OrderPayload' 74 channelBindings: 75 amqp: 76 is: routingKey 77 exchange: 78 name: orderExchange 79 type: direct 80 durable: true 81 vhost: / 82 bindingVersion: 0.2.0 83 messageBindings: 84 amqp: 85 bindings: 86 amqp: 87 timestamp: true 88 ack: false 89 bindingVersion: 0.2.0
Assigning channels to servers
Let’s start directly with the first feature, the assignment of channels to servers, which has been available since AsyncAPI 2.2.0. This enables us to assign the respective channel to one or more specific servers. This is done by setting the optional servers
property of type string related to the Channel Item
object. Please note that the names of the servers always need to be the same as the names of the servers defined in the server
object. We now adapt the above example to the feature accordingly.
1asyncapi: '2.2.0' 2info: 3 title: Order Service 4 version: 1.0.0 5 description: The service is in charge of processing orders 6 contact: 7 name: Daniel Kocot 8 email: daniel.kocot@codecentric.de 9 license: 10 name: Apache 2.0 11 url: https://www.apache.org/licenses/LICENSE-2.0.html 12servers: 13 rabbitmqInStaging: 14 url: rabbitmq-staging.codecentric.de:{port} 15 description: RabbitMQ Broker in staging environment 16 protocol: amqp 17 protocolVersion: '0.9.1' 18 variables: 19 port: 20 default: '5672' 21 enum: 22 - '5672' 23 - '15672' 24 rabbitmqInProd: 25 url: rabbitmq.codecentric.de:{port} 26 description: RabbitMQ Broker in production environment 27 protocol: amqp 28 protocolVersion: '0.9.1' 29 variables: 30 port: 31 default: '5672' 32 enum: 33 - '5672' 34 - '15672' 35channels: 36 orderProcessed: 37 servers: 38 - rabbitmqInStaging 39 publish: 40 operationId: orderProcessedPub 41 description: Payload of processed order 42 message: 43 $ref: '#/components/messages/orderProcessed' 44 bindings: 45 $ref: '#/components/messageBindings/amqp/bindings' 46 subscribe: 47 operationId: orderProcessedSub 48 description: Payload of processed order 49 message: 50 $ref: '#/components/messages/orderProcessed' 51 bindings: 52 $ref: '#/components/messageBindings/amqp/bindings' 53 bindings: 54 amqp: 55 $ref: '#/components/channelBindings/amqp' 56components: 57 schemas: 58 OrderPayload: 59 type: object 60 properties: 61 id: 62 type: integer 63 format: int64 64 description: ID of received order 65 customerReference: 66 type: string 67 description: Reference for the customer according the order 68 messages: 69 orderProcessed: 70 name: orderProcessed 71 title: Order Processed 72 summary: Inform about a new processed order in the system 73 contentType: application/json 74 payload: 75 $ref: '#/components/schemas/OrderPayload' 76 channelBindings: 77 amqp: 78 is: routingKey 79 exchange: 80 name: orderExchange 81 type: direct 82 durable: true 83 vhost: / 84 bindingVersion: 0.2.0 85 messageBindings: 86 amqp: 87 bindings: 88 amqp: 89 timestamp: true 90 ack: false 91 bindingVersion: 0.2.0
Servers and channels as reusable objects
With version 2.3.0 servers
and channels
are available as reusable objects. Thus, the two elements only have to be defined within the components
, then they can be referenced within the description. This is now also applied to our example description.
1asyncapi: '2.3.0' 2info: 3 title: Order Service 4 version: 1.0.0 5 description: The service is in charge of processing orders 6 contact: 7 name: Daniel Kocot 8 email: daniel.kocot@codecentric.de 9 license: 10 name: Apache 2.0 11 url: https://www.apache.org/licenses/LICENSE-2.0.html 12servers: 13 staging: 14 $ref: '#/components/servers/rabbitmqInStaging' 15 production: 16 $ref: '#/components/servers/rabbitmqInProd' 17channels: 18 orderProcessed: 19 servers: 20 - staging 21 publish: 22 operationId: orderProcessedPub 23 description: Payload of processed order 24 message: 25 $ref: '#/components/messages/orderProcessed' 26 bindings: 27 $ref: '#/components/messageBindings/amqp/bindings' 28 subscribe: 29 operationId: orderProcessedSub 30 description: Payload of processed order 31 message: 32 $ref: '#/components/messages/orderProcessed' 33 bindings: 34 $ref: '#/components/messageBindings/amqp/bindings' 35 bindings: 36 amqp: 37 $ref: '#/components/channelBindings/amqp' 38components: 39 schemas: 40 OrderPayload: 41 type: object 42 properties: 43 id: 44 type: integer 45 format: int64 46 description: ID of received order 47 customerReference: 48 type: string 49 description: Reference for the customer according the order 50 servers: 51 rabbitmqInStaging: 52 url: rabbitmq-staging.codecentric.de:{port} 53 description: RabbitMQ Broker in staging environment 54 protocol: amqp 55 protocolVersion: '0.9.1' 56 variables: 57 port: 58 default: '5672' 59 enum: 60 - '5672' 61 - '15672' 62 rabbitmqInProd: 63 url: rabbitmq.codecentric.de:{port} 64 description: RabbitMQ Broker in production environment 65 protocol: amqp 66 protocolVersion: '0.9.1' 67 variables: 68 port: 69 default: '5672' 70 enum: 71 - '5672' 72 - '15672' 73 messages: 74 orderProcessed: 75 name: orderProcessed 76 title: Order Processed 77 summary: Inform about a new processed order in the system 78 contentType: application/json 79 payload: 80 $ref: '#/components/schemas/OrderPayload' 81 channelBindings: 82 amqp: 83 is: routingKey 84 exchange: 85 name: orderExchange 86 type: direct 87 durable: true 88 vhost: / 89 bindingVersion: 0.2.0 90 messageBindings: 91 amqp: 92 bindings: 93 amqp: 94 timestamp: true 95 ack: false 96 bindingVersion: 0.2.0
Contributor time
When looking at the description, it quickly becomes apparent that there is further potential with regard to reusability. This refers specifically to the variables
for the server
object. Exactly this caused me to post a Request for Comments (RFC) in the Git repo for the specification. In the meantime three pull requests followed out of the RFC. One for the specification itself and the other for the JSON schema . I submitted the third and final pull request for the JS parser shortly after the post was published. Now the feature can become a part of the next release (2.4.0) of the AsyncAPI specification. Hopefully ;). If you also have a feature in mind for an open-source project, I can only encourage you to put it into action. Only in this way can we help keep open source an integral part of our daily work.
New protocol bindings
After this short trip into the world of open source contributions I would like to take a look at the innovations regarding protocol bindings. What is actually meant by protocol bindings? Protocol bindings or short bindings describe the specifics of the used protocol. They are the basis of the architecture component, which is an essential part of the description with AsyncAPI. This can be done on the levels of server
, channel
, operation
and message
. Up to version 2.1.0 the following protocols are supported:
- HTTP
- Websockets
- Kafka
- AMQP 0.91
- AMQP 1.0
- MQTT
- MQTT 5
- NATS
- JMS
- SNS
- SQS
- STOMP
- Redis
- Mercure
- IBM MQ
However, the binding for IBM MQ cannot be applied at the level of ‘operation’. With the last two releases two more bindings for Anypoint MQ and Solace have been added. More detailed information about the bindings can be found at Repo within the AsyncAPI Org in GitHub.
Outlook and summary: Beyond AsyncAPI version 2.3.0
In AsyncAPI, we find a very convenient way to describe event- and message-driven architectures and also to incorporate this description into existing processes of our API lifecycle, supported by CI/CD pipelines. It will be exciting to see how this and other specifications and the topics around the description of APIs will evolve in the coming years. So look forward to more posts on these aspects.
More articles
fromDaniel Kocot
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Daniel Kocot
Senior Solution Architect / Head of API Consulting
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.