API Documentation

The following documents the microesb internal dependencies. It is not strictly necessary to understand these to implement or configure a working service setup.

Note

You should continue reading to gain a better understanding of how internal processing works, especially Multi-Class Handling, before proceeding to the example section.

1. Base Handler

The Abstract Base Class (ABC) must be inherited by the following sub-classes:

  • ClassHandler

  • MultiClassHandler

It provides template functions described in the Internal Classes / Class Representation subsection.

It inherits transformer.JSONTransformer to enable a generic, recursive dictionary representation of the class instance hierarchy. This feature allows for efficient assertions on complex object hierarchies.

Example test case (/test/integration/test_base.py, test: test_multi_item_object):

assert shipment.json_dict == {
    'id': 'testshipment1',
    'SYSServiceMethod': None,
    'Palette': [
        {'id': 1, 'label': 'label1'},
        {'id': 2, 'label': 'label2'}
    ]
}

2. Class Handler

The ClassHandler class inherits from the BaseHandler class.

It provides template methods for implementation classes and the ClassMapper sub-class (see implementation-classes).

An implementation class, especially the root class, must inherit the ClassHandler class and explicitly call the parent (superclass) __init__() method.

Example:

from microesb import microesb

class TestClass(microesb.ClassHandler):
    def __init__(self):
        super().__init__()

3. Multi-Class Handler

The MultiClassHandler class also inherits from the BaseHandler class.

Warning

It does not inherit from ClassHandler. Multi-class handling is only possible in last level classes or endpoint classes.

It indirectly overloads the necessary methods from ClassHandler. To see the differences, refer to the Internal Classes / Class Representation subsection.

Example: Standard ClassHandler vs. MultiClassHandler implementation:

from microesb import microesb

class TestClass1(microesb.ClassHandler):
    def __init__(self):
        super().__init__()

class TestClass2(microesb.MultiClassHandler):
    def __init__(self):
        super().__init__()

For an example service call metadata (Host properties), see Example 1 (1. Hosting Use Case).

4. Implementation Classes

Implementation classes are defined in the implementation phase and contain the programmed service logic.

Note

Every implementation class must inherit either ClassHandler or MultiClassHandler. Only endpoint classes may inherit MultiClassHandler.

4.1. Abstraction

The ClassMapper class is responsible for hierarchically mapping and connecting the desired implementation classes.

After ClassMapper sets up internal class instances, the ServiceMapper class populates these class instance properties with values from the provided service call metadata.

4.2. Inheritance

An implementation class must inherit from either microesb.ClassHandler or microesb.MultiClassHandler.

Additionally, it must include the super().__init__() syntax in its constructor to ensure correct instantiation by the ClassMapper.

4.3. Class Properties Model

The microesb property model is a flat, OOP-based structure.

Consider two implementation classes: Customer as the root class and Domain as the child class of Customer.

  • Customer properties (defined in the service properties config): “Name” and “CustomerID”.

  • Domain properties: “Name” and “Ending” (with a default value of ‘de’).

Both class instances are set up by the ClassMapper in Python’s global domain space.

Example of class member setup after ClassMapper invocation:

1class Customer(microesb.ClassHandler):
2    self.Name = None
3    self.CustomerID = None
4
5class Domain(microesb.ClassHandler):
6    self.Name = None
7    self.Ending = 'de'

4.4. ParentObject Properties

Using the example from 4.3, Customer is defined as the root class and Domain as its child class.

  • Add the method get_customer_dbdata() as a public member of Customer.

  • Add the method do_something() as a public member of Domain.

 1class Customer(microesb.ClassHandler):
 2    self.Name = None
 3    self.CustomerID = None
 4
 5    def get_customer_dbdata(self):
 6        self.CustomerID = dbquery('customerid_by_name')
 7
 8class Domain(microesb.ClassHandler):
 9    self.Name = None
10    self.Ending = 'de'
11
12    def do_something(self):
13        print("CustomerID:{}".format(self.parent_object.CustomerID))

Calling Customer.get_customer_dbdata() sets Customer.CustomerID to a valid customer ID. Printing self.parent_object.CustomerID inside Domain.do_something() invokes the BaseHandler.parent_object() method, returning the self._SYSParentObject reference (due to the @property decorator).

4.5. Class Import

All implementation classes must be imported into the global Python namespace.

from microesb import microesb

Importing the main microesb module will call import esbconfig (see the following code, line 14).

 1# ]*[ --------------------------------------------------------------------- ]*[
 2#  .                         Micro ESB Python Module                         .
 3# ]*[ --------------------------------------------------------------------- ]*[
 4#  .                                                                         .
 5#  .  Copyright Claus Prüfer (2016 - 2024)                                   .
 6#  .                                                                         .
 7#  .                                                                         .
 8# ]*[ --------------------------------------------------------------------- ]*[
 9
10import abc
11import sys
12import logging
13import importlib
14import esbconfig

The microesb standard installation will include an empty esbconfig.py in the global Python dist-packages or in the active Python environment.

Warning

If you do not provide an esbconfig.py in your project folder, the default installation file will be used.

The following esbconfig.py tells the microesb importer to use the file service_classes.py and import implementation classes Class1, Class2, and Class3 into the global namespace. These classes will then be usable by ClassMapper and ServiceMapper during internal processing.

import_classes = {
    'service_classes': [
        'Class1',
        'Class2',
        'Class3'
    ]
}

Note

The Python module containing the implementation classes must also be present in the project folder.

5. Class Mapper

The ClassMapper class is responsible for hierarchically mapping and connecting the desired implementation classes.

The ClassMapper class must be invoked during initialization or before the ServiceMapper. It requires the following configuration dictionaries as input parameters:

Example:

class_reference = { ... }
class_mapping = { ... }
service_properties = { ... }

class_mapper = microesb.ClassMapper(
    class_references=class_reference,
    class_mappings=class_mapping,
    class_properties=service_properties
)

6. Service Mapper

The ServiceMapper class is responsible for mapping and populating the existing class instances (created by ClassMapper) with the given service call metadata.

It requires the following as input parameters: - A reference to the ClassMapper instance - Service Call Metadata Dictionary (see “Configuration / 4. Service Call Metadata”)

Example:

service_metadata = { ... }

res = microesb.ServiceMapper(
    class_mapper=class_mapper,
    service_data=service_metadata
)