- 
                Notifications
    You must be signed in to change notification settings 
- Fork 15
Angularjs Command Sourcing
Angularjs and Command Sourcing
The communication between Angular applications to resource servers is normally done through REST API. Compare with other web service protocols it has its merits but the traditional way of REST API design is not suitable for event sourcing architecture.
Let’s take a look at the pros and cons of REST and SOAP first.
SOAP packaging for both request and response is heavy weight and parsing XML is expensive. WSDL discovery adds another layer of overhead and reveals entire message format for targeted attacks. The integration is at process level not data level. Above is the penalty to scalability of you system and why it is rarely used over the Internet. Even in enterprise web service integration, it is used less and less.
REST is light weigh, has predictable end points and exposes resource instead of process. It is very suitable for client side applications (AngularJS etc.) that only consume resources. However, it has it own shortcomings.
- There is no standard and developers design the API differently.
- This causes the mapping from URL to request handler complicated.
The following is my recommendation on how Angular sends command to the server and the server gives back response by looking up rule from command data to handle the request.
From Angular, each communication to the backend will be a command using HTTP post(read, write, not cacheable) and get(read, cacheable).
There are two part of the each command: common and command specific
Here is a list of elements for common:
host
app
category
name
version
readOnly
Of above, category, name and readOnly are mandatory. If host and app are missing, then it means to call some common rules of part of the core system. If version is missing, then it means for the rule the original will be called.
Command specific data portion will be flexible and can be anything.
{
	“host”: “www.networknt.com”,
	“app”: “OnlineShopping”,
	“category”: “user”,
	“name”, “login”,
	“version”: 1,
	“readOnly”, false,
	“data”: {
		“userId”: “stevehu”,
		“password”, “password”,
		“rememberMe”, true	
	}
}
Here is the way to lookup command rules and event rules based on command common fields
    public static String getCommandRuleClass(Map<String, Object> jsonMap) throws Exception {
        Class c = Class.forName("com.networknt.light.rule.Rule");
        String commandName = (String) jsonMap.get("name");
        String ruleClass = commandName.substring(0, 1).toUpperCase() + commandName.substring(1) + "Rule";
        ruleClass = c.getPackage().getName() + "." +
                (jsonMap.get("host") == null? "" : jsonMap.get("host") + ".") +
                (jsonMap.get("app") == null? "" : jsonMap.get("app") + ".") +
                (jsonMap.get("category") == null? "" : jsonMap.get("category") + ".") +
                (jsonMap.get("version") == null? "" : jsonMap.get("version") + ".") +
                ruleClass;
        //System.out.println("ruleClass = " + ruleClass);
        return ruleClass;
    }
    public static String getEventRuleClass(Map<String, Object> jsonMap) throws Exception {
        Class c = Class.forName("com.networknt.light.rule.Rule");
        String eventName = (String) jsonMap.get("name");
        String ruleClass = eventName.substring(0, 1).toUpperCase() + eventName.substring(1) + "EvRule";
        ruleClass = c.getPackage().getName() + "." +
                (jsonMap.get("host") == null? "" : jsonMap.get("host") + ".") +
                (jsonMap.get("app") == null? "" : jsonMap.get("app") + ".") +
                (jsonMap.get("category") == null? "" : jsonMap.get("category") + ".") +
                (jsonMap.get("version") == null? "" : jsonMap.get("version") + ".") +
                ruleClass;
        //System.out.println("ruleClass = " + ruleClass);
        return ruleClass;
    }
The way the api rule is called.
if(readOnly) {            
    RuleEngine.getInstance().executeRule(Util.getCommandRuleClass(jsonMap), jsonMap);
} else {
    boolean valid = RuleEngine.getInstance().executeRule(Util.getCommandRuleClass(jsonMap), jsonMap);
    if(valid) {
        // persist event into event store.
        Map<String, Object> eventMap = (Map<String, Object>)jsonMap.get("eventMap");
        DbService.persistEvent(eventMap);
        RuleEngine.getInstance().executeRuleAsync(Util.getEventRuleClass(eventMap), eventMap);
    }
}