Last month I started to write SharpBus, a simple message processor inspired by ideas from Mule Java project. See:
As usual, I’m using TDD (Test-Driven Development), implementing small use cases and API consumption, in the simplest possible way. In fact, the project is a personal exercise of TDD. I hope that some may be useful beyond that. For now, it is an example that I want to share my workflow.
You can see the progress in:
The main ideas to implement are:
- There are Messages containing Payloads and Properties (dictionary of name / value)
- There Flows that process messages
- A Flow is composed of several elements
The elements can be chained in the flow, and can be:
- A Transformer, taking a payload or complete message, and returns a transformed version
- A Processor, taking a payload or complete message, operate on them, maybe accessing the business domain, but without transformation
- Input, a payload/message producer
- Output, a payload/message consumer, at the end od the Flow process
- A Rourter, given a payload/message, it decides with Branch to follow in the Flow. Each Branch is identified by a name.
There will also be items that can issue new posts than the current, and can issue them to different flows in the system. The message producers should be able to run threads (Threads) in principle. And there will be a set of threads (Pool of Threads) attending the incoming messages and deriving them to the respective flows.
A flow can take a message and return a response (Request / Response), or it can take a message, process it without returning an answer.
Some items need complete Message and other items operate over the Payload.
The elements in the world of Mule / Java are objects. Notably, in C #, the simplest way to implement is using lambdas. So, following TDD, the early testing and deployment has come out that way. You can see in some simple tests:
As an example of send a Payload and receive an answer, using an empty Flow:
var flow = Flow.Create();
To send a payload and transform it:
var flow = Flow.Create()
.Transform(x => ((int)x) + 1);
The .Transform Transform expects a Func<object, object> which may be provided at the time with a lambda. In a classic Java 7 Mule, we should provide an object that implements an interface having a method to transform the Payload. I have to think whether it is worth having a typed Transform <T> (receiving T and returns T), or Transform <T, S> (receiving and returns T S).
I decided to build the flow by code. In the Mule environment Spring is used to set up the flow using XML. I think it is time to explore this other way, build the flow by code, and put it as the "first way", ie, as the way on which everything else could be mounted. If anyone ever needed a DSL (Domain-Specific Language) for creating flows could be implemented this way by having well designed code.
Following TDD, I still have not a case of using a Message (a complete message with content (Payload) and properties (Properties, a name / value) dictionary. All of the above is to process Payload directly.
Upcoming topics: add Message Payload with the output of messages, routing, assembling branches, etc. ..
Angel “Java” Lopez