REST API Management Service In Qorus

In this blog post, you’ll learn how to create a Qorus service to manage your REST APIs. Services in Qorus are of two types:

  1. System services – For system services delivered with Qorus
  2. User services – User services written/configured by Qorus developers
This blog post will walk you though the process of creating a user service for managing your REST APIs.

ℹ️ Note: A working example is made available to you in our building-blocks repository. You can find the code files and the metadata files in the examples/create-customer-service directory.

Getting Started

You’ll get started by deploying a DB schema that acts as your playground for CRUD operations. For this example, you’ll create two tables responsible for storing customer records, crm_customer_example and crm_address_example.

You can deploy the above DB schema by deploying the schema module file, CrmCustomerExampleSchema.qsm in the examples/create-customer-service directory with oload using the Python client.

You should see the following output after a successful deployment

Uploading files to remote host "wss://localhost:8011/": .
processing user schemas: loading qsm file: /tmp/qorus-test-instance/WCXsxaMbOGVd16C/CrmCustomerExampleSchema.qsm
pgsql:postgres@postgres%pg: creating CrmCustomerExampleSchema schema 1.0
31 changes made; schema is now at version 1.0
pgsql:postgres@postgres%pg: user schema "/tmp/qorus-test-instance/WCXsxaMbOGVd16C/CrmCustomerExampleSchema.qsm" is at version 1.0
OK
-- process terminated with exit code 0 --
You now have a DB schema with two tables, sequences and triggers deployed to the Qorus’ Postgres database.
Alternatively, you can deploy the DB schema by clicking the run button next to the CrmCustomerExampleSchema schema module

Creating a Qorus User Service

1. Open the Qorus IDE and click on the purple “Q” to get the IDEs main menu. Log in to your Qorus server by clicking on the Login button.
2. Click on the Create new (new file) icon next to the Service interface from the interface hierarchy view.
3. In the Qorus Webview window, fill in the New service form with the following:
  • Target Directory : Browse through the Show Directories field and select a source directory. This will be the directory where the code and metadata files generated by the interface are stored.
  • Name : create-customer-example. This will be the name of your service.
  • Click on Please select field next to the Base class name attribute and select QorusService, The base class for Qorus services.
    Base class name : QorusService
  • Version : 1.0
  • Description : This service uses a Swagger schema to provide a REST API to simulate creating a customer in a CRM system. The description field supports markdown so, feel free to format your text in Markdown.
4. From the Optional Fields drop-down list to the upper-right corner of the form, Find the API Manager field and add it to the New service form.
5. In the API Manager field, set the API Schema Type to swagger
ℹ️ Note: A metadata file describing the swagger schema, example-customer-schema-1.0.yaml is made available to you in the examples/create-customer-service directory.
6. Then, fill the Options section of the API Manager filed with the following:
  • Populate the Custom tab of the root-uri option with example-crm, This will be your root URI path for the API
  • Under the Custom tab of the schema option, browse through the Show Directories field and select the swagger schema file, example-customer-schema-1.0.yaml in the examples/create-customer-service directory.
  • Click on the Add option button below the options section and add the auth-name option. Under the Custom tab, set the authenticator to permissive.
  • Similarly, add the listener-bind-address option and fill the Custom tab with *:0
    With this, we tell Qorus to use a random port on all interfaces

ℹ️ Note: API manager configuration has very flexible configuration to configure how the API handler is started, it can be started on all Qorus system listeners, if no bind address is given and various other options can be given as well. Only Qorus Enterprise Edition supports the authentication options, Qorus Community Edition does not support users, permissions, or user-based authentication.

  • Under the API Endpoints section, click on the Select Endpoint and add the /customers/POST endpoint and set the type to method.
    Click on the Plus button, and fill in the following:
  • Name : customerCreate
  • Description : Creates a new customer record
  • Similarly, Add the following endpoints:
  • /customers/*/DELETE
    Type : method

    Name : customerDelete
    Description : Deletes an existing customer
  • /customers/*/GET
    Type : method
    Name : customerRead
    Description : Returns info about one customer
  • /customers/*/PUT
    Type : method
    Name : customerUpdate
    Description : Updates a customer
  • /customers/GET
    Type : method
    Name : customersGet
    Description : Retrieve / search customers
7. From the Optional Fields drop-down list, Add the Autostart field and set it true.
8. Add the Groups field and set it to the EXAMPLES group.
9. Similarly, add and populate the Author field.
10. Click on the Next button at the bottom.
11. Click Submit to save your Service interface.

After the submission, the IDE will open the interface’s code file with a CreateCustomerExample class and empty methods for the endpoints you specified earlier. For this example, you can copy the logic from the example-create-customer-1.0.qsd file in the examples/create-customer-service directory.

ℹ️ Note: The contents of example-create-customer-1.0.qsd are written using the Qore language, however, Qorus provides the flexibility to choose between Qore, Java and Python. Make sure to set your preferred language during the interface configuration in the language field.

Finally, deploy the service to the Qorus server by clicking on the cloud icon next to the service’s name in the hierarchy view.

ℹ️ Note: You can achieve the same by deploying the example-create-customer-1.0.qsd.yaml file to the server with oload using the Python client or by deploying the example-create-customer service.

When using API managers in Qorus services, the request type is the input type for the API, and the response type is the output type. When a service method is associated to an API endpoint, the parameter types to the service method must correspond to the request type.

For OpenAPI / Swagger APIs, request arguments are passed as a hash, with each hash key corresponding to a declared argument. The return value of the method must correspond to the type specified in the schema. When an FSM is used to serve an API endpoint, then the same data is passed to the FSM and expected as output; and any FSM created from the IDE will have these types specified in the FSM as well.

Getting the Service's Port Number

Since you’ve set *:0 as your listener-bind-address, the service binds on a random port every time it’s started, also multiple listeners may be started due to this bind option.

To get the port the listener is bound on, call:

qrest put services/example-create-customer/getPort/call
Response:
43573
-- process terminated with exit code 0 --
To see all the listeners started for the service, call:
qrest services/example-create-customer/resources
Response:
hash: (1 member)
svc-example-create-customer-2-svc-example-create-customer-1 : hash: (3 members)
type : "HttpListener"
desc : "listening on ipv4(0.0.0.0):43573 (dedicated)"
info : hash: (19 members)
content : <NOTHING>
headers : <NOTHING>
name : "svc-example-create-customer-2"
hostname : "0.0.0.0"
hostname_desc : "ipv4(0.0.0.0)"
address : "0.0.0.0"
address_desc : "ipv4(0.0.0.0)"
port : 43573
family : 2
familystr : "ipv4"
ssl : False
id : 2
desc : "ipv4(0.0.0.0):43573"
proto : "http"
bind : "0.0.0.0:0"
get_remote_certs : False
ssl_verify_flags : list: (1 element)
[0]="SSL_VERIFY_NONE"
ssl_accept_all_certs : True
url : "http://[YOUR-IP]:43573"
-- process terminated with exit code 0 --

Performing the CRUD Operations Manually

You can perform the CRUD operations manually with the following:
ℹ️ Note: Replace the “[PORT]” with the port number on which the listener is bound. i.e., the result of qrest put services/example-create-customer/getPort/call
1. To Create a customer, call:
qrest post http://localhost:[PORT]/example-crm/customers '{Name=test,Type=new,TaxId="1234567",Address={Name=test customer,AddressLine1=10 Main Street,City=Prague,PostalCode=130 00,Country=CZ}}'
2. Get a list of customers with:
qrest http://localhost:[PORT]/example-crm/customers?limit=[number-of-records]

ℹ️ Note: Replace “[number-of-records]” with the number of records you want to see in the response. i.e., qrest http://localhost:[PORT]/example-crm/customers?limit=1 will include a single customer record in the response.

3. To get customer info, call:
qrest http://localhost:[PORT]/example-crm/customer/1
ℹ️ Note: The response in this case is customer one’s info
4. You can update a customer record with:
qrest put http://localhost:[PORT]/example-crm/customers/1 Type=STANDARD
ℹ️ Note:This will update the customer one’s record
5. To delete a record, call:
qrest delete http://localhost:[PORT]/example-crm/customers/1
ℹ️ Note: This will delete the customer one’s record

Getting Information About APIs In Qorus

You can use qdp, the command-line interface to the Data Provider API to get information about APIs in Qorus. For example, once the service has been deployed, the OpenAPI / Swagger schema can be used to provide information about the APIs described in the schema as follows:
qdp swagger'{schema=resource://example-create-customer:example-customer-schema-1.0.yaml}'
You should see the following output:
["customers"]

ℹ️ Note: This uses the swagger Data Provider factory to provide information about the APIs implemented in the schema, which can be accessed using the special location scheme. In the above example, we use the resource:// scheme.

To see the request and response types for different APIs, the following commands can be used:
For response types:
qdp swagger'{schema=resource://example-create-customer:example-customer-schema-1.0.yaml}'/customers/GET response
Output:
softlist<hash<auto>> body: elements ->
*softint Id
softstring Name
softstring Type
softstring TaxId
hash<auto> Address
softstring Name
softstring AddressLine1
*softstring AddressLine2
*softstring AddressLine3
softstring City
*softstring PostalCode
*softstring Region
softstring Country
For request types:
qdp swagger'{schema=resource://example-create-customer:example-customer-schema-1.0.yaml}'/customers/POST request
Output:
hash<auto> body
*softint Id
softstring Name
softstring Type
softstring TaxId
hash<auto> Address
softstring Name
softstring AddressLine1
*softstring AddressLine2
*softstring AddressLine3
softstring City
*softstring PostalCode
*softstring Region
softstring Country
ℹ️ Note: The path components after the factory options are child data providers; for an OpenAPI-based Data Provider, these paths depend on the URI paths and REST methods for the request. For more information on the qdp program, run:

qdp -h

Testing the Solution

You can test the solution you’ve developed so far by running the example-create-customer.qtest test file in the examples/create-customer-service directory. Go to the Qorus IDE and in the interface hierarchy view, under the Tests file type, find the example-create-customer test. Run the test by clicking on the play button next to it.

You should see the following output after a successful test in VS Code at View → Output → Qorus Remote Development

Files to test:
examples/create-customer-service/example-create-customer.qtest
Execution to Local - https://localhost:8011/ has started ...
options: {"continue-on-error":false}
... response: {"id":3,"href":"api/latest/development/test/3"}
uri https://localhost:8011/api/latest/development/test/3
1s checking execution progress (ID: 3) ...
2s checking execution progress (ID: 3) ...
... response: QUnit Test "example-create-customer" v<latest>
Ran 1 test case, 1 succeeded (5 assertions)
... status: FINISHED
Execution finished successfully (ID: 3)

Grab your FREE application integrations eBook.
You'll quickly learn how to connect your apps and data into robust processes!