Java – Design solution for communicating between multiple layers

design-patternsjavamultithreading

We are developing a framework that has several layers and would be deployed in a multi-threaded environment. Each layer may have its own input/output data type. The top layer takes the input, performs some actions on the data and passes it to the next layer. Based on the output from next layer, the top layer would perform another set of operations on the data. Similar interactions happen between other layers.


There are two use cases that we did not incorporate in the original design:

  1. Generating metrics over what operations each layer performs on the data.

  2. The change in data in one layer affects the operations in another layer, the changes should be recorded and each layer should have capability to fetch the list of changes.

After some thinking we came up with two approaches to accommodate these requirements in the existing design:

  1. Use observer pattern and let each layer report its changes. These changes can be then pulled by the layer that needs to use it.

    Pros:

    • Since we have already come up with a design for the framework and most of work is complete. This approach would not require significant changes to the existing design, if any.

    Cons:

    • It becomes difficult to manage(record and report back) changes corresponding to each layer.
    • There is a central class that aggregates all the data for each request. This class acts like a global variable. It has to be initialized and deleted by the top layer. Adding another top layer could be error prone.
  2. Extend the current data classes using an interface equivalent to EventContainer. This way all the layers would record their changes and spit them in their output.

    Pros:

    • This approach is much more cleaner and extendable than observer pattern.

    Cons:

    • It would require significant design changes.
    • The concept of data having events as well merges two separate concerns into one and does not seem like a good idea.

We would like to know if there is a design pattern or any other solution that solves this problem?

Which of the above two solutions should be given higher preference considering that we would want a flexible, extendable and cleaner solution?

Best Answer

We would like to know if there is a design pattern or any other solution that solves this problem?

To me this sound like the kind of problem that Enterprise Integration Patterns solve by using communication channels and message passing.

The patterns can be use to decouple the communication between applications, between layers or between components.

There is a number of frameworks that can be used to implement this type of applications like Spring Integration, Apache Camel and Mule

What you describe sounds to me like a Service Activator. One of many different types of message endpoints (ME). The communication between your components will happen through message channels.

The components/service activators are totally unaware of each other and the channels define the pipeline that carries the messages between them.

Most frameworks, like Spring Integration, provide you with interceptors to get a chance to do something with the messages as they flow through the pipeline (equivalent to your observer pattern).

Interesting metrics can also be captured in the form of MXBeans as the message flow through the pipeline.

+----+ channel +----+ channel +----+ | |---------------| |---------------| | | ME | <-message-> | ME | <-message-> | ME | | |---------------| |---------------| | *----+ +----+ +----+

In this type of frameworks the channel abstraction gives you a lot of power. The channel could be direct channels or publish subscribe channels, and the hand off of message can be synchronous or asynchronous. So you have total control of the message flow, the span of transactions, etc.

Related Topic