Layering in Java Webapps – My Final Version

What a good layering solution should do

It must handle the following problems:

1. Dividing a system into layers based on modularization principles, such as single-direction dependency, limited entry of components and so on. 

2. Compatible with modern dependency management tools such as Maven 

3. Allowing for evolving into a distributed system in the future 

Here I present my final version of layering after so many years’ development of java webapps.


Layers

layering

Components’ Responsibilities

Component Responsibility Naming Conventions
Biz Layer – Neutral Services  Most reusable core business logic(CRUD, Biz Modelling etc.)

Bean: Xxx

Facade: XxxService

Repository: XxxRepos/ XxxDAO

Application Layer – Front-End Managers The complete logic of use cases for front end users (customers)

Bean: FoXxx

Facade: FoXxxManager

Application Layer – Back-Office Managers The complete logic of use case for back office users (admin, staff etc.) 

Bean: BoXxx

Facade: BoXxxManager 

Application Layer – Partner System Service Providers Remote services for partner systems which belong to the same company

Bean: SsXxx(Ss= Some System)

Facade: SsRpc

Web Layer – Front-End Controllers

Web MVC controllers to serve front end users with browsers

Presentation only. No biz at all

Bean: N/A 

Facade:  FoXxxController

Web Layer – Front-End Web Services

Web Services to serve front end users’ rich clients (desktop/phone app)

Presentation only. No biz at all 

Bean: N/A

Facade: FoXxxResource/FoXxxSoap

Web Layer – Back-Office Controllers

Web MVC controllers to serve back office users with browsers

Presentation only. No biz at all

Bean: N/A

Facade: BoXxxController 

(Continue)

Component Bean DTO Dependency on Layer Below
Biz Layer – Neutral Services 

Fine-grained entity

Data oriented 

Beans as DTOs 

N/A
Application Layer – Front-End Managers

Very coarse-grained

Crossing multiple biz entities 

User oriented

Request/Response pairs as DTOs

Response has error props

Order order = convertSomehow(foNewOrderRequest); 

authService.permissionCheck(currentUserId…) ;

orderService.saveNewOrder(order);

itemService.doAnotherThing(…);

FoOrder foOrder = combineSomehow(order, item, permission);

return FoResponse.success(foOrder); 

Application Layer – Back-Office Managers

Very coarse-grained

Crossing multiple biz entities

User oriented

Similar with above

Similar with above
Application Layer – Partner System Service Providers

Fairly fine-grained 

Partner system oriented 

Beans as DTOs

Order order = convertSomehow(ssOrder); 

itemService.doAnotherThing();

SsOrder ssOrder = addOrRemoveProp(order);

return ssOrder; 

Web Layer – Front-End Controllers N/A N/A

FoNewOrderRequest foNewOrderRequest = webFormToObj(httpRequest); 

FoResponse foResponse  = foOrderManager.doSth(currentUserId, foNewOrderRequest);

httpResponse.putSomehow("data",  foResponse.getData());

httpResponse.putSomehow("error",  foResponse.getError());

Web Layer – Front-End Web Services N/A N/A

FoNewOrderRequest foNewOrderRequest = jsonToObj(jsonRequest); 

FoResponse foResponse  = foOrderManager.doSth(currentUserId, foNewOrderRequest);

return toRestResponse(foResponse); 

Web Layer – Back-Office Controllers N/A N/A Similar with "Front-End Controllers"

Be Pragmatic (Anti-Patterns)

1. Managers are allowed to call repositories(DAOs) directly. It is annoying to have to have a same-name method in XxxService to wrap  its counterpart in XxxRepo.

2. BoXxx/BoRequest/BoResponse should rely on and be allowed to extend FoXxx/FoRequest/FoResponse,  and Back office Controllers should be allowed to call Front end managers.  This is because  back office users are also users.  If you don’t allow this "slight violation", you may end up write tons of duplicate code in Bo Managers. 

3. Web layer annotations such as @XmlElement should be allowed to put on application layer beans and DTOs.  If not, you will have to create a lot of duplicate beans/DTOs on web layer. 


Maven Projects

ideal-maven-projects

(Note: webapp must have "runtime" dependency on impl_fo and impl_bo, which has not been shown in the diagram.)

This is a ideal version of separation.  The problem is it has too many maven projects.   

A pragmatic version


Support for Distributed System Design

1. The maven project "intf-pso" is used as the RPC client stub for partner systems

2. The maven project "intf-fo" can be used as the RPC client stub for web service clients if they are also written in Java

3. The web layer can be an independent system immediately without any compilation error since they only rely on app-layer interfaces at compile time.  Just let intf-fo and intf-bo be its client stub.  In advance, the web layer’s components can each be an independent system. 

If the web layer is transferred to another team

If the web layer is going to be transferred to another team in your organisation, the app layer should go with it. Otherwise, a small change will involve two team’s work, which is unbearable.

They will now be responsible for all the user-specific cases and considered as your partner system. 

web-another-team

The original FO and BO managers should not rely on the biz services any more.  Instead, you must create pso interfaces to wrap them and provide services to the original managers.  


A demo webapp

For a demo webapp with most of the components describe, see  this project on github

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.