• +43 660 1453541
  • contact@germaniumhq.com

Creating REST Endpoints Using BPMN Messages in Python


Creating REST Endpoints Using BPMN Messages in Python

Sometimes we just want to process events that arrive from an outside system, but still model these in an BPMN process. BPMN natively supports that representation in the form of input messages starting events. We’ll be wiring Flask to stream messages directly into the process using the message_calback function.

This is the BPMN process that we’re going to model (full code links are available at the end of the article).

description

We’re using instead of only the regular start event start event, also a message event message event.

The start event gets automatically triggered at the start of the process, and simply instantiates the Flask server in the "Run Flask Server" task:

app = Flask(__name__)


@adhesive.task('Run Flask Server')
def run_flask_server(context):
    app.run()

Now if you notice, we haven’t registered any handlers yet in the Flask app object. What we’re doing is we’re registering them into the @adhesive.message_callback call:

@adhesive.message_callback('REST: /rest/process-resource')
def message_rest_rest_process_resource(context, callback):
    @app.route("/rest/resource/create")
    def create_resource():
        callback(Dict({
            "type": "CREATE"
        }))

        return "Create event fired"

    @app.route("/rest/resource/process")
    def process_resource():
        callback(Dict({
            "type": "PROCESS"
        }))

        return "Process event fired"

As with the @adhesive.message, the @adhesive.message_callback gets called before activating the main process. That means our routes get registered before firing up app.run().

Whenever a new requests hits, we’re just pushing the new token into the process. The data from the token is used then to route the event into the appropriate tasks:

message routing

It becomes trivial now implementing a REST webhook, that’s backed by a business process behind in the decision making on how to process that request. Furthermore, the tokens are still just regular tokens, that means we have the capability of creating an orchestrating process that while operating can still receive events from the outside world.

Notes

Now you wonder why not extract the name of the REST endpoint directly from the BPMN process, something like:

@adhesive.message_callback(re='REST: (.+)')
def message_rest_rest_process_resource(context, callback, endpoint):
    @app.route(f"{endpoint}/create")
    def create_resource(): ...

Why? Because for some reason Flask refuses to register a view, if the implementation function name is already used by some other view.

What Next

To try it simply install adhesive in a Python 3.6+ environment:

pip install -U adhesive

And run the process described in this article, available from here https://github.com/germaniumhq/adhesive-samples/tree/master/rest-endpoint