Skip to content

Latest commit

 

History

History
253 lines (201 loc) · 14.1 KB

AsyncApiFromUml.md

File metadata and controls

253 lines (201 loc) · 14.1 KB

Generating an AsyncAPI Specification from an annotated UML model

It is possible to generate an skeleton AsyncAPI Specification from an annotated UML model. For this, we provide an Industry 4.0 (I4.0) UML profile. In this page you'll find:

If you want to learn more about our AsyncAPI Toolkit, check out our main README file.

How did we create this model?

UML is a powerful language that allows us to represent everything from the architecture to the behavioral aspects of software systems. However, when its expressiveness is too broad for a given context, it can be tailored for specific purposes by profiling. A UML profile provides a set of stereotypes and tagged values that are added to UML models to extend their semantics. To build a UML profile, the application domain must be analyzed to identify its particularities. Following best practices, this analysis can be captured in a domain model. In our case, we have defined a publish-subscribe model in Industry 4.0 for, subsequently and following the good practices of Lagarde et al. and Selic, get a UML profile.

This is the domain model we have defined for the Industry 4.0 field:

I4.0 UML Domain Model

As can be seen, in an Industry 4.0 architecture we find at least one message Broker in addition to the architecture components (I4.0 Component). A broker has a name, a URL (url), accepts a protocol, and may have a description. The architecture components define and execute Operatiosn. When a given operation publishes to a Topic (which has a name, can have a description, and can be parameterized---see parameters), or is executed as a consequence of a subscription to a topic, becomes a Publisher or a Subscriber operation. A publisher operation sends a type of Message, just like a subscriber operation. Messages have a name, and can have a description, and a certain content (Payload). Said content is an object with a certain value and that conforms to a certain type.

What does this profile look like?

Starting from the previous model, and following the good practices indicated above, we have derived the UML profile below:

I4.0 UML Profile

Thus, a UML model (Model metaclass) can be annotated as an Industry 4.0 architecture using the I4.0 Architecture stereotype. Using this stereotype, we can add metadata such as the name of the architecture (name), the version of the specification, or a description. Likewise, UML components (metaclass Component) can be annotated as I4.0 Component (to indicate that they are components of our Industry 4.0 architecture), or as Broker (to indicate that they represent a broker). Brokers have the same properties as in the domain model (name, url, protocol, and description). Also, all components of Industry 4.0 must be associated with a broker.

The operations (Operation metaclass) of an Industry 4.0 component can be annotated as Publisher or Subscriber to indicate that they publish to a topic, or are run by a subscription to a topic, via the topic property. As in the domain model, a Topic is a UML Signal. In this case, a Signal annotated as a Topic has a name, an optional description, an optional identifier of the publish and subscribe operations (_ publishOpId_ and subscribeOpId, respectively), and a set of parameters, which in turn can be named, typed, and can contain optional descriptions. Note that the identifiers publishOpId and subscribeOpId do not necessarily have to coincide with the name of the operations of the components that publish or subscribe to a given topic, since a given topic is going to be associated with numerous publisher and subscriber operations. Next, we see that any UML StructuredClassifier can be annotated to represent a certain Message. Thus, a message has a name, and an optional description. It should be noted that, since in the domain model a message points to a single Payload whose type is a StructuredClassifier, the profile has avoided representing Payload explicitly: the type of the Payload is the StructuredClassifier itself annotated by the message, and its value, the object resulting from instantiating said StructuredClassifier. Finally, we find the RedefinableProperty stereotype, which allows us to annotate properties (metaclass Property). This is a helper stereotype that allows us to set a friendlier name, or title, to any property at the modeler's convenience.

Do you provide any example?

Yes! Look at the model below!

I4.0 UML model

What can be generated out of an annotated UML model?

From the above profiles model, it is possible to obtain the following AsyncAPI specification:

{
	"asyncapi": "2.0.0",
	"info": {
		"title" : "Example Architecture",
		"version" : "0.1.0"
	},
	"servers": {
		"production" : {
			"url" : "example.com:1883",
			"protocol" : "mqtt"
		}
	},
	"channels": {
		"iotbox/{id}/monitor" : {
			"parameters" : {
				"id" : {
					"schema" : {
						"type" : "string"
					}
				}
			},
			"publish" : {
				"operationId" : "sendStatus",
				"message": {
					"$ref" : "#/components/messages/MonitorMessage"
				}
			},
			"subscribe" : {
				"operationId" : "receiveStatus",
				"message": {
					"$ref" : "#/components/messages/MonitorMessage"
				}
			}
		},
		"iotbox/{id}/configure" : {
			"parameters" : {
				"id" : {
					"schema" : {
						"type" : "string"
					}
				}
			},
			"publish" : {
				"operationId" : "sendServiceConfiguration",
				"message": {
					"$ref" : "#/components/messages/ConfigurationMessage"
				}
			},
			"subscribe" : {
				"operationId" : "receiveServiceConfiguration",
				"message": {
					"$ref" : "#/components/messages/ConfigurationMessage"
				}
			}
		}
	},
	"components": {
		"messages": {
			"MonitorMessage" : {
				"name" : "MonitorMessage",
				"payload" : {
					"$ref" : "#/components/schemas/PathInfo"
				}
			},
			"ConfigurationMessage" : {
				"name" : "ConfigurationMessage",
				"payload" : {
					"$ref" : "#/components/schemas/Configuration"
				}
			}
		},
		"schemas": {
			"Configuration" : {
				"type" : "object",
				"properties" : {
					"monitoringfrequency" : {
						"$ref" : "#/components/schemas/MonitoringFrequency"
					}
				}
			},
			"MonitoringFrequency" : {
				"type" : "object",
				"properties" : {
					"value" : {
						"type" : "integer"
					},
					"unit" : {
						"type" : "string",
						"enum" : [
							"seconds",
							"minutes"
						]
					}
				}
			},
			"PathInfo" : {
				"type" : "object",
				"properties" : {
					"id" : {
						"type" : "string"
					},
					"beltInfos" : {
						"type" : "array",
						"items" : {
							"$ref" : "#/components/schemas/BeltInfo"
						}
					}
				}
			},
			"BeltInfo" : {
				"type" : "object",
				"properties" : {
					"id" : {
						"type" : "string"
					},
					"ts" : {
						"type" : "string",
						"title" : "timestamp"
					},
					"speed" : {
						"type" : "integer"
					}
				}
			}
		}
	}
}

How can I test and play with this functionality?

First, Download and install the AsyncAPI Toolkit.

To see the above model, and test the transformation and the code generation, run the Example AsyncAPI Project from I4.0 UML Model.

First, use the dedicated wizard in the New Project dialog:

New Project Wizard - Step 1

Second, AsyncAPI Project, set a project name, and continue.

New Project Wizard - Step 2

Third, select the Example AsyncAPI Project from I4.0 UML Model template.

New Project Wizard - Step 3

Finally, the wizard can be completed.

New Project Wizard - Step 4

After that, a new Maven project with the following contents will appear in the workspace.

Streetlights API Project Contents

Pay special attention to the following files:

  • src/main/java/example/I40.di is the main Papyrus UML file with the example Industry 4.0 architecture shown above.

  • src/main/java/example/I40.asyncapi is the AsynAPI specification which is automatically generate from the UML model above. Code and other resourcs in the gen directory will be generated from the specification contained in this file.

  • src/main/java/example/SubscribeExample.java is an example program demonstrating how to use the generated code. In this case, this program subscribes to an example topic, and waits for messages until enter is pressed.

  • src/main/java/example/PublishExample.java is another example program. In this case, this program publishes messages in the example topic, one per each execution of the program. In can be executed at the same time than the SubscribeExample.java program, and messages sent by this program will be received by SubscribeExample.java.

Where can I find the profile in the source code?

The profile can be found in the /plugins/io.github.abelgomez.asyncapi.i40.profile/model/ directory. These are the main contents:

Can I regenerate my AsyncAPI specification (and the generated code) after modifying the initial UML model?

Yes! But keep in mind that any manual modifications to the I40.asyncapi file will be overwritten!

Just use the AsyncAPI -> Generate AsyncAPI context menu over the I40.uml file:

Regenerate code

Where can I find the different transformations in the source code?

The integration of the Industry 4.0 Profile within the AsyncAPI Toolkit relies on two model transformations: