Skip to content

Creating and Editing SWAGGER Specifications

OpenAPI 3.0 Specification

SWAGGER (now know as Open API Specification or sometimes abbreviated as OAS3 or OAPI), allows you to describe the structure of your APIs so that machines and humans can read them.

The ability of APIs to describe their own structure is the root of all awesomeness in Swagger. Why is it so great? Well, by reading your API’s structure, you can automatically build beautiful and interactive API documentation with SWAGGER UI. Accelerator can also automatically generate client/server libraries/programs for your API in many languages (now including RPGLE using rest4i), and explore other possibilities like automated testing.

API specifications can be written in YAML or JSON. The format is easy to learn and readable to both humans and machines. The complete OpenAPI Specification can be found on GitHub: OpenAPI 3.0 Specification

MDRest4i uses the SWAGGER definition passed as a request body to the MDRSDK api on the IBM i, to generate RPGLE and COBOL code for Consumers and Providers.

SWAGGER extensions

SWAGGER extensions (JSON objects prefixed with an “x-”) are added to each SWAGGER specification to facilitate some of the code generation processes. Subfields inside an x- extension need not have the x- prefix

These are listed below, with the swagger key or path(path as in JSON or YAML path not REST API path) they are extending. For example x-mdrinfo appears in the "/info" of the swagger document, where "/" is the root

x-mdrinfo

Extends: /info Old Name: x-mdrinfo Function: This contains information about swagger spec as published in MDRest4i Documenter. Example:

x-mdrinfo:
  environment: RestTest
  refuuid: testSQLStu
  description: Documentation on MD Documenter
  publishDate: '2023-05-09T14:14:58.051Z'
  url: /docu/?envrefuuid=RestTest&refuuid=testSQLStu
  x-forceOverwrite: false

x-mdrGenRequest

Extends: root Old Name: n/a Function: Created by SDK when submitting a generation request. Specifies the selections made by the user when requesting code generation. Example:

x-mdrGenRequest: 
  genPath: '/myapiname'
  genMethod: 
    - POST
    - GET
  genRequestDate: '2023-06-26T15:11:08.658Z' 

x-mdrGen

Extends: /path - Old Name: x-mdrinfo Function: This is found at the root of each /path in the SWAGGER spec

paths:
  /myapiname{pathparm2}:
    x-mdrGen:
      # Extension of path
      RESTtype: consumer
      # Tells the generator what program type to create. consumer or API
      genTemplate: RPGLE_EACH
      # Tells the generator which template to use in the generator config/template file. RPGLE_EACH = one program per method, RPGLE_ALL = all methods in one program(This will be written after v14.0). The details of these are stored in mdrsdk_Templates.json
      language: RPGLE
      jwt: 'N'
      # GEN logic to get Authorization header
      mdrGenOptions:
      # Tells generator the details for each method
        GET:
        # The same structure below is used for GET, DELETE, and OPTIONS methods
          object: '/QSYS.LIB/SKDEMO14.LIB/SKDEMO14.PGM'
          # Library/object name of the API or consumer program
          source: '/QSYS.LIB/SKDEMO14.LIB/QDEMOSRC.FILE/SKDEMO14.MBR'
          # location of source file/mbr for the API or consumer. uses either IFS format /mdrtst14/src/skdemo.rpgle .LIB format
          copybookPath: '/QSYS.LIB/SKDEMO14.LIB/QDEMOSRC.FILE/SKDEMO14P.MBR'
          # location of copy book source file/mbr for payloads. uses either IFS format /mdrtst14/src/skdemo.rpgle .LIB format
          lastmdrGen: '1970-01-01T00:00:00.000Z'
          # time stamp for last time program was generated. Updated with return from MDRSDK. When OAPI spec if first created this value is set to zero : 1970-01-01T00:00:00.000Z
          msgLvl: 10 # NOTEMP
          # message level from generator API. Updated with return from MDRSDK. Not added until a generation attempt is made and response form MDRSDK received
          msg: SUCCESS - source generated and object compiled # NOTEMP
          # message text from generator API. Updated with return from MDRSDK. Not added until a generation attempt is made and response form MDRSDK received
          url: https://dev.mdcms.ch/mdrdemod12/helloworld # CONSUMER ONLY
          # Used by generator to determine endpoint/schema of request.
          authorization: Basic # CONSUMER ONLY: can be "Basic", "Bearer" or "Digest" 
          DCMApp: MDREST4I_CLIENT # NOTEMP # CONSUMER ONLY
          # Which DCM Application to use in connection.  Takes precedence over keystore, but if not specified, a default keystore (see below) is used.
          APPID: MDR001 # NOTEMP # CONSUMER ONLY
          # Which APPid detail to use from MDRCREDX credentials store
          CLIENTID: AWS001 # NOTEMP # CONSUMER ONLY
          # Which CLIENTID detail to use from MDRCREDX credentials store
          keystore: # NOTEMP # CONSUMER ONLY
            path: '/QIBM/USERDATA/ICSS/CERT/SERVER/DEFAULT.KDB'
            # IFS path to keystore file.  Default = *SYSTEM
            label: 'sk-ecdsa-2048-key'
            # label within keystore (default = none)
            password: 'fr0gzEatFl!es'
            # password needed to access keystore (default = none)
          payloads:
          # This object will describe how payloads will be parsed and generated and what format XML/JSON etc will be used
            format: JSON
            # This can be JSON and XML and TXT for now
            parseMethod: DATA-INTO
            # This will control what happens to in bound payloads. initially we will allow DATA-INTO, JPATH, IFS.
            parseInto: '/mdrest4i/data/input.json'
            # This value is used by the generator to determine where the payload coming in to in the request(Provider) and response(Consumer) will be written to. 
              #For example If parseMethod = IFS, the generator will always use a generated variable 'parsePath' to set the path where the payload is written. If it has a value, then the generator will create the variable and then assign this value in the generated code. If parsePath is blank, the generator will assign a default value to the generated parsePath variable such as '/mdrest4i/payloads/{pgmname}/input.json'.
              # If parseMethod = DATA-INTO for example the SDK user can specify where the payload should end up and in what format
            parseIntoFormat: UTF-8
            # Tells the generator how to generate code to handle the format of the parseInto requirement.
          paging: false # NOTEMP
          # GEN logic to send and receive pagination headers
          missingEntryHandling: false # NOTEMP
          # GEN logic to for handling missing entries in request body
          numExceptionBypass: true # NOTEMP
          # GEN logic for exception handling of numbers from request body, too large for numeric variables
          callType: MODULE # NOTEMP PROVIDER ONLY
          # API ONLY: GEN logic for calling a module from API. enum: MODULE, PGM, SRVPGM.
          called: # NOTEMP PROVIDER ONLY 
            # Calling details used by generator - only exists in swagger if added in UI by user.
            callLib: STUART
            # qualified library name for module. *LIBL can be used so no qualified name is used in generated code
            callname: MYMOD
            # module, service program or program name
            procName: GETSTUFF
            # procedure name
            callparms:
            # GEN logic for parameters to be passed to called 
              inqry:
              # parameters from query string used in call
                - accountid
              inhdr:
              # parameters from HTTP headers used in call
                - x-name
              inpth:
                - pathparm2
              # parameters from API path used in call
        POST:
        # The same structure below is used for POST, PATCH and PUT methods
          object: '/QSYS.LIB/SKDEMO14.LIB/SKDEMO14.PGM'
          # Library/object name of the API or consumer program
          source: '/QSYS.LIB/SKDEMO14.LIB/QDEMOSRC.FILE/SKDEMO14.MBR'
          # location of source file/mbr for the API or consumer. uses either IFS format /mdrtst14/src/skdemo.rpgle .LIB format
          copybookPath: '/QSYS.LIB/SKDEMO14.LIB/QDEMOSRC.FILE/SKDEMO14P.MBR'
          # location of copy book source file/mbr for payloads. uses either IFS format /mdrtst14/src/skdemo.rpgle .LIB format
          lastmdrGen: '1970-01-01T00:00:00.000Z'
          # time stamp for last time program was generated. Updated with return from MDRSDK. When OAPI spec if first created this value is set to zero : 1970-01-01T00:00:00.000Z
          msgLvl: 10  # NOTEMP 
          # message level from generator API. Updated with return from MDRSDK. Not added until a generation attempt is made and response form MDRSDK received
          msg: SUCCESS - source generated and object compiled  # NOTEMP 
          # message text from generator API. Updated with return from MDRSDK. Not added until a generation attempt is made and response form MDRSDK received
          url: https://dev.mdcms.ch/mdrdemod12/helloworld
          # CONSUMER ONLY: Used by generator to determine endpoint/schema of request.
          authorization: Basic # CONSUMER ONLY: can be "Basic", "Bearer" or "Digest". Adds the relevant logic to consumer for setting the authorization details before the request is made  # NOTEMP
          DCMApp: MDREST4I_CLIENT # CONSUMER ONLY  # NOTEMP 
          # Which DCM Application to use in connection
          APPID: MDR001 # CONSUMER ONLY # NOTEMP 
          # Which APPid detail to use from MDRCREDX credentials store
          CLIENTID: AWS001 # CONSUMER ONLY # NOTEMP 
          # Which CLIENTID detail to use from MDRCREDX credentials store
          payloads:
          # This object will describe how payloads will be parsed and generated and what format XML/JSON etc will be used
            format: JSON
            # This can be JSON and XML and TXT for now
            parseMethod: DATA-INTO
            # This will control what happens to inbound payloads. initially we will allow DATA-INTO, JPATH(used for mdr_JSONPATHV etc),  IFS. MDR-DATAINTO(used for MDR-DATAINTO), will be in V14.2
            parseInto: '/mdrest4i/data/input.json'
            # This value is used by the generator to determine where the payload coming in to in the request(Provider) and response(Consumer) will be written to. 
              #For example If parseMethod = IFS, the generator will always use a generated variable 'parsePath' to set the path where the payload is written. If it has a value, then the generator will create the variable and then assign this value in the generated code. If parsePath is blank, the generator will assign a default value to the generated parsePath variable such as '/mdrest4i/payloads/{pgmname}/input.json'.
              # If parseMethod = DATA-INTO for example the SDK user can specify where the payload should end up and in what format
            parseIntoFormat: UTF-8
            genMethod: DATA-GEN
            # This will control what happens to in bound payloads. initially we will allow DATA-GEN, MDR-YAJL(used for mdr_addchar() etc), or IFS. MDR-GEN(used for MDR-DATAGEN) will be added in V14.2
            genPath: '/mdrest4i/data/input.json' 
            # GEN logic to create payload directly from IFS. only used when parseMethod = IFS
          # message text from generator API
          paging: false   # NOTEMP
          # GEN logic to send and receive pagination headers
          missingEntryHandling: false   # NOTEMP
          # GEN logic to for handling missing entries in request body
          numExceptionBypass: true   # NOTEMP
          # GEN logic for exception handling of numbers from request body, too large for numeric variables
          callType: MODULE # NOTEMP PROVIDER ONLY
          # API ONLY: GEN logic for calling a module from API. enum: MODULE, PGM, SRVPGM.
          called: # PROVIDER ONLY 
            # Calling details used by generator - only exists in swagger if added in UI by user.
            callLib: STUART
            # qualified library name for module. *LIBL can be used so no qualified name is used in generated code
            callname: MYMOD
            # module, service program or program name
            procName: GETSTUFF
            # procedure name
            callparms:
            # GEN logic for parameters to be passed to called program
              inqry:
              # parameters from query string used in call
                - accountid
              inhdr:
              # parameters from HTTP headers used in call
                - x-name
              inpth:
                - pathparm2
              # parameters from API path used in call              
              schema: '#/components/schemas/parameters'
              # The request body schema that should be passed with the call. the corresponding data structure is passed at the end of the parameters passed           

The table below defines the UI settings and corresponding generator actions. | OAPI Extension | UI Value |MDRSDK Constant| Generator Action | |-------|----------|----------------|-------------------| |parseMethod|DATA-INTO|METHOD_DATAINTO|Use IBM's DATA-INTO function to parse data into a data structure| |parseMethod|JPATH|METHOD_JSONPATH| Use MDR_JSONPATHV etc functions to parse into a data structure| |parseMethod|IFS|METHOD_IFSSAVE|Use MDR_writeBodyToFile to save the incoming payload directly into an ifs file specified in mdrGenOptions.payloads.parseInto using mdrGenOptions.payloads.parseIntoFormat | |##########|################|################|###################################################################| |genMethod|DATA-GEN|METHOD_DATAGEN|Use IBM's DATA-GEN function to generate a JSON payload from a data structure| |genMethod|MDR-YAJL|METHOD_MDRYAJL|Use mdr_addchar etc to build payload| |genMethod|IFS|METHOD_IFSREAD|Load payl;oad directly from IFS file specified in mdrGenOptions.payloads.genPath|

x-schemaFld & x-schema

Extends: /path/method/paramters/schema Function: Both are used to tell the generator where to look for the detailed parameteter attributes for for generating RPG/COBOL Variables. we only ass detailed attributes (such as IBM i data types, size etc) in the SWAGGER schemas Example

      parameters:
        - in: query
          name: dept
          description: department
          required: true
          schema:
            x-schemaFld: Department
            # The element in the schema that this paramters relates to
            x-schema: '#/components/schemas/parameters'
            # The schema that this parameter relates to
        - in: header
          name: x-category
          description: Category
          required: true
          schema:
            x-schemaFld: Category
            # The element in the schema that this paramters relates to
            x-schema: '#/components/schemas/parameters'
            # The schema that this parameter relates to

x-flow

Extends: /path/method/paramters/in: header Function: Specifies the usage of HTTP Headers in the transaction. Tells the generator what code to create for fetching and writing headers in request/responses. Example

      parameters:
        - in: query
          name: dept
          description: department
          required: true
          schema:
            x-schemaFld: Department
            x-schema: '#/components/schemas/parameters'
        - in: header
          name: x-category
          description: Category
          required: true
          schema:
            x-schemaFld: Category
            x-schema: '#/components/schemas/parameters'
          x-flow: both
          # Tells the generator what HTTP Header handling code to create. enum: in, out, both

x-ibmitype & x-column

Extends: /components/schemas/[mdlDummy]/properties/[REFUUID] Function: Specifies PF/TABLE name and Library that the schema was built from. Tells the generator where to get the variable attributes when building payload data structures. Also used to create SQL reads for GET methods where the schema is the explicit (norefs) payload. Example

components:
  schemas:
    mdlDummy:
      properties:
        refuuid:
          description: REFUUID
          type: string # used by generator set type dat element: variable, data structure, array
          maxLength: 50 # used by generator to set char/varchar length
          x-ibmitype: varchar
          x-column: REFUUID
        envname:
          description: ENVNAME
          type: string
          maxLength: 250
          x-ibmitype: varchar
          x-column: ENVNAME
        type:
          description: TYPE
          type: string
          maxLength: 1
          x-ibmitype: char
          x-column: TYPE
        mdcmsurl:
          description: MDCMSURL
          type: string
          maxLength: 256
          x-ibmitype: char
          x-column: MDCMSURL
        timestamp:
          description: TIMESTAMP
          type: string
          format: date
          maxLength: 26
          x-column: TIMESTAMP
        decfld:
          description: DECFLD
          type: number
          x-ibmitype: packed
          maximum: 99999999.99
          x-column: DECFLD
        decfld1:
          description: DECFLD1
          type: integer
          x-ibmitype: packed
          maximum: 9999999999
          x-column: DECFLD1
        numfld:
          description: NUMFLD
          type: integer
          x-ibmitype: zoned
          maximum: 134217727
          x-column: NUMFLD
      type: object

X-mdrschema

Extends: /components/schemas/[mdlSQLex] Function: Specifies the source of the SQL, COBOL, RPGLE used to create the SWAGGER schema, and the SDK path that stores the SQL code to be used to insert in generated API/CONSUMER MDRSDK Usage: MDRSDK would return these values as part of MDRSDK_readschema() function. The following data structures apply:

dcl-ds MDRSDK_schemaExtensions_t qualified template;
  type        varchar(30)   inz;
  objectPath  varchar(4094) inz;
  srcPath     varchar(4094) inz;
  sdksrcpath  varchar(4094) inz;
end-ds;

dcl-pr MDRSDK_readSchema ind  extproc(*cwiden:MDRSDK_env.readSchema);
  cfg        likeds(MDRSDK_plugin_t);
  handle     pointer value;
  prop       likeds(MDRSDK_schemaProp_t);
  extensions likeds(MDRSDK_schemaExtensions_t);
end-pr;
Examples See here or a complete OpenAPI example that has multiple paths, each with a different schema type

components:
  schemas:
    mdlRespDB2:
      x-mdrschema: # Provides reference information that the SDK used to extract the schema. For SQL this information is used by the generator to create the SQL statements
        type: DB2 # has different possible values based upon what reverse engineering tools available. Currently DB2, DS-RPGLE, DS-COBOL, SQL
        objectPath: "/QSYS.LIB/MDRTST14.LIB/LXCLIENT.FILE" # path to object used to create schema. currently this is only applicable when using DB2 "Type" 
        srcpath: "" # Original source used by SDK UI to create schema via reverse engineering apis such as MDRSCHEMA, MDRGENSCM, MDRFIELDS etc
        sdksrcpath: "" # The SDK saves the imported SQL to this path. The generator will use this exact SQL code to insert the sql statement in the generated API/Consumer, rather than the source from the original source member/folder etc. This avoids mismatches if the source is changed between import and code generation.
  ##############################
    mdlRespDSExtract:
      x-mdrschema:
        type: DS-RPGLE
        objectPath: ""
        srcpath: "/qsys.lib/mdrtst14.lib/examples.file/SCMR001.mbr"
        sdksrcpath: ""
  ##############################
    mdlRespDSCOBOLExtract:
      x-mdrschema:
        type: DS-COBOL
        objectPath: ""
        srcpath: "/qsys.lib/mdrtst14.lib/examples.file/SCMC001.mbr"
        sdksrcpath: ""
  ##############################
    mdlRespSQLmbrExtract:
      x-mdrschema:
        type: SQL
        objectPath: ""
        srcpath: "/qsys.lib/mdrtst14.lib/examples.file/scmq001.mbr"
        sdksrcpath: "/www/mdrstt12/specs/cons/STUART/SQL87dd3e0.sql" 
  ##############################
    mdlRespSQLLocalExtract:
      x-mdrschema:
        type: SQL
        objectPath: ""
        srcpath: ""
        sdksrcpath: "/www/mdrstt12/specs/cons/STUART/SQL87dd3e0.sql"