In many cases, when you work with SOA or BPM, Business Rules are involved. They are important for decision logic, validations and process routing. The Business Rule Engine (BRE) that comes with Oracle SOA Suite is a logical choice for modelling such Business Rules, but how do you make sure that those rules can be reused over different services and processes? And how do you isolate the Business Rules logic, so you don’t need to redeploy any other components upon changes?
In one of my projects, I’ve faced the situation of needing to address these issues and have come up with a flexible solution. This blog is the result of further finetuning of that solution, mainly by using the KISS approach.
Business Rule Engine (BRE)First things first: let’s talk about the Business Rule Engine. It’s a powerful tool for executing if-then rules or rules in decision tables, but it’s not always too business friendly for modelling. If that’s a major problem for your client, you should consider Oracle Policy Automation instead. However, if you decided to use the BRE, then reusability becomes an issue pretty quickly. It’s very tempting to just create a BPM process and have the Business Rule component generated from there, but then those rules will only be exposed to that particular composite. There is no central repository for reusable Business Rules (like MDS), so your only real option is to put your Business Rules in a separate SOA composite.
When we dive deeper into the Business Rule Engine, we see four major components:
- Decision Services
RuleSets are groups of rules that can be called by different Decision Services. They should generally contain rules that should always be executed together.
Rules are being executed by the BRE. A rule can only exist in the context of one RuleSet, so rules are not reusable on their own.
Facts are the input objects for your Rules. Since our objective is to create reusability, I recommend to stick to one input fact, which can then be used by all the Rules.
Now let’s have a look at the internal architecture of the Business Rule Engine (see picture above). Since we have the same Facts in all our RuleSets, we’ll get matches for all of them, so all RuleSets will be activated, including those that are not being called by your Decision Service! When a RuleSet fails to activate, an error will occur, so make sure that your Rules have the right conditions to make sure that this doesn’t happen. For example, a Rule that checks if reasonOfEmploymentTermination is of a certain value can have a very nasty impact on an Enrollment process that doesn’t contain this element. To avoid this, I’ve established the practice of using the pre-populated IF part of any Rule to check for the conditions of applying the Rule (f.e. employmentEndDate != null) and entering the actual Rule logic in the THEN part with a nested expression. This way, you have a consistent Rule design and since activation of RuleSets is incredibly fast, performance is not really an issue here.
So, to summarize what should be done in the Business Rule component, we have multiple Decision Services, all based on the same Fact, that call one or more reusable RuleSets.
Organizing your SOA landscapeSo, you’ve decided to reuse your Business Rules and separate them from your processes. Your next step will be to think about the granularity of those Business Rule composites. Since we want both flexibility and reusability, I recommend a domain based structure, so, by example of my latest project, there can be an Employment Rules composite, an Employee Rules composite, Employer rules composite etc…
Since validations and process logic don’t always depend on one functional domain, I have also created a reusable Business Service (Employment Rules Business Service) that calls the domain based rule composites, wraps the responses together and exposes a canonical interface. This way, the number of integrations needed for Business Rule execution can be limited and some orchestration can be done in a centralized way. Additionally, this Business Service can take care of gathering additional information required to execute the Business Rules, so you don’t have to do that in each process or service.
How to keep things Loosely CoupledBasically, my processes and services don’t really care which rules are being executed exactly. They just want to tell to the Rules Business Service “execute the rules that are applicable to me and give me the outcome”. So, when we take the Enrollment Process for example, it will send its relevant payload to the Business Service, together with an element to identify which rules should be executed. For example: EnrollmentProcessRules or EnrollmentValidationRules. Based on this information, the Business Service will do its orchestration and the Rules Services do some Content Based Routing to use the right Decision Service. Click the picture below to understand how it all hangs together.
When you look at the picture, Process A will call the Employment Rules Business Service with some payload and the identifier “EnrollmentProcessRules”. The Business Service does its orchestration and calls the Employment Rules Provider Service. This Provider Service then uses Content Based Routing in a Mediator to go the right Decision Service, which then calls the relevant RuleSets (defined with drag & drop in BRE) that execute the Rules within. The result will be sent back to the Business Service, that gathers all the results and returns a response to the process. Now, if an additional rule needs to be added for this process, how do we do this? We just go into the Business Rule component, add a Rule to a RuleSet or create a new RuleSet with the new Rule and add this RuleSet to the Decision Service that’s being used by the process, depending on the situation. Now we can just deploy the Provider Service again and the process can use its new rule without being changed. Same logic applies for modifying or deleting rules, so things are perfectly loosely coupled this way.