I am trying to automate Business Process which can be characterized as a
pipeline with distinct stages
.Pipeline can be perceived as A->B->C, where A,B,C are distinct Business Steps that work on some common POJO.
For example, lets consider this Business process:
Business needs to identify whether a Book can be sold in Indian Subcontinent.
Step 1. Ensure that the Book has a
specific Publisher P
Step 2. Fetch all editions of Book. The book can only be sold if the
edition is > 2.0
Step 3. Make sure that the
Price is < 5k
. If not check with the Publisher.
This is a simple Pipeline with 3 steps. These steps are different from each other and should be designed for easy re-usability. For example, if tomorrow I need to work on a similar logic for US, I should be able to use Step 1, but for a different publisher.
I have an Interface like this:-
interface Step {
// T pojo might vary based on which business problem is being solved.
// But the variation will be very slight. For example, different Business
// involving Books will typically work on multiple POJO's each having attributes of Books (with slight variations)
<T> void process(T pojo) throws Exception;
}
For simplicity, let's say we have 2 distict Business Process in Indian Subcontinent & in US. We might have following POJOs.
class IndianBooks {
String publisher;
int price;
String importer; // this one is not present next POJO
...
}
class USBooks {
String publisher;
int price;
String printedAt; //this one is different from IndianBooks
...
}
Each Pipeline step would implement this Step Interface
For example.
class FilterByPublisher implements Step {
//lets say FilterByPublisher is invoked by Business 1, which deals with Indian Subcontinent
// `process` method should be able to operate on IndianBooks POJO
// if invoked by Pipeline2 which opearates on US Books this method should be
// able to handle USBooks POJO
void process(T pojo) {
1. needs to access publisher attribute of T
...
}
}
I have thought of the following way:
- using
instanceof
within theprocess()
method to check the type of the POJO and then operate on it, then set the other attribute.Note that this change should be reflected in sub-sequent Stages
But somehow I feel that this is not a scalable way since everytime a new Pipeline comes into the scene, I will need to update this method.
Any inputs on how I can effectively solve this?
Update: - After looking at the comment from @Jules, I looked at Visitor Pattern & thought of following approach.
I could keep the Step Interface generic. Create an abstract FilterByPublisher
class which handles filtering logic. Create 2 Concrete Filter Classes (to be used by different Business Processes) which just handle the input & pass on to the abstract FilterByPublisher
class.
abstract class FilterByPublisher {
void filter(String publisher) {
..
}
}
class FilterByPublisher_IndianBusiness extends FilterByPublisher implements Step {
@Override
public <T> void process(T pojo) {
String publisher = ((IndianBooks)pojo).getPublisher(); // typecast
filter(publisher);
}
}
Any other alternatives are welcome.
step reusable
. This way each step can be plugged in & out in different pipelines. The constraint here is that different Pipelines might be working on different POJOs so the Stage(or step) should be able to handle that. One solution is to havemultiple concrete Stages
doing same thing but on different POJOs.The processing can be provided by Abstract Stage & POJO handling by Concrete Stages.