Swagger

How to generate Swagger documentation with Pip.Services.

Key takeaways

Swagger module Contains components used to generate Swagger UIs.
Swagger YAML file File used to declare methods to be documented via Swagger.
Swagger An Interface Description Language for describing RESTful APIs using JSON.

Introduction

In this tutorial, you will learn how to generate Swagger documentation for a REST service. We will see three different cases. The first is a common REST service, which is documented via a YAML file containing a description of its methods. The second is a commandable REST service, which has a defined set of commands that is used to define the Swagger document. Finally, the last case considers a commandable REST component with a command set and a Swagger UI defined by a YAML file.

Swagger document generation

Pip.Services offers two types of REST services, which are defined by two different classes. The first is an ordinary REST service and is defined by the RestService component. The second is a REST service that contains a set of predefined commands (or methods) that can be called from other services and is defined by the CommandableHttpService class.

As such, they represent two different approaches when it comes to Swagger documentation: A REST service needs a YAML file that describes its UI in order to generate its documentation, whereas a commandable service allows for automatic generation via a description of the command set or via a YAML file if the path to it is included in the configuration file. Moreover, it should be noted that an automatically-generated description always considers an HTTP method as POST.

To explain these cases, we will create an app that given a name returns the phrase “Hello {name}” by calling a method named greeting. In this app, we will include the necessary elements to create a Swagger UI that documents this method. The following sections teach the steps to achieve this goal.

Pre-requisites

First of all, to create a Swagger UI, we need to install the swagger module. This can be done with the following command:

npm install pip-services3-swagger-nodex --save
dotnet add package PipServices3.Swagger
go get github.com/pip-services3-gox/pip-services3-swagger-gox
dart pub add pip_services3_swagger
pip install pip-services3-swagger
Not available

Document 1: REST service

In this case, we want to document the greeting method as part of a REST service. For this, we need to define a YAML file containing the information necessary to create the Swagger UI.

Service

Our REST service is called HelloFriendService. It is defined by a class that inherits from the RestService component and has a method named greetings, which given a name, returns “Hello {name}” on a web page.

It also contains a reference to the controller and a method named register that defines the necessary elements for the Swagger UI. Its code is as follows:

import { ConfigParams, Descriptor, IReferences } from 'pip-services3-commons-nodex';
import { RestService } from 'pip-services3-rpc-nodex';

class HelloFriendRestService extends RestService {
    private _controller: HelloFriendController;

    // swagger
    private _swaggerContent: string;
    private _swaggerPath: string;

    public constructor() {
        super();
        this._baseRoute = "/hello_friend";

        let controllerDescriptor = new Descriptor("hello-friend", "controller", "*", "*", "1.0");
        this._dependencyResolver.put("controller", controllerDescriptor);
    }

    public configure(config: ConfigParams): void {
        super.configure(config);

        // swagger
        this._swaggerContent = config.getAsNullableString("swagger.content");
        this._swaggerPath = config.getAsNullableString("swagger.path");
    }

    public setReferences(references: IReferences) {
        super.setReferences(references);
        this._controller = this._dependencyResolver.getOneRequired<HelloFriendController>("controller");
    }

    public register(): void {
        this.registerRoute("GET", "/greeting", null, this.greeting);

        // swagger
        if (this._swaggerContent != null)
            this.registerOpenApiSpec(this._swaggerContent);

        if (this._swaggerPath != null)
            this.registerOpenApiSpecFromFile(this._swaggerPath);
    }

    public async greeting(req: any, res: any): Promise<void> {
        let name = req.query.name;
        let result = this._controller.greeting(name);

        this.sendResult(req, res, result);
    }
}

using System.Threading.Tasks;

using PipServices3.Commons.Config;
using PipServices3.Commons.Refer;
using PipServices3.Rpc.Services;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;

public class HelloFriendRestService: RestService
{
    private HelloFriendController _controller;

    // swagger
    private string _swaggerContent;
    private string _swaggerPath;

    public HelloFriendRestService(): base()
    {
        _baseRoute = "/hello_friend";

        var controllerDescriptor = new Descriptor("hello-friend", "controller", "*", "*", "1.0");
        _dependencyResolver.Put("controller", controllerDescriptor);

    }

    public override void Configure(ConfigParams config)
    {
        base.Configure(config);

        // swagger
        _swaggerContent = config.GetAsNullableString("swagger.content");
        _swaggerPath = config.GetAsNullableString("swagger.path");
    }

    public override void SetReferences(IReferences references)
    {
        base.SetReferences(references);
        _controller = _dependencyResolver.GetOneRequired<HelloFriendController>("controller");
    }

    public override void Register()
    {
        RegisterRoute("GET", "/greeting", this.Greeting);

        // swagger
        if (_swaggerContent != null)
            RegisterOpenApiSpec(_swaggerContent);

        if (_swaggerPath != null)
            RegisterOpenApiSpecFromFile(_swaggerPath);
    }

    public async Task Greeting(HttpRequest req, HttpResponse res, RouteData routeData)
    {
        var name = req.Query["name"];
        var result = _controller.Greeting(name);

        await SendResultAsync(res, result);
    }
}

import (
	"context"
	"net/http"
	"os"

	ccmd "github.com/pip-services3-gox/pip-services3-commons-gox/commands"
	cconf "github.com/pip-services3-gox/pip-services3-commons-gox/config"
	crefer "github.com/pip-services3-gox/pip-services3-commons-gox/refer"
	crun "github.com/pip-services3-gox/pip-services3-commons-gox/run"
	cvalid "github.com/pip-services3-gox/pip-services3-commons-gox/validate"
	cbuild "github.com/pip-services3-gox/pip-services3-components-gox/build"
	cproc "github.com/pip-services3-gox/pip-services3-container-gox/container"
	rbuild "github.com/pip-services3-gox/pip-services3-rpc-gox/build"
	rpcservices "github.com/pip-services3-gox/pip-services3-rpc-gox/services"
	cswagger "github.com/pip-services3-gox/pip-services3-swagger-gox/build"
)

// REST service (Swagger UI from YAML file)

type HelloFriendRestService struct {
	*rpcservices.RestService

	_swaggerContent string
	_swaggerPath    string
	_controller     *HelloFriendController
}

func NewHelloFriendRestService() *HelloFriendRestService {
	c := &HelloFriendRestService{}
	c.RestService = rpcservices.InheritRestService(c)
	c.BaseRoute = "/hello_friend"

	controllerDescriptor := crefer.NewDescriptor("hello-friend", "controller", "*", "*", "1.0")
	c.DependencyResolver.Put(context.Background(), "controller", controllerDescriptor)
	return c
}

func (c *HelloFriendRestService) Configure(ctx context.Context, config *cconf.ConfigParams) {
	c.RestService.Configure(context.Background(), config)

	// swagger
	c._swaggerContent, _ = config.GetAsNullableString("swagger.content")
	c._swaggerPath, _ = config.GetAsNullableString("swagger.path")
}

func (c *HelloFriendRestService) SetReferences(ctx context.Context, references crefer.IReferences) {
	c.RestService.SetReferences(ctx, references)
	depRes, depErr := c.DependencyResolver.GetOneRequired("controller")
	if depErr == nil && depRes != nil {
		c._controller = depRes.(*HelloFriendController)
	}
}

func (c *HelloFriendRestService) greeting(res http.ResponseWriter, req *http.Request) {
	// vars := mux.Vars(req)

	name := req.URL.Query().Get("message")
	// message := vars["name"]
	result := c._controller.Greeting(name)

	c.SendResult(res, req, result, nil)
}

func (c *HelloFriendRestService) Register() {
	c.RegisterRoute("GET", "/greeting", nil, c.greeting)

	// swagger
	if c._swaggerContent != "" {
		c.RegisterOpenApiSpec(c._swaggerContent)
	}

	if c._swaggerPath != "" {
		c.RegisterOpenApiSpecFromFile(c._swaggerPath)
	}
}

import 'dart:async';

import 'package:pip_services3_commons/pip_services3_commons.dart';
import 'package:pip_services3_rpc/pip_services3_rpc.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';

class HelloFriendRestService extends RestService {
  HelloFriendController? _controller;

  String? _swaggerContent;
  String? _swaggerPath;

  HelloFriendRestService() : super() {
    baseRoute = '/hello_friend';

    var controllerDescriptor =
        Descriptor('hello-friend', 'controller', '*', '*', '1.0');
    dependencyResolver.put('controller', controllerDescriptor);
  }

  @override
  void configure(ConfigParams config) {
    super.configure(config);

    // swagger
    _swaggerContent = config.getAsNullableString("swagger.content");
    _swaggerPath = config.getAsNullableString("swagger.path");
  }

  @override
  void setReferences(IReferences references) {
    super.setReferences(references);

    _controller =
        dependencyResolver.getOneRequired<HelloFriendController>('controller');
  }

  @override
  void register() {
    registerRoute('get', '/greeting', null, _greeting);

    // swagger
    if (_swaggerContent != null) {
      registerOpenApiSpec_(_swaggerContent!);
    }

    if (_swaggerPath != null) {
      registerOpenApiSpecFromFile(_swaggerPath!);
    }
  }

  FutureOr<Response> _greeting(Request req) {
    var name = req.params['name'];
    var result = _controller!.greeting(name);

    return sendResult(req, result);
  }
}

from pip_services3_commons.refer import Descriptor
from pip_services3_commons.validate import Schema
from pip_services3_rpc.services import RestService

import bottle


class HelloFriendRestService(RestService):

    def __init__(self):
        super(HelloFriendRestService, self).__init__()

        self._base_route = "/hello_friend"

        ControllerDescriptor = Descriptor('hello-friend', 'controller', '*', '*', '1.0')
        self._dependency_resolver.put('controller', ControllerDescriptor)
        self._controller = None

        # Swagger
        self._swagger_content = None
        self._swagger_path = None

    def configure(self, config):
        super().configure(config)
        
        # Swagger
        self._swagger_content = config.get_as_nullable_string("swagger.content")
        self._swagger_path = config.get_as_nullable_string('swagger.path')

    def set_references(self, references):
        super(HelloFriendRestService, self).set_references(references)
        self._controller = self._dependency_resolver.get_one_required('controller')

    def register(self):
        self.register_route(method="GET", route="/greeting", schema=Schema(), handler=self.greeting)
        
        # Swagger
        if self._swagger_content:
            self._register_open_api_spec(self._swagger_content)

        if self._swagger_path:
            self._register_open_api_spec_from_file(self._swagger_path)

    def greeting(self):
        name = bottle.request.query.get('name')
        result = self._controller.greeting(name)
        return self.send_result(result)
Not available
Configuration

As we will use a process container to run the example, we need to describe this service in the configuration file. In this description, we set the Swagger’s enable field to true to specify that we want to generate a Swagger UI for the service, and we define the path to our YAML file containing the Swagger UI description.

# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'
# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: '../../../rest_swagger.yml'
# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'
# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'
# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'
Not available
Swagger YAML file

Now, we create a YAML file that will be used by Swagger to define the UI. In our case, the service has the greeting method only, which we consider of type GET. An example of this file is:

openapi: '3.0.2'
info:
  title: 'Friends Service'
  description: 'REST API from YAML file'
  version: '1'
paths:
  /hello_friend/greeting:
    get:
      tags:
        - hello_friend
      parameters:
        - in: query
          name: name
          schema:
            type: string
          required: true
      responses:
        201:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: 'object'

Documents 2 & 3: Commandable REST service

These two cases document the same commandable REST service. The difference between them is that the first automatically generates the Swagger UI based on a command set, and the second uses a YAML file.

Command set

To create a command set, we extend the CommandSet class and define our greeting command in it. The code below illustrates how to do this:

import { 
    Command, CommandSet, ICommand, 
    ObjectSchema, TypeCode, Parameters 
} from 'pip-services3-commons-nodex';

class FriendsCommandSet extends CommandSet {
    private _controller: HelloFriendController;

    public constructor(controller: HelloFriendController) {
        super();

        this._controller = controller;

        this.addCommand(this.makeGreeting());
    }

    private makeGreeting(): ICommand {
        return new Command('greeeting', 
            new ObjectSchema(true).withRequiredProperty('name', TypeCode.String), 
            async (correlationId: string, args: Parameters) =>
            {
                let name = args.getAsString("name");
                let res = this._controller.greeting(name);
                return res;
            }
        );
    }
}

using System;

using PipServices3.Commons.Commands;
using PipServices3.Commons.Validate;
using PipServices3.Commons.Run;

public class FriendsCommandSet: CommandSet
{
    private HelloFriendController _controller;

    public FriendsCommandSet(HelloFriendController controller) : base()
    {
        _controller = controller;

        AddCommand(MakeGreeting());
    }

    private ICommand MakeGreeting()
    {
        return new Command("greeting", 
                new ObjectSchema().WithRequiredProperty("name", TypeCode.String), 
                (string correlationId, Parameters args) =>
                {
                    var name = args.GetAsString("name");
                    var res = _controller.Greeting(name);
                    return res;
                }
            );
    }
}

import (
    crun "github.com/pip-services3-gox/pip-services3-commons-gox/run"
    cvalid "github.com/pip-services3-gox/pip-services3-commons-gox/validate"
    ccmd "github.com/pip-services3-gox/pip-services3-commons-gox/commands"
)


// Command set
type FriendsCommandSet struct {
	*ccmd.CommandSet
	controller *HelloFriendController
}

func NewFriendsCommandSet(controller *HelloFriendController) *FriendsCommandSet {
	c := &FriendsCommandSet{
		CommandSet: ccmd.NewCommandSet(),
		controller: controller,
	}

	c.AddCommand(c.makeGreetingCommand())

	return c
}

func (c *FriendsCommandSet) makeGreetingCommand() ccmd.ICommand {
	return ccmd.NewCommand(
		"greeting",
		cvalid.NewObjectSchema().
			WithRequiredProperty("name", cvalid.NewFilterParamsSchema()),
		func(ctx context.Context, correllationId string, args *crun.Parameters) (result interface{}, err error) {
			name := args.GetAsString("name")
			return c.controller.Greeting(name), nil
		})
}
import 'package:pip_services3_commons/pip_services3_commons.dart';

class FriendsCommandSet extends CommandSet {
  HelloFriendController _controller;

  FriendsCommandSet(HelloFriendController controller)
      : _controller = controller,
        super() {
    addCommand(_makeGreeting());
  }

  ICommand _makeGreeting() {
    return Command('greeting', null,
        (String? correlationId, Parameters args) async {
      var name = args.getAsString('name');
      var res = _controller.greeting(name);
      return res;
    });
  }
}

from pip_services3_commons.commands import Command, CommandSet, ICommand
from pip_services3_commons.run import Parameters
from pip_services3_commons.validate import Schema, ObjectSchema
from pip_services3_commons.convert import TypeCode
from typing import Optional

class FriendsCommandSet(CommandSet):
    _controller: 'HelloFriendController'

    def __init__(self, controller):
        super().__init__()

        self._controller = controller

        self.add_command(self._make_greeting())

    def _make_greeting(self) -> ICommand:
        def handler(correlation_id: Optional[str], args: Parameters):
            name = args.get_as_string("name")
            res = self._controller.greeting(name)
            return res

        return Command(
            "greeting",
            ObjectSchema(True).with_required_property("name", TypeCode.String),
            handler
        )
Not available
Service for document 2

Once our command set has been defined, we create our commandable REST service by extending the CommandableHttpService class and we link it to our controller. This service checks for a YAML file in the configuration file. If not found, it builds the Swagger UI from the command set. In our example, the configuration file doesn’t include a path to a YAML file, and the Swagger UI is generated from the command set previously defined.

import { ConfigParams, Descriptor } from 'pip-services3-commons-nodex';
import { CommandableHttpService } from 'pip-services3-rpc-nodex';

class FriendCommandableHttpService1 extends CommandableHttpService {
    private _swaggerPath: string;

    public constructor() {
        super("commandable_hello_friend1");
        this._dependencyResolver.put('controller', new Descriptor("hello-friend", "controller", "*", "*", "*"));
    }

    public configure(config: ConfigParams): void {
        super.configure(config);

        // Swagger
        this._swaggerPath = config.getAsNullableString("swagger.path");
    }

    public register(): void {
        super.register();

        if (this._swaggerPath != null)
            this.registerOpenApiSpecFromFile(this._swaggerPath);
    }
}

using PipServices3.Commons.Config;
using PipServices3.Commons.Refer;
using PipServices3.Rpc.Services;

public class FriendCommandableHttpService1: CommandableHttpService
{
    private string _swaggerPath;

    public FriendCommandableHttpService1(): base("commandable_hello_friend1")
    {
        _dependencyResolver.Put("controller", new Descriptor("hello-friend", "controller", "*", "*", "*"));
    }

    public override void Configure(ConfigParams config)
    {
        base.Configure(config);

        // Swagger
        _swaggerPath = config.GetAsNullableString("swagger.path");
    }

    public override void Register()
    {
        base.Register();

        if (_swaggerPath != null)
            RegisterOpenApiSpecFromFile(_swaggerPath);
    }
}

import (
    refer "github.com/pip-services3-gox/pip-services3-commons-gox/refer"
    cservices "github.com/pip-services3-gox/pip-services3-rpc-gox/services"
    cconf "github.com/pip-services3-gox/pip-services3-commons-gox/config"
)

type FriendCommandableHttpService1 struct {
	*rpcservices.CommandableHttpService
	_swaggerPath string
}

func NewFriendCommandableHttpService1() *FriendCommandableHttpService1 {
	c := &FriendCommandableHttpService1{}
	c.CommandableHttpService = rpcservices.InheritCommandableHttpService(c, "commandable_hello_friend1")
	c.DependencyResolver.Put(context.Background(), "controller", crefer.NewDescriptor("hello-friend", "controller", "*", "*", "*"))
	return c
}

func (c *FriendCommandableHttpService1) Configure(ctx context.Context, config *cconf.ConfigParams) {
	c.RestService.Configure(ctx, config)

	// swagger
	c._swaggerPath, _ = config.GetAsNullableString("swagger.path")
}

func (c *FriendCommandableHttpService1) Register() {
	c.CommandableHttpService.Register()

	// swagger
	if c._swaggerPath != "" {
		c.RegisterOpenApiSpecFromFile(c._swaggerPath)
	}
}

import 'package:pip_services3_commons/pip_services3_commons.dart';
import 'package:pip_services3_rpc/pip_services3_rpc.dart';

class FriendCommandableHttpService1 extends CommandableHttpService {
  String? _swaggerPath;

  FriendCommandableHttpService1() : super('commandable_hello_friend1') {
    dependencyResolver.put(
        'controller', Descriptor('hello-friend', 'controller', '*', '*', '*'));
  }

  @override
  set config(ConfigParams? _config) {
    super.config = _config;

    // swagger
    _swaggerPath = config?.getAsNullableString('swagger.path');
  }

  @override
  void register() {
    super.register();

    if (_swaggerPath != null) registerOpenApiSpecFromFile(_swaggerPath!);
  }
}

from pip_services3_rpc.services import CommandableHttpService

class FriendCommandableHttpService1(CommandableHttpService):

    def __init__(self):
        super().__init__('commandable_hello_friend1')
        self._dependency_resolver.put('controller', Descriptor('hello-friend', 'controller', '*', '*', '*'))

        self._swagger_path = None
        
    def configure(self, config):
        super().configure(config)

        # Swagger
        self._swagger_path = config.get_as_nullable_string('swagger.path')

    def register(self):
        super().register()

        if self._swagger_path:
            self._register_open_api_spec_from_file(self._swagger_path)
Not available
Configuration for document 2

To be able to generate a Swagger UI, we need to set the swagger’s enable field to true. Besides, as we want to document the commands defined in the command set, we declare auto as true and we define the route field that will be part of the URL for the generated Swagger UI. The example below shows this configuration.

- descriptor: "hello-friend:service:commandable-http1:default:1.0"
  swagger:
    enable: true
    auto: true
    route: swagger
    name: Friends Service
    description: Commandable REST API - Automatic
Service for document 3

Similar to the previous one, this service builds the Swagger UI from the YAML file defined in the configuration file.

import { ConfigParams, Descriptor } from 'pip-services3-commons-nodex';
import { CommandableHttpService } from 'pip-services3-rpc-nodex';

class FriendCommandableHttpService2 extends CommandableHttpService {
    private _swaggerPath: string;

    public constructor() {
        super("commandable_hello_friend2");
        this._dependencyResolver.put('controller', new Descriptor("hello-friend", "controller", "*", "*", "*"));
    }

    public configure(config: ConfigParams): void {
        super.configure(config);

        // Swagger
        this._swaggerPath = config.getAsNullableString("swagger.path");
    }

    public register(): void {
        super.register();

        if (this._swaggerPath != null)
            this.registerOpenApiSpecFromFile(this._swaggerPath);
    }
}

using PipServices3.Rpc.Services;

public class FriendCommandableHttpService2 : CommandableHttpService
{
    private string _swaggerPath;

    public FriendCommandableHttpService2() : base("commandable_hello_friend2")
    {
        _dependencyResolver.Put("controller", new Descriptor("hello-friend", "controller", "*", "*", "*"));
    }

    public override void Configure(ConfigParams config)
    {
        base.Configure(config);

        // Swagger
        _swaggerPath = config.GetAsNullableString("swagger.path");
    }

    public override void Register()
    {
        base.Register();

        if (_swaggerPath != null)
            RegisterOpenApiSpecFromFile(_swaggerPath);
    }
}

import (
    refer "github.com/pip-services3-gox/pip-services3-commons-gox/refer"
    cservices "github.com/pip-services3-gox/pip-services3-rpc-gox/services"
    cconf "github.com/pip-services3-gox/pip-services3-commons-gox/config"
)

type FriendCommandableHttpService2 struct {
	rpcservices.CommandableHttpService
	_swaggerPath string
}

func NewFriendCommandableHttpService2() *FriendCommandableHttpService2 {
	c := &FriendCommandableHttpService2{}
	c.CommandableHttpService = *rpcservices.InheritCommandableHttpService(c, "commandable_hello_friend2")
	c.DependencyResolver.Put(context.Background(), "controller", crefer.NewDescriptor("hello-friend", "controller", "*", "*", "*"))
	return c
}

func (c *FriendCommandableHttpService2) Configure(ctx context.Context, config *cconf.ConfigParams) {
	c.RestService.Configure(ctx, config)

	// swagger
	c._swaggerPath, _ = config.GetAsNullableString("swagger.path")
}

func (c *FriendCommandableHttpService2) Register() {
	c.CommandableHttpService.Register()

	// swagger
	if c._swaggerPath != "" {
		c.RegisterOpenApiSpecFromFile(c._swaggerPath)
	}
}

import 'package:pip_services3_commons/pip_services3_commons.dart';
import 'package:pip_services3_rpc/pip_services3_rpc.dart';

class FriendCommandableHttpService2 extends CommandableHttpService {
  String? _swaggerPath;

  FriendCommandableHttpService2() : super('commandable_hello_friend2') {
    dependencyResolver.put(
        'controller', Descriptor('hello-friend', 'controller', '*', '*', '*'));
  }

  @override
  set config(ConfigParams? _config) {
    super.config = _config;

    // swagger
    _swaggerPath = config?.getAsNullableString('swagger.path');
  }

  @override
  void register() {
    super.register();

    if (_swaggerPath != null) registerOpenApiSpecFromFile(_swaggerPath!);
  }
}

from pip_services3_rpc.services import CommandableHttpService

class FriendCommandableHttpService2(CommandableHttpService):

    def __init__(self):
        super().__init__('commandable_hello_friend2')
        self._dependency_resolver.put('controller', Descriptor('hello-friend', 'controller', '*', '*', '*'))

        self._swagger_path = None
        
    def configure(self, config):
        super().configure(config)

        # Swagger
        self._swagger_path = config.get_as_nullable_string('swagger.path')

    def register(self):
        super().register()

        if self._swagger_path:
            self._register_open_api_spec_from_file(self._swagger_path)
Not available
Configuration for document 3

In this case, we declare a path to a YAML file containing the description for the Swagger UI. As a result, even though we have declared auto as true, the system will choose this file over the automatic generation.

- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: '../../../commandable_swagger.yml'
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'
Not available
Swagger yam file for document 3

Here, we use the YAML file below to describe the UI. As we can see, the main difference with the previous one is that we declare the HTTP method as POST instead of GET, and therefore, we define the requestBody as required.

openapi: '3.0.2'
info:
  title: 'Friends Service'
  description: 'Commandable REST API from YAM file'
  version: '1'
paths:
  /commandable_hello_friend/greeting:
    post:
      tags:
        - commandable_hello_friend
      requestBody:
        required: true
        description: Friend name
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string

      responses:
        201:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: 'object'

Containerization

Now that our REST services are defined, we want to create a process container to run them. For this, we need to define our factory of components and a class extending ProcessContainer. The following sections explain how to do this.

Factory

To create our factory of components, we extend the Factory class and register our REST and commandable REST services.

import { Descriptor } from 'pip-services3-commons-nodex';
import { Factory } from 'pip-services3-components-nodex';


class HelloFriendServiceFactory extends Factory {
    public constructor()
    {
        super();
        
        let HttpServiceDescriptor = new Descriptor("hello-friend", "service", "http", "*", "1.0");                          // View 1
        let CommandableHttpServiceDescriptor1 = new Descriptor("hello-friend", "service", "commandable-http1", "*", "1.0"); // View 2
        let CommandableHttpServiceDescriptor2 = new Descriptor("hello-friend", "service", "commandable-http2", "*", "1.0"); // View 2
        let ControllerDescriptor = new Descriptor("hello-friend", "controller", "default", "*", "1.0");                     // Controller

        this.registerAsType(HttpServiceDescriptor, HelloFriendRestService);                      // View 1
        this.registerAsType(CommandableHttpServiceDescriptor1, FriendCommandableHttpService1);   // View 2
        this.registerAsType(CommandableHttpServiceDescriptor2, FriendCommandableHttpService2);   // View 3
        this.registerAsType(ControllerDescriptor, HelloFriendController);                        // Controller
    }
}
    
using PipServices3.Components.Build;
using PipServices3.Commons.Refer;


public class HelloFriendServiceFactory: Factory
{
    public HelloFriendServiceFactory(): base()
    {
        var HttpServiceDescriptor = new Descriptor("hello-friend", "service", "http", "*", "1.0");                          // View 1
        var CommandableHttpServiceDescriptor1 = new Descriptor("hello-friend", "service", "commandable-http1", "*", "1.0"); // View 2
        var CommandableHttpServiceDescriptor2 = new Descriptor("hello-friend", "service", "commandable-http2", "*", "1.0"); // View 2
        var ControllerDescriptor = new Descriptor("hello-friend", "controller", "default", "*", "1.0");                     // Controller

        RegisterAsType(HttpServiceDescriptor, typeof(HelloFriendRestService));                      // View 1
        RegisterAsType(CommandableHttpServiceDescriptor1, typeof(FriendCommandableHttpService1));   // View 2
        RegisterAsType(CommandableHttpServiceDescriptor2, typeof(FriendCommandableHttpService2));   // View 3
        RegisterAsType(ControllerDescriptor, typeof(HelloFriendController));                        // Controller
    }
}

        
import (
    cbuild "github.com/pip-services3-gox/pip-services3-components-gox/build"
    cref "github.com/pip-services3-gox/pip-services3-commons-gox/refer"
)

type HelloFriendServiceFactory struct {
	*cbuild.Factory
}

func NewHelloFriendServiceFactory() *HelloFriendServiceFactory {
	c := &HelloFriendServiceFactory{
		Factory: cbuild.NewFactory(),
	}

	HttpServiceDescriptor := crefer.NewDescriptor("hello-friend", "service", "http", "*", "1.0")                          // View 1
	CommandableHttpServiceDescriptor1 := crefer.NewDescriptor("hello-friend", "service", "commandable-http1", "*", "1.0") // View 2
	CommandableHttpServiceDescriptor2 := crefer.NewDescriptor("hello-friend", "service", "commandable-http2", "*", "1.0") // View 2
	ControllerDescriptor := crefer.NewDescriptor("hello-friend", "controller", "default", "*", "1.0")                     // Controller

	c.RegisterType(HttpServiceDescriptor, NewHelloFriendRestService)                    // View 1
	c.RegisterType(CommandableHttpServiceDescriptor1, NewFriendCommandableHttpService1) // View 2
	c.RegisterType(CommandableHttpServiceDescriptor2, NewFriendCommandableHttpService2) // View 3
	c.RegisterType(ControllerDescriptor, NewHelloFriendController)                      // Controller

	return c
}

    
import 'package:pip_services3_commons/pip_services3_commons.dart';
import 'package:pip_services3_components/pip_services3_components.dart';


class HelloFriendServiceFactory extends Factory {
  HelloFriendServiceFactory() : super() {
    var HttpServiceDescriptor =
        Descriptor('hello-friend', 'service', 'http', '*', '1.0'); // View 1
    var CommandableHttpServiceDescriptor1 = Descriptor(
        'hello-friend', 'service', 'commandable-http1', '*', '1.0'); // View 2
    var CommandableHttpServiceDescriptor2 = Descriptor(
        'hello-friend', 'service', 'commandable-http2', '*', '1.0'); // View 2
    var ControllerDescriptor = Descriptor(
        'hello-friend', 'controller', 'default', '*', '1.0'); // Controller

    registerAsType(HttpServiceDescriptor, HelloFriendRestService); // View 1
    registerAsType(CommandableHttpServiceDescriptor1,
        FriendCommandableHttpService1); // View 2
    registerAsType(CommandableHttpServiceDescriptor2,
        FriendCommandableHttpService2); // View 3
    registerAsType(ControllerDescriptor, HelloFriendController); // Controller
  }
}
    
from pip_services3_commons.refer import Descriptor
from pip_services3_components.build import Factory


class HelloFriendServiceFactory(Factory):
    def __init__(self):
        super(HelloFriendServiceFactory, self).__init__()

        HttpServiceDescriptor = Descriptor('hello-friend', 'service', 'http', '*', '1.0')                          # View 1
        CommandableHttpServiceDescriptor1 = Descriptor('hello-friend', 'service', 'commandable-http1', '*', '1.0') # View 2
        CommandableHttpServiceDescriptor2 = Descriptor('hello-friend', 'service', 'commandable-http2', '*', '1.0') # View 2
        ControllerDescriptor = Descriptor('hello-friend', 'controller', 'default', '*', '1.0')                     # Controller
                                                                                
            
        self.register_as_type(HttpServiceDescriptor, HelloFriendRestService)                       # View 1
        self.register_as_type(CommandableHttpServiceDescriptor1, FriendCommandableHttpService1)    # View 2
        self.register_as_type(CommandableHttpServiceDescriptor2, FriendCommandableHttpService2)    # View 3
        self.register_as_type(ControllerDescriptor, HelloFriendController)                         # Controller
        
Not available
Process container

Once we have our factory, we define our process container by extending the ProcessContainer class and adding the factories for the services and Swagger. Our code will look something like this:

import { DefaultSwaggerFactory } from 'pip-services3-swagger-nodex';
import { DefaultRpcFactory } from 'pip-services3-rpc-nodex';
import { ProcessContainer } from 'pip-services3-container-nodex';


class HelloFriendProcess extends ProcessContainer {
    public constructor() {
        super("hello-friend", "HelloFriend microservice");

        this._configPath = "./config.yml";
        this._factories.add(new HelloFriendServiceFactory());
        this._factories.add(new DefaultRpcFactory());
        this._factories.add(new DefaultSwaggerFactory());
    }
}

using PipServices3.Container;
using PipServices3.Rpc.Build;
using PipServices3.Swagger.Build;


public class HelloFriendProcess : ProcessContainer
{
    public HelloFriendProcess() : base("hello-friend", "HelloFriend microservice")
    {
        _configPath = "../../../config.yml";
        _factories.Add(new HelloFriendServiceFactory());
        _factories.Add(new DefaultRpcFactory());
        _factories.Add(new DefaultSwaggerFactory());
    }
}

import (
    cproc "github.com/pip-services3-gox/pip-services3-container-gox/container"
	rbuild "github.com/pip-services3-gox/pip-services3-rpc-gox/build"
    sbuild "github.com/pip-services3-gox/pip-services3-swagger-gox/build"
)


type HelloFriendProcess struct {
	*cproc.ProcessContainer
}

func NewHelloFriendProcess() *HelloFriendProcess {
	c := &HelloFriendProcess{
		ProcessContainer: cproc.NewProcessContainer("hello-friend", "HelloFriend microservice"),
	}

	c.SetConfigPath("./config.yml")

	c.AddFactory(NewHelloFriendServiceFactory())
	c.AddFactory(rbuild.NewDefaultRpcFactory())
	c.AddFactory(cswagger.NewDefaultSwaggerFactory())

	return c
}


import 'package:pip_services3_container/pip_services3_container.dart';
import 'package:pip_services3_rpc/pip_services3_rpc.dart';
import 'package:pip_services3_swagger/pip_services3_swagger.dart';


class HelloFriendProcess extends ProcessContainer {
  HelloFriendProcess() : super('hello-friend', 'HelloFriend microservice') {
    configPath = './config.yml';
    factories.add(HelloFriendServiceFactory());
    factories.add(DefaultRpcFactory());
    factories.add(DefaultSwaggerFactory());
  }
}

from pip_services3_container.ProcessContainer import ProcessContainer
from pip_services3_rpc.build import DefaultRpcFactory
from pip_services3_swagger.build.DefaultSwaggerFactory import DefaultSwaggerFactory



class HelloFriendProcess(ProcessContainer):

    def __init__(self):
        super(HelloFriendProcess, self).__init__('hello-friend', 'HelloFriend microservice')
        self._config_path = './configV6.yml'
        self._factories.add(HelloFriendServiceFactory())
        self._factories.add(DefaultRpcFactory())
        self._factories.add(DefaultSwaggerFactory())
Not available

Runner

After our components are defined, we can run our app by invoking the run method from our process container.

export async function main() {
    try {
        let proc = new HelloFriendProcess();
        proc.run(process.argv);
    } catch (ex) {
        console.error(ex);
    }
}

class Program
{
    static void Main(string[] args)
    {
        try
        {
            var task = (new HelloFriendProcess()).RunAsync(args);
            task.Wait();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
    }
}

import (
    "os"
)

func main() {
	proc := NewHelloFriendProcess()
	proc.Run(context.Background(), os.Environ())
}

void main(List<String> argument) {
  try {
    var proc = HelloFriendProcess();
    proc.run(argument);
  } catch (ex) {
    print(ex);
  }
}

if __name__ == '__main__':
    runner = HelloFriendProcess()
    print("run")
    try:
        runner.run()
    except Exception as ex:
        print(ex)
Not available

And, after executing our code, we will see the following messages on our console:

figure 1

Results

To see the generated Swagger UIs, we can use the following URL:

http://localhost:8080/swagger/index.html

General Interface

The generated Swagger UI presents a drop-down menu that can be used to select any of the cases defined in this exercise.

figure 2

Document 1: REST service

If we select the hello_friend option, we will see a UI that presents all the information defined in the Swagger YAML file.

figure 3

Document 2: Commandable REST service

Alternatively, if we choose the commandable_hello_friend1 option, we will be presented by a UI showing the information automatically generated from the command set.

figure 4

Document 3: Commandable REST service.

Finally, if we select commandable_hello_friend2, we get a similar UI but generated from our YAML file.

figure 5

Final code

In this section, we show the complete code and the corresponding configuration YAML file.

swagger.py
import { 
    Command, CommandSet, ConfigParams, 
    Descriptor, ICommand, IReferences, 
    ObjectSchema, TypeCode, Parameters, ICommandable, IConfigurable

} from 'pip-services3-commons-nodex';

import { CommandableHttpService, DefaultRpcFactory, RestService } from 'pip-services3-rpc-nodex';

import { DefaultSwaggerFactory } from 'pip-services3-swagger-nodex';
import { ProcessContainer } from 'pip-services3-container-nodex';
import { Factory } from 'pip-services3-components-nodex';


export async function main() {
    // Runner
    try {
        let proc = new HelloFriendProcess();
        proc.run(process.argv);
    } catch (ex) {
        console.error(ex);
    }
}

// REST service (Swagger UI from YAML file)

class HelloFriendRestService extends RestService {
    private _controller: HelloFriendController;

    // swagger
    private _swaggerContent: string;
    private _swaggerPath: string;

    public constructor() {
        super();
        this._baseRoute = "/hello_friend";

        let controllerDescriptor = new Descriptor("hello-friend", "controller", "*", "*", "1.0");
        this._dependencyResolver.put("controller", controllerDescriptor);
    }

    public configure(config: ConfigParams): void {
        super.configure(config);

        // swagger
        this._swaggerContent = config.getAsNullableString("swagger.content");
        this._swaggerPath = config.getAsNullableString("swagger.path");
    }

    public setReferences(references: IReferences) {
        super.setReferences(references);
        this._controller = this._dependencyResolver.getOneRequired<HelloFriendController>("controller");
    }

    public register(): void {
        this.registerRoute("GET", "/greeting", null, this.greeting);

        // swagger
        if (this._swaggerContent != null)
            this.registerOpenApiSpec(this._swaggerContent);

        if (this._swaggerPath != null)
            this.registerOpenApiSpecFromFile(this._swaggerPath);
    }

    public async greeting(req: any, res: any): Promise<void> {
        let name = req.query.name;
        let result = this._controller.greeting(name);

        this.sendResult(req, res, result);
    }
}

// Command set 

class FriendsCommandSet extends CommandSet {
    private _controller: HelloFriendController;

    public constructor(controller: HelloFriendController) {
        super();

        this._controller = controller;

        this.addCommand(this.makeGreeting());
    }

    private makeGreeting(): ICommand {
        return new Command('greeeting', 
            new ObjectSchema(true).withRequiredProperty('name', TypeCode.String), 
            async (correlationId: string, args: Parameters) =>
            {
                let name = args.getAsString("name");
                let res = this._controller.greeting(name);
                return res;
            }
        );
    }
}

// Commandable REST service (Swagger UI automatically generated from command set)

class FriendCommandableHttpService1 extends CommandableHttpService {
    private _swaggerPath: string;

    public constructor() {
        super("commandable_hello_friend1");
        this._dependencyResolver.put('controller', new Descriptor("hello-friend", "controller", "*", "*", "*"));
    }

    public configure(config: ConfigParams): void {
        super.configure(config);

        // Swagger
        this._swaggerPath = config.getAsNullableString("swagger.path");
    }

    public register(): void {
        super.register();

        if (this._swaggerPath != null)
            this.registerOpenApiSpecFromFile(this._swaggerPath);
    }
}


// Commandable REST service (Swagger UI generated from YAML file)  

class FriendCommandableHttpService2 extends CommandableHttpService {
    private _swaggerPath: string;

    public constructor() {
        super("commandable_hello_friend2");
        this._dependencyResolver.put('controller', new Descriptor("hello-friend", "controller", "*", "*", "*"));
    }

    public configure(config: ConfigParams): void {
        super.configure(config);

        // Swagger
        this._swaggerPath = config.getAsNullableString("swagger.path");
    }

    public register(): void {
        super.register();

        if (this._swaggerPath != null)
            this.registerOpenApiSpecFromFile(this._swaggerPath);
    }
}

// Controller

class HelloFriendController implements IConfigurable, ICommandable {
    private defaultName: string;
    private commandSet: FriendsCommandSet;

    public constructor() {
        this.defaultName = "Pip User";
    }
    
    public configure(config: ConfigParams): void {
        this.defaultName = config.getAsStringWithDefault("default_name", this.defaultName);
    }

    public getCommandSet(): CommandSet {
        if (this.commandSet == null)
            this.commandSet = new FriendsCommandSet(this);

        return this.commandSet;
    }

    public greeting(name: string): string {
        return "Hello " + name ?? this.defaultName + " !"; 
    }
}


// Factory

class HelloFriendServiceFactory extends Factory {
    public constructor()
    {
        super();
        
        let HttpServiceDescriptor = new Descriptor("hello-friend", "service", "http", "*", "1.0");                          // View 1
        let CommandableHttpServiceDescriptor1 = new Descriptor("hello-friend", "service", "commandable-http1", "*", "1.0"); // View 2
        let CommandableHttpServiceDescriptor2 = new Descriptor("hello-friend", "service", "commandable-http2", "*", "1.0"); // View 2
        let ControllerDescriptor = new Descriptor("hello-friend", "controller", "default", "*", "1.0");                     // Controller

        this.registerAsType(HttpServiceDescriptor, HelloFriendRestService);                      // View 1
        this.registerAsType(CommandableHttpServiceDescriptor1, FriendCommandableHttpService1);   // View 2
        this.registerAsType(CommandableHttpServiceDescriptor2, FriendCommandableHttpService2);   // View 3
        this.registerAsType(ControllerDescriptor, HelloFriendController);                        // Controller
    }
}

// Container

class HelloFriendProcess extends ProcessContainer {
    public constructor() {
        super("hello-friend", "HelloFriend microservice");

        this._configPath = "./config.yml";
        this._factories.add(new HelloFriendServiceFactory());
        this._factories.add(new DefaultRpcFactory());
        this._factories.add(new DefaultSwaggerFactory());
    }
}


using System;
using System.Threading.Tasks;

using PipServices3.Commons.Config;
using PipServices3.Commons.Refer;
using PipServices3.Rpc.Services;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using PipServices3.Commons.Commands;
using PipServices3.Commons.Validate;
using PipServices3.Commons.Run;
using PipServices3.Components.Build;
using PipServices3.Container;
using PipServices3.Rpc.Build;
using PipServices3.Swagger.Build;

namespace ExampleApp
{
    class Program
    {
        
        static void Main(string[] args)
        {
            // Runner
            try
            {
                var task = (new HelloFriendProcess()).RunAsync(args);
                task.Wait();
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
            }

        }
    }

    // REST service (Swagger UI from YAML file)

    public class HelloFriendRestService: RestService
    {
        private HelloFriendController _controller;

        // swagger
        private string _swaggerContent;
        private string _swaggerPath;

        public HelloFriendRestService(): base()
        {
            _baseRoute = "/hello_friend";

            var controllerDescriptor = new Descriptor("hello-friend", "controller", "*", "*", "1.0");
            _dependencyResolver.Put("controller", controllerDescriptor);

        }

        public override void Configure(ConfigParams config)
        {
            base.Configure(config);

            // swagger
            _swaggerContent = config.GetAsNullableString("swagger.content");
            _swaggerPath = config.GetAsNullableString("swagger.path");
        }

        public override void SetReferences(IReferences references)
        {
            base.SetReferences(references);
            _controller = _dependencyResolver.GetOneRequired<HelloFriendController>("controller");
        }

        public override void Register()
        {
            RegisterRoute("GET", "/greeting", this.Greeting);

            // swagger
            if (_swaggerContent != null)
                RegisterOpenApiSpec(_swaggerContent);

            if (_swaggerPath != null)
                RegisterOpenApiSpecFromFile(_swaggerPath);
        }

        public async Task Greeting(HttpRequest req, HttpResponse res, RouteData routeData)
        {
            var name = req.Query["name"];
            var result = _controller.Greeting(name);

            await SendResultAsync(res, result);
        }
    }

    // Command set 

    public class FriendsCommandSet : CommandSet
    {
        private HelloFriendController _controller;

        public FriendsCommandSet(HelloFriendController controller) : base()
        {
            _controller = controller;

            AddCommand(MakeGreeting());
        }

        private ICommand MakeGreeting()
        {
            return new Command("greeting",
                    new ObjectSchema().WithRequiredProperty("name", TypeCode.String),
                    async (string correlationId, Parameters args) =>
                    {
                        var name = args.GetAsString("name");
                        var res = _controller.Greeting(name);
                        return res;
                    }
                );
        }
    }

    // Commandable REST service (Swagger UI automatically generated from command set)

    public class FriendCommandableHttpService1 : CommandableHttpService
    {
        private string _swaggerPath;

        public FriendCommandableHttpService1() : base("commandable_hello_friend1")
        {
            _dependencyResolver.Put("controller", new Descriptor("hello-friend", "controller", "*", "*", "*"));
        }

        public override void Configure(ConfigParams config)
        {
            base.Configure(config);

            // Swagger
            _swaggerPath = config.GetAsNullableString("swagger.path");
        }

        public override void Register()
        {
            base.Register();

            if (_swaggerPath != null)
                RegisterOpenApiSpecFromFile(_swaggerPath);
        }
    }

    // Commandable REST service (Swagger UI generated from YAML file)  

    public class FriendCommandableHttpService2 : CommandableHttpService
    {
        private string _swaggerPath;

        public FriendCommandableHttpService2() : base("commandable_hello_friend2")
        {
            _dependencyResolver.Put("controller", new Descriptor("hello-friend", "controller", "*", "*", "*"));
        }

        public override void Configure(ConfigParams config)
        {
            base.Configure(config);

            // Swagger
            _swaggerPath = config.GetAsNullableString("swagger.path");
        }

        public override void Register()
        {
            base.Register();

            if (_swaggerPath != null)
                RegisterOpenApiSpecFromFile(_swaggerPath);
        }
    }

    // Controller

    public class HelloFriendController : IConfigurable, ICommandable
    {
        private string defaultName;
        private FriendsCommandSet commandSet;

        public HelloFriendController()
        {
            defaultName = "Pip User";
        }

        public void Configure(ConfigParams config)
        {
            defaultName = config.GetAsStringWithDefault("default_name", defaultName);
        }

        public CommandSet GetCommandSet()
        {
            if (commandSet == null)
                commandSet = new FriendsCommandSet(this);

            return commandSet;
        }

        public string Greeting(string name)
        {
            return "Hello " + name ?? defaultName + " !";
        }
    }

    // Factory

    public class HelloFriendServiceFactory : Factory
    {
        public HelloFriendServiceFactory() : base()
        {
            var HttpServiceDescriptor = new Descriptor("hello-friend", "service", "http", "*", "1.0");                          // View 1
            var CommandableHttpServiceDescriptor1 = new Descriptor("hello-friend", "service", "commandable-http1", "*", "1.0"); // View 2
            var CommandableHttpServiceDescriptor2 = new Descriptor("hello-friend", "service", "commandable-http2", "*", "1.0"); // View 2
            var ControllerDescriptor = new Descriptor("hello-friend", "controller", "default", "*", "1.0");                     // Controller

            RegisterAsType(HttpServiceDescriptor, typeof(HelloFriendRestService));                      // View 1
            RegisterAsType(CommandableHttpServiceDescriptor1, typeof(FriendCommandableHttpService1));   // View 2
            RegisterAsType(CommandableHttpServiceDescriptor2, typeof(FriendCommandableHttpService2));   // View 3
            RegisterAsType(ControllerDescriptor, typeof(HelloFriendController));                        // Controller
        }
    }

    // Container

    public class HelloFriendProcess : ProcessContainer
    {
        public HelloFriendProcess() : base("hello-friend", "HelloFriend microservice")
        {
            _configPath = "../../../config.yml";
            _factories.Add(new HelloFriendServiceFactory());
            _factories.Add(new DefaultRpcFactory());
            _factories.Add(new DefaultSwaggerFactory());
        }
    }
}

package main

import (
	"context"
	"net/http"
	"os"

	ccmd "github.com/pip-services3-gox/pip-services3-commons-gox/commands"
	cconf "github.com/pip-services3-gox/pip-services3-commons-gox/config"
	crefer "github.com/pip-services3-gox/pip-services3-commons-gox/refer"
	crun "github.com/pip-services3-gox/pip-services3-commons-gox/run"
	cvalid "github.com/pip-services3-gox/pip-services3-commons-gox/validate"
	cbuild "github.com/pip-services3-gox/pip-services3-components-gox/build"
	cproc "github.com/pip-services3-gox/pip-services3-container-gox/container"
	rbuild "github.com/pip-services3-gox/pip-services3-rpc-gox/build"
	rpcservices "github.com/pip-services3-gox/pip-services3-rpc-gox/services"
	cswagger "github.com/pip-services3-gox/pip-services3-swagger-gox/build"
)

// Runner
func main() {
	proc := NewHelloFriendProcess()
	proc.Run(context.Background(), os.Environ())
}

// REST service (Swagger UI from YAML file)

type HelloFriendRestService struct {
	*rpcservices.RestService

	_swaggerContent string
	_swaggerPath    string
	_controller     *HelloFriendController
}

func NewHelloFriendRestService() *HelloFriendRestService {
	c := &HelloFriendRestService{}
	c.RestService = rpcservices.InheritRestService(c)
	c.BaseRoute = "/hello_friend"

	controllerDescriptor := crefer.NewDescriptor("hello-friend", "controller", "*", "*", "1.0")
	c.DependencyResolver.Put(context.Background(), "controller", controllerDescriptor)
	return c
}

func (c *HelloFriendRestService) Configure(ctx context.Context, config *cconf.ConfigParams) {
	c.RestService.Configure(context.Background(), config)

	// swagger
	c._swaggerContent, _ = config.GetAsNullableString("swagger.content")
	c._swaggerPath, _ = config.GetAsNullableString("swagger.path")
}

func (c *HelloFriendRestService) SetReferences(ctx context.Context, references crefer.IReferences) {
	c.RestService.SetReferences(ctx, references)
	depRes, depErr := c.DependencyResolver.GetOneRequired("controller")
	if depErr == nil && depRes != nil {
		c._controller = depRes.(*HelloFriendController)
	}
}

func (c *HelloFriendRestService) greeting(res http.ResponseWriter, req *http.Request) {
	// vars := mux.Vars(req)

	name := req.URL.Query().Get("message")
	// message := vars["name"]
	result := c._controller.Greeting(name)

	c.SendResult(res, req, result, nil)
}

func (c *HelloFriendRestService) Register() {
	c.RegisterRoute("GET", "/greeting", nil, c.greeting)

	// swagger
	if c._swaggerContent != "" {
		c.RegisterOpenApiSpec(c._swaggerContent)
	}

	if c._swaggerPath != "" {
		c.RegisterOpenApiSpecFromFile(c._swaggerPath)
	}
}

// Command set
type FriendsCommandSet struct {
	*ccmd.CommandSet
	controller *HelloFriendController
}

func NewFriendsCommandSet(controller *HelloFriendController) *FriendsCommandSet {
	c := &FriendsCommandSet{
		CommandSet: ccmd.NewCommandSet(),
		controller: controller,
	}

	c.AddCommand(c.makeGreetingCommand())

	return c
}

func (c *FriendsCommandSet) makeGreetingCommand() ccmd.ICommand {
	return ccmd.NewCommand(
		"greeting",
		cvalid.NewObjectSchema().
			WithRequiredProperty("name", cvalid.NewFilterParamsSchema()),
		func(ctx context.Context, correllationId string, args *crun.Parameters) (result interface{}, err error) {
			name := args.GetAsString("name")
			return c.controller.Greeting(name), nil
		})
}

// Commandable REST service (Swagger UI automatically generated from command set)

type FriendCommandableHttpService1 struct {
	*rpcservices.CommandableHttpService
	_swaggerPath string
}

func NewFriendCommandableHttpService1() *FriendCommandableHttpService1 {
	c := &FriendCommandableHttpService1{}
	c.CommandableHttpService = rpcservices.InheritCommandableHttpService(c, "commandable_hello_friend1")
	c.DependencyResolver.Put(context.Background(), "controller", crefer.NewDescriptor("hello-friend", "controller", "*", "*", "*"))
	return c
}

func (c *FriendCommandableHttpService1) Configure(ctx context.Context, config *cconf.ConfigParams) {
	c.RestService.Configure(ctx, config)

	// swagger
	c._swaggerPath, _ = config.GetAsNullableString("swagger.path")
}

func (c *FriendCommandableHttpService1) Register() {
	c.CommandableHttpService.Register()

	// swagger
	if c._swaggerPath != "" {
		c.RegisterOpenApiSpecFromFile(c._swaggerPath)
	}
}

// Commandable REST service (Swagger UI generated from YAML file)

type FriendCommandableHttpService2 struct {
	rpcservices.CommandableHttpService
	_swaggerPath string
}

func NewFriendCommandableHttpService2() *FriendCommandableHttpService2 {
	c := &FriendCommandableHttpService2{}
	c.CommandableHttpService = *rpcservices.InheritCommandableHttpService(c, "commandable_hello_friend2")
	c.DependencyResolver.Put(context.Background(), "controller", crefer.NewDescriptor("hello-friend", "controller", "*", "*", "*"))
	return c
}

func (c *FriendCommandableHttpService2) Configure(ctx context.Context, config *cconf.ConfigParams) {
	c.RestService.Configure(ctx, config)

	// swagger
	c._swaggerPath, _ = config.GetAsNullableString("swagger.path")
}

func (c *FriendCommandableHttpService2) Register() {
	c.CommandableHttpService.Register()

	// swagger
	if c._swaggerPath != "" {
		c.RegisterOpenApiSpecFromFile(c._swaggerPath)
	}
}

// Controller

type HelloFriendController struct {
	commandSet  *FriendsCommandSet
	defaultName string
}

func NewHelloFriendController() *HelloFriendController {
	c := &HelloFriendController{defaultName: "Pip User"}
	return c
}

func (c *HelloFriendController) Configure(config *cconf.ConfigParams) {
	c.defaultName = config.GetAsStringWithDefault("default_name", c.defaultName)
}

func (c *HelloFriendController) GetCommandSet() *ccmd.CommandSet {
	if c.commandSet == nil {
		c.commandSet = NewFriendsCommandSet(c)
	}
	return c.commandSet.CommandSet
}

func (c *HelloFriendController) Greeting(name string) string {
	if name != "" {
		return "Hello " + name + " !"
	} else {
		return "Hello " + c.defaultName + " !"
	}
}

// Factory

type HelloFriendServiceFactory struct {
	*cbuild.Factory
}

func NewHelloFriendServiceFactory() *HelloFriendServiceFactory {
	c := &HelloFriendServiceFactory{
		Factory: cbuild.NewFactory(),
	}

	HttpServiceDescriptor := crefer.NewDescriptor("hello-friend", "service", "http", "*", "1.0")                          // View 1
	CommandableHttpServiceDescriptor1 := crefer.NewDescriptor("hello-friend", "service", "commandable-http1", "*", "1.0") // View 2
	CommandableHttpServiceDescriptor2 := crefer.NewDescriptor("hello-friend", "service", "commandable-http2", "*", "1.0") // View 2
	ControllerDescriptor := crefer.NewDescriptor("hello-friend", "controller", "default", "*", "1.0")                     // Controller

	c.RegisterType(HttpServiceDescriptor, NewHelloFriendRestService)                    // View 1
	c.RegisterType(CommandableHttpServiceDescriptor1, NewFriendCommandableHttpService1) // View 2
	c.RegisterType(CommandableHttpServiceDescriptor2, NewFriendCommandableHttpService2) // View 3
	c.RegisterType(ControllerDescriptor, NewHelloFriendController)                      // Controller

	return c
}

// Container

type HelloFriendProcess struct {
	*cproc.ProcessContainer
}

func NewHelloFriendProcess() *HelloFriendProcess {
	c := &HelloFriendProcess{
		ProcessContainer: cproc.NewProcessContainer("hello-friend", "HelloFriend microservice"),
	}

	c.SetConfigPath("./config.yml")

	c.AddFactory(NewHelloFriendServiceFactory())
	c.AddFactory(rbuild.NewDefaultRpcFactory())
	c.AddFactory(cswagger.NewDefaultSwaggerFactory())

	return c
}

import 'dart:async';

import 'package:pip_services3_commons/pip_services3_commons.dart';
import 'package:pip_services3_components/pip_services3_components.dart';
import 'package:pip_services3_container/pip_services3_container.dart';
import 'package:pip_services3_rpc/pip_services3_rpc.dart';
import 'package:pip_services3_swagger/pip_services3_swagger.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_router/shelf_router.dart';

void main(List<String> argument) {
  // Runner
  try {
    var proc = HelloFriendProcess();
    proc.run(argument);
  } catch (ex) {
    print(ex);
  }
}

// REST service (Swagger UI from YAML file)

class HelloFriendRestService extends RestService {
  HelloFriendController? _controller;

  String? _swaggerContent;
  String? _swaggerPath;

  HelloFriendRestService() : super() {
    baseRoute = '/hello_friend';

    var controllerDescriptor =
        Descriptor('hello-friend', 'controller', '*', '*', '1.0');
    dependencyResolver.put('controller', controllerDescriptor);
  }

  @override
  void configure(ConfigParams config) {
    super.configure(config);

    // swagger
    _swaggerContent = config.getAsNullableString('swagger.content');
    _swaggerPath = config.getAsNullableString('swagger.path');
  }

  @override
  void setReferences(IReferences references) {
    super.setReferences(references);

    _controller =
        dependencyResolver.getOneRequired<HelloFriendController>('controller');
  }

  @override
  void register() {
    registerRoute('get', '/greeting', null, _greeting);

    // swagger
    if (_swaggerContent != null) {
      registerOpenApiSpec_(_swaggerContent!);
    }

    if (_swaggerPath != null) {
      registerOpenApiSpecFromFile(_swaggerPath!);
    }
  }

  FutureOr<Response> _greeting(Request req) {
    var name = req.params['name'];
    var result = _controller!.greeting(name);

    return sendResult(req, result);
  }
}

// Command set

class FriendsCommandSet extends CommandSet {
  HelloFriendController _controller;

  FriendsCommandSet(HelloFriendController controller)
      : _controller = controller,
        super() {
    addCommand(_makeGreeting());
  }

  ICommand _makeGreeting() {
    return Command('greeting', null,
        (String? correlationId, Parameters args) async {
      var name = args.getAsString('name');
      var res = _controller.greeting(name);
      return res;
    });
  }
}

// Commandable REST service (Swagger UI automatically generated from command set)

class FriendCommandableHttpService1 extends CommandableHttpService {
  String? _swaggerPath;

  FriendCommandableHttpService1() : super('commandable_hello_friend1') {
    dependencyResolver.put(
        'controller', Descriptor('hello-friend', 'controller', '*', '*', '*'));
  }

  @override
  set config(ConfigParams? _config) {
    super.config = _config;

    // swagger
    _swaggerPath = config?.getAsNullableString('swagger.path');
  }

  @override
  void register() {
    super.register();

    if (_swaggerPath != null) registerOpenApiSpecFromFile(_swaggerPath!);
  }
}

// Commandable REST service (Swagger UI generated from YAML file)

class FriendCommandableHttpService2 extends CommandableHttpService {
  String? _swaggerPath;

  FriendCommandableHttpService2() : super('commandable_hello_friend2') {
    dependencyResolver.put(
        'controller', Descriptor('hello-friend', 'controller', '*', '*', '*'));
  }

  @override
  set config(ConfigParams? _config) {
    super.config = _config;

    // swagger
    _swaggerPath = config?.getAsNullableString('swagger.path');
  }

  @override
  void register() {
    super.register();

    if (_swaggerPath != null) registerOpenApiSpecFromFile(_swaggerPath!);
  }
}

// Controller

class HelloFriendController implements IConfigurable, ICommandable {
  String defaultName;
  FriendsCommandSet? commandSet;

  HelloFriendController() : defaultName = 'Pip User';

  @override
  void configure(ConfigParams config) {
    defaultName = config.getAsStringWithDefault('default_name', defaultName);
  }

  @override
  CommandSet getCommandSet() {
    if (commandSet == null) commandSet = FriendsCommandSet(this);

    return commandSet!;
  }

  String greeting(String? name) {
    return 'Hello ' + (name ?? defaultName) + ' !';
  }
}

// Factory

class HelloFriendServiceFactory extends Factory {
  HelloFriendServiceFactory() : super() {
    var HttpServiceDescriptor =
        Descriptor('hello-friend', 'service', 'http', '*', '1.0'); // View 1
    var CommandableHttpServiceDescriptor1 = Descriptor(
        'hello-friend', 'service', 'commandable-http1', '*', '1.0'); // View 2
    var CommandableHttpServiceDescriptor2 = Descriptor(
        'hello-friend', 'service', 'commandable-http2', '*', '1.0'); // View 2
    var ControllerDescriptor = Descriptor(
        'hello-friend', 'controller', 'default', '*', '1.0'); // Controller

    registerAsType(HttpServiceDescriptor, HelloFriendRestService); // View 1
    registerAsType(CommandableHttpServiceDescriptor1,
        FriendCommandableHttpService1); // View 2
    registerAsType(CommandableHttpServiceDescriptor2,
        FriendCommandableHttpService2); // View 3
    registerAsType(ControllerDescriptor, HelloFriendController); // Controller
  }
}

// Container

class HelloFriendProcess extends ProcessContainer {
  HelloFriendProcess() : super('hello-friend', 'HelloFriend microservice') {
    configPath = './config.yml';
    factories.add(HelloFriendServiceFactory());
    factories.add(DefaultRpcFactory());
    factories.add(DefaultSwaggerFactory());
  }
}

from pip_services3_commons.refer import Descriptor
from pip_services3_commons.validate import Schema
from pip_services3_rpc.services import RestService

import bottle

# REST service (Swagger UI from YAML file)

class HelloFriendRestService(RestService):

    def __init__(self):
        super(HelloFriendRestService, self).__init__()

        self._base_route = "/hello_friend"

        ControllerDescriptor = Descriptor('hello-friend', 'controller', '*', '*', '1.0')
        self._dependency_resolver.put('controller', ControllerDescriptor)
        self._controller = None

        # Swagger
        self._swagger_content = None
        self._swagger_path = None

    def configure(self, config):
        super().configure(config)
        
        # Swagger
        self._swagger_content = config.get_as_nullable_string("swagger.content")
        self._swagger_path = config.get_as_nullable_string('swagger.path')

    def set_references(self, references):
        super(HelloFriendRestService, self).set_references(references)
        self._controller = self._dependency_resolver.get_one_required('controller')

    def register(self):
        self.register_route(method="GET", route="/greeting", schema=Schema(), handler=self.greeting)
        
        # Swagger
        if self._swagger_content:
            self._register_open_api_spec(self._swagger_content)

        if self._swagger_path:
            self._register_open_api_spec_from_file(self._swagger_path)

    def greeting(self):
        name = bottle.request.query.get('name')
        result = self._controller.greeting(name)
        return self.send_result(result)

# Command set    
    
from pip_services3_commons.commands import Command, CommandSet, ICommand
from pip_services3_commons.run import Parameters
from pip_services3_commons.validate import Schema, ObjectSchema
from pip_services3_commons.convert import TypeCode
from typing import Optional

class FriendsCommandSet(CommandSet):
    _controller: 'HelloFriendController'

    def __init__(self, controller):
        super().__init__()

        self._controller = controller
        self.add_command(self._make_greeting())

    def _make_greeting(self) -> ICommand:
        def handler(correlation_id: Optional[str], args: Parameters):
            name = args.get_as_string("name")
            res = self._controller.greeting(name)
            return res

        return Command(
            "greeting",
            ObjectSchema(True).with_required_property("name", TypeCode.String),
            handler
        )
    
# Commandable REST service (Swagger UI automatically generated from command set)
    
from pip_services3_rpc.services import CommandableHttpService

class FriendCommandableHttpService1(CommandableHttpService):

    def __init__(self):
        super().__init__('commandable_hello_friend1')
        self._dependency_resolver.put('controller', Descriptor('hello-friend', 'controller', '*', '*', '*'))

        self._swagger_path = None
        
    def configure(self, config):
        super().configure(config)

        # Swagger
        self._swagger_path = config.get_as_nullable_string('swagger.path')

    def register(self):
        super().register()
        
        if self._swagger_path:
            self._register_open_api_spec_from_file(self._swagger_path)

# Commandable REST service (Swagger UI generated from YAML file)            
            
from pip_services3_rpc.services import CommandableHttpService

class FriendCommandableHttpService2(CommandableHttpService):

    def __init__(self):
        super().__init__('commandable_hello_friend2')
        self._dependency_resolver.put('controller', Descriptor('hello-friend', 'controller', '*', '*', '*'))

        self._swagger_path = None
        
    def configure(self, config):
        super().configure(config)

        # Swagger
        self._swagger_path = config.get_as_nullable_string('swagger.path')

    def register(self):
        super().register()

        if self._swagger_path:
            self._register_open_api_spec_from_file(self._swagger_path)
            
# Controller
            
from pip_services3_commons.commands import ICommandable
from pip_services3_commons.config import IConfigurable

class HelloFriendController(IConfigurable, ICommandable): 
                                          
    __defaultName = None
    __command_set: 'FriendsCommandSet' = None
        
    def __init__(self):
        self.__defaultName = "Pip User"

    def configure(self, config):
        self.__defaultName = config.get_as_string_with_default("default_name", self.__defaultName)
        
    def get_command_set(self) -> CommandSet:
        if self.__command_set is None:
            self.__command_set = FriendsCommandSet(self)

        return self.__command_set

    def greeting(self, name):
        return f"Hello, {name if name else self.__defaultName} !"
    
from pip_services3_commons.refer import Descriptor
from pip_services3_components.build import Factory

# Factory

class HelloFriendServiceFactory(Factory):
    def __init__(self):
        super(HelloFriendServiceFactory, self).__init__()

        HttpServiceDescriptor = Descriptor('hello-friend', 'service', 'http', '*', '1.0')                          # View 1
        CommandableHttpServiceDescriptor1 = Descriptor('hello-friend', 'service', 'commandable-http1', '*', '1.0') # View 2
        CommandableHttpServiceDescriptor2 = Descriptor('hello-friend', 'service', 'commandable-http2', '*', '1.0') # View 2
        ControllerDescriptor = Descriptor('hello-friend', 'controller', 'default', '*', '1.0')                     # Controller
                                                                                
            
        self.register_as_type(HttpServiceDescriptor, HelloFriendRestService)                       # View 1
        self.register_as_type(CommandableHttpServiceDescriptor1, FriendCommandableHttpService1)    # View 2
        self.register_as_type(CommandableHttpServiceDescriptor2, FriendCommandableHttpService2)    # View 3
        self.register_as_type(ControllerDescriptor, HelloFriendController)                         # Controller
        
from pip_services3_container.ProcessContainer import ProcessContainer
from pip_services3_rpc.build import DefaultRpcFactory
from pip_services3_swagger.build.DefaultSwaggerFactory import DefaultSwaggerFactory

# Container

class HelloFriendProcess(ProcessContainer):

    def __init__(self):
        super(HelloFriendProcess, self).__init__('hello-friend', 'HelloFriend microservice')
        self._config_path = './config.yml'
        self._factories.add(HelloFriendServiceFactory())
        self._factories.add(DefaultRpcFactory())
        self._factories.add(DefaultSwaggerFactory())
        
# Runner        

if __name__ == '__main__':
    runner = HelloFriendProcess()
    print("run")
    try:
        runner.run()
    except Exception as ex:
        print(ex)

Not available
config.yaml
---
# Container context
- descriptor: "pip-services:context-info:default:default:1.0"
  name: "hello-friend"
  description: "HelloFriend microservice"

# Console logger
- descriptor: "pip-services:logger:console:default:1.0"
  level: "trace"

# Performance counter that post values to log
- descriptor: "pip-services:counters:log:default:1.0"

# Controller
- descriptor: "hello-friend:controller:default:default:1.0"
  default_name: "Friend"

# Shared HTTP Endpoint
- descriptor: "pip-services:endpoint:http:default:1.0"
  connection:
    protocol: http
    host: 0.0.0.0
    port: 8080

# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'


- descriptor: "hello-friend:service:commandable-http1:default:1.0"
  swagger:
    enable: true
    auto: true
    route: swagger
    name: Friends Service
    description: Commandable REST API - Automatic
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'

# Heartbeat service
- descriptor: "pip-services:heartbeat-service:http:default:1.0"

# Status service
- descriptor: "pip-services:status-service:http:default:1.0"

# Swagger service
- descriptor: "pip-services:swagger-service:http:default:1.0"
---
# Container context
- descriptor: "pip-services:context-info:default:default:1.0"
  name: "hello-friend"
  description: "HelloFriend microservice"

# Console logger
- descriptor: "pip-services:logger:console:default:1.0"
  level: "trace"

# Performance counter that post values to log
- descriptor: "pip-services:counters:log:default:1.0"

# Controller
- descriptor: "hello-friend:controller:default:default:1.0"
  default_name: "Friend"

# Shared HTTP Endpoint
- descriptor: "pip-services:endpoint:http:default:1.0"
  connection:
    protocol: http
    host: 0.0.0.0
    port: 8080

# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: '../../../rest_swagger.yml'


- descriptor: "hello-friend:service:commandable-http1:default:1.0"
  swagger:
    enable: true
    auto: true
    route: swagger
    name: Friends Service
    description: Commandable REST API - Automatic
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: '../../../commandable_swagger.yml'

# Heartbeat service
- descriptor: "pip-services:heartbeat-service:http:default:1.0"

# Status service
- descriptor: "pip-services:status-service:http:default:1.0"

# Swagger service
- descriptor: "pip-services:swagger-service:http:default:1.0"
---
# Container context
- descriptor: "pip-services:context-info:default:default:1.0"
  name: "hello-friend"
  description: "HelloFriend microservice"

# Console logger
- descriptor: "pip-services:logger:console:default:1.0"
  level: "trace"

# Performance counter that post values to log
- descriptor: "pip-services:counters:log:default:1.0"

# Controller
- descriptor: "hello-friend:controller:default:default:1.0"
  default_name: "Friend"

# Shared HTTP Endpoint
- descriptor: "pip-services:endpoint:http:default:1.0"
  connection:
    protocol: http
    host: 0.0.0.0
    port: 8080

# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'


- descriptor: "hello-friend:service:commandable-http1:default:1.0"
  swagger:
    enable: true
    auto: true
    route: swagger
    name: Friends Service
    description: Commandable REST API - Automatic
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'

# Heartbeat service
- descriptor: "pip-services:heartbeat-service:http:default:1.0"

# Status service
- descriptor: "pip-services:status-service:http:default:1.0"

# Swagger service
- descriptor: "pip-services:swagger-service:http:default:1.0"
---
# Container context
- descriptor: "pip-services:context-info:default:default:1.0"
  name: "hello-friend"
  description: "HelloFriend microservice"

# Console logger
- descriptor: "pip-services:logger:console:default:1.0"
  level: "trace"

# Performance counter that post values to log
- descriptor: "pip-services:counters:log:default:1.0"

# Controller
- descriptor: "hello-friend:controller:default:default:1.0"
  default_name: "Friend"

# Shared HTTP Endpoint
- descriptor: "pip-services:endpoint:http:default:1.0"
  connection:
    protocol: http
    host: 0.0.0.0
    port: 8080

# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'


- descriptor: "hello-friend:service:commandable-http1:default:1.0"
  swagger:
    enable: true
    auto: true
    route: swagger
    name: Friends Service
    description: Commandable REST API - Automatic
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'

# Heartbeat service
- descriptor: "pip-services:heartbeat-service:http:default:1.0"

# Status service
- descriptor: "pip-services:status-service:http:default:1.0"

# Swagger service
- descriptor: "pip-services:swagger-service:http:default:1.0"
---
# Container context
- descriptor: "pip-services:context-info:default:default:1.0"
  name: "hello-friend"
  description: "HelloFriend microservice"

# Console logger
- descriptor: "pip-services:logger:console:default:1.0"
  level: "trace"

# Performance counter that post values to log
- descriptor: "pip-services:counters:log:default:1.0"

# Controller
- descriptor: "hello-friend:controller:default:default:1.0"
  default_name: "Friend"

# Shared HTTP Endpoint
- descriptor: "pip-services:endpoint:http:default:1.0"
  connection:
    protocol: http
    host: 0.0.0.0
    port: 8080

# HTTP Service V1
- descriptor: "hello-friend:service:http:default:1.0"
  swagger:
    enable: true
    path: './rest_swagger.yml'


- descriptor: "hello-friend:service:commandable-http1:default:1.0"
  swagger:
    enable: true
    auto: true
    route: swagger
    name: Friends Service
    description: Commandable REST API - Automatic
- descriptor: "hello-friend:service:commandable-http2:default:1.0"
  swagger:
    enable: true
    auto: false
    route: swagger
    path: './commandable_swagger.yml'

# Heartbeat service
- descriptor: "pip-services:heartbeat-service:http:default:1.0"

# Status service
- descriptor: "pip-services:status-service:http:default:1.0"

# Swagger service
- descriptor: "pip-services:swagger-service:http:default:1.0"
Not available

Wrapping up

In this tutorial, we have seen how to create Swagger UIs from a REST service and a commandable REST service. First, we created a REST service that is Swagger enabled and obtained all the information necessary to create the UI from a YAML file. After that, we created a commandable REST service, which developed a UI from a set of commands or a YAML file. Finally, we created a process container used to run our app. Once run, our app produced Swagger UIs documenting the greeting method for each case.