View on GitHub

Microservice DSL (MDSL)

A Domain-Specific Language (DSL) to specify (micro-)service contracts, their data representations and API endpoints.

HomeData TypesBindingsProvider and ClientTutorialCheat SheetTools

Service Endpoint Contracts in MDSL

Use Cases for MDSL Specifications

Concepts

The contract syntax (grammar) of MDSL is inspired by the API domain model from Microservice API Patterns (MAP): An API description features one or more endpoints, which expose operations that expect and deliver messages.1:

ServiceSpecification: 
    'API' 'description' name=ID
    ('version' svi=SemanticVersioningIdentifier)? // plain STRING
    ('usage' 'context' reach=Visibility ('for' direction+=DirectionList)?)?
	('overview' description=STRING)?
	types+=DataContract*
	contracts+=EndpointContract+
	providers+=Provider*
	clients+=Client*
	gateways+=Gateway*
	orchestrations+=Orchestration* 
	scenarios+=IntegrationScenario* 
	('IPA')?;

EndpointContract:
	'endpoint' 'type' name=ID 
	('version' svi=SemanticVersioningIdentifier)? // plain STRING
	('serves' 'as' primaryRole=ResourceRole 
	    ('and' otherRoles+=ResourceRole)* 'role'?)? // pattern decorator
	('identified' 'by' pathParameters=ElementStructure)? 
	('exposes' ops+=operation+)?;
	('receives' events+=Event+)?

Operation:
	'operation' 
	name=ID 
	('version' svi=SemanticVersioningIdentifier)?
	('with' 'responsibility' responsibility=OperationResponsibility)? // pattern decorator
	('in'  mep=MessageExchangePattern 'conversation')? 
	('expecting' requestMessage=DataTransferRepresentation)? 
	('delivering' responseMessage=DataTransferRepresentation 
	  ('links' relations+=RelationshipLink+)? // optional within 'delivering'
	  ('reporting' reports=StatusReports)? // optional within 'delivering'
	)? // response is optional 
	('transitions' st=StateTransition)? 
	('emitting' events+=Event+)?  
	('compensated' 'by' undo=[Operation])?  
	('protected' 'by' policies=SecurityPolicies)?  

DataTransferRepresentation:
	('headers' headers=ElementStructure)? 
	'payload' payload=ElementStructure
	('structured' 'as' ts=TypeSystem)?;

The notation used above is the grammar language of Xtext (which is close to that of antlr4). The full MSDL grammar can be found here.

Endpoint types correspond to ports in the Hexagonal Architecture terminology; adapters are represented by technology bindings The request and response messages consist of headers and payloads, whose content is modelled with MDSL data transfer representations.

Note: The above MDSL grammar also has language concepts to model compensating operations, states and their transitions, event emission and reception, and security policies. These features are still under design and development. The MDSL Primer shows them, and sample specifications featuring these advanced concepts can also be found here and here. Please view these grammar extensions as technology previews subject to change in future versions.

Example

The following exemplary API specification compiles against the MDSL grammar sketched above:

API description SampleCustomerManagementAPI version "1.0.0"
usage context PUBLIC_API for FRONTEND_INTEGRATION 

endpoint type CustomerManagementContract 
  version "1.0.0" 
  serves as INFORMATION_HOLDER_RESOURCE
  exposes 
  	operation lookupSingleCustomer version "1.0.1"
	  with responsibility RETRIEVAL_OPERATION in REQUEST_REPLY conversation
	  expecting 
		payload ID<string> 
	  delivering  
		payload {"customerId":ID<int>,
		          "name":D,
		          "address"} 
				
  	operation lookupCustomerDirectory // no version information
	  with responsibility RETRIEVAL_OPERATION in REQUEST_REPLY conversation
	  expecting 
		payload <<Request_Bundle>> "customerId":ID<int>+ // at least one
	  delivering
		payload
		  "customerRecord": { 
			"cid":ID!, // ! mandatory, exactly one
			"nameTuple":("firstname":D, "lastname":D), 
			"addressTuple":(
			  "street":D<string>, 
			  "poBox":D?, // optional
			  "zipCode":D, 
			  "city":D)+,
			"segment":("REGULAR":D|"VIP":D) // choice 
		}* // zero or more

The described API SampleCustomerManagementAPIsupports one endpoint type CustomerManagementContract that exposes two operations lookupSingleCustomer, lookupCustomerDirectory to retrieve some customer data in a Customer Relationship Management (CRM) scenario. While request messages (expecting) are mandatory, response messages (delivering) are optional.

The specification of the message exchange pattern is optional; permitted values are REQUEST_REPLY, ONE_WAY and NOTIFICATION. Request-reply operations must have a request and a response message; one way operations only have a requests message.

Several Microservice API Patterns (MAPs) are used to annotate endpoint, operation, and one representation element (INFORMATION_HOLDER_RESOURCE, RETRIEVAL_OPERATION).2 Moreover, foundation patterns from MAP may comment on the usage scenario for the described API; this is optional (here: PUBLIC_API for FRONTEND_INTEGRATION). The MAP decorators are supported as explicit enum values in the grammar; you can also use any “STRING”.

The first operation lookupSingleCustomer requires the API client to send an ID in the request message to be able to return the corresponding customer record. Its response message format lists three atomic parameters (customerId, name, address).

The second operation lookupCustomerDirectory expects at least one customer id (+) so that multiple records can be returned in one response (*), which implements the Request Bundle pattern in MAP. This is indicated with the <<Request_Bundle>> stereotype. These pattern stereotypes merely serve as markers; tools such as code generators can use them to fine-tune their output.

The data contract of the lookupSingleCustomer operation is fully specified, whereas part of the message elements in the response of lookupCustomerDirectory are still incomplete (for instance, "zipCode":D).3

For more explanations of the message structures, see data contracts (schemas).

Security and Error Reporting

Response messages can indicate which type of error information might replace/accompany it, and operations can define a security policy:

endpoint type HelloWorldPlusEndpoint
exposes 
  operation sayHello in REQUEST_REPLY conversation
    expecting payload D<string>  
    delivering payload SampleDTO
      // message-level status report:
      reporting error "400": D<int> // bad request (HTTP error code) 
  // operation-level security policy:
  protected by policy "HTTPBasicAuthentication":MD

In this example, the error report is a simple numeric code (400); elaborate error reports can be modeled as well, as any MDSL data type can be used.

The security policy also is modelled as an MDSL data contract; it can be used to define the various security assertions and protocol headers that exist (for instance, basic authentication in HTTP, as explained in the OpenAPI specification). Important note: This MDSL feature also still is under design and construction (view it as an incomplete technology preview); future versions of the MDSL documentation pages will provide more examples.

Note: These two MDSL features and tool support for them still are under development; future versions of the MDSL documentation pages will provide more examples.

Technology Mappings

See this page for information on how MDSL maps to OpenAPI and REST, WSDL/SOAP, and gRPC.

Site Navigation

Copyright: Olaf Zimmermann, 2018-2022. All rights reserved. See license information.

  1. This domain model is published in Section 3 of the EuroPLoP 2019 paper on Patterns for API Evolution from the MAP team

  2. The notion of API roles and responsibilities as well as the term Information Holder have their roots in Responsibility-Driven Design (RDD)

  3. If an operation does not expect or deliver any payload, this can be expressed with the help of the empty/null type D<void>. This type should only be used for this purpose.