The Three Levels of Service

Back when I first started programming, everything was about ‘The Three Tiers of server side applications.’ Today, I find that not much has changed. Yes, the UI and top layers have been pushed to the client. If they haven’t in your apps, they should. And the bottom layer, the data layer as been almost stripped away via the ORM and Active Record patterns. Which is good, because we are getting to the guts, the middle layer, the business layer.

A refresher (old school);

TOP - UI / Controller / View
This includes anything on the screen the user sees or clicks. And handling that click.

MIDDLE - Business / Manager / Service
This includes domain specific routing and logic and domain model manipulation.

BOTTOM - DAO / Data Access / Database
This includes transforming our middle layer data and logic paths into storage items.

New School 3-Tier; 

TOP - Web Service Gateway
This includes transforming JSON / XML / URL Encoded parameters into server language specified objects. I suppose you could throw in some SOAP, but let’s try to REST instead.

MIDDLE - Business Service and Domain Logic
This includes taking objects and doing something with them, perhaps calling a remote service.

BOTTOM - Domain Validation and Data Storage
This includes securing data consistency for objects being stored and also writing or cascading domain model relationship contracts.

Example;
A web request comes in, say a login request.

url: /login

Our gateway will accept two possible entry points. First, url encoded params for the username and password. Second, a json submitted object which has two properties; username and password. The gateway is written to be smart enough so that either one works. After the gateway as accepted the call (remember to do validation on incoming params before doing anything else), we are tossed to the Service layer. Don’t try to do too much in a gateway, save it for the service layer. The gateway is only for making sure we can accept a response and for quickly letting the user know if the params need to be changed.

For our purposes, every service layer method is wrapped with a security check. This security checks to see if the method we are invoking is allowed to run given the user asking for the request. In our gateway, we parsed a ‘sessionToken’ that we store in a request variable on the server. A request variable lives and dies on each request, so we can be sure we aren’t mudding up a user’s authority. If the service method is not marked as @Public, we verify that the user exists. We then verify that the user is also allowed to access this method, perhaps based on Role.

When the request gets passed security, we can now execute some code and do something with the request. In our case, the user wants to be authenticated. The service method will now send the username down to the dao layer. If a user is found that matches the requested username, we go on and validate password, then we validate that the user is still active, etc. If everything passes, we can create a ‘session’ for the user (which contains a ‘sessionToken’).

But, I’ve gotten ahead of myself. How does the dao layer work? Well, before we even get to the dao layer, we wrap it in an aspect, same as the security service wrapper. The dao wrapper could potentially do more validation, but more importantly will run more security. If we were creating an object (saving it from the UI) in our application, we wrapper the Crud.save method and ensure that, for instance, the object being saved is only being saved where the user is allowed to save said resource. This is done by comparing the UserSession (that we verified after the gateway and before the service layer) with the resource being saved and the ‘context’ of how the application is configured. If we want multi-tenancy, this works out great, because our service and our dao’s know nothing about the tenant-state of the object, so we can at once remove multi-tenancy if needed.

The actual DAO layer (or active record if that is your thing) must only map objects to data storage. There should be no security (app / user wise) in your DAO. Make your dao simple and dumb and wrap it if you need more.

I’m sure none of the above makes much sense… Apologies…

A quick review;

Request -> Gateway -> Security Wrapper -> Service -> Dao Wrapper -> Dao -> Data storage

Response <- Gateway <- Service <- Post-Dao Wrapper <- Dao <- Data storage


You can also add a wrapper on the gateway for responses. If your app generates an exception, you’ll need to write something nice back to the user. Otherwise, you’ll pay for it with emails that say, “Internal Server Error”… And in reality, you should (upon exception) be sending your dev team a nice email with a stack trace or whatever you need when one occurs. Nothing better than pre-empting your users problems with “Oh, we saw that you had an issue and have already fixed it.”




Published by and tagged Architecture using 856 words.