Java – How to decompose Monolithic applications into Microservices with interdependent functional modules

javamicroservicessoaweb services

I work with a large monolithic web application that has between 12-24 functional modules and these are all maintained inside a single war project structure. While the code itself is already segmented into well defined and independent packages, there are implications to deploying a single web application in this way from scaling to maintainability and so forth; very much what most industry advocates say is problematic with this type of architectural design.

I want to split this monolithic application into smaller deploy-able components, but there are a few issues that make this difficult for me to grasp.

Domain Model

Nearly all of our domain model classes have some relationship with other domain model classes from other modules. For example, a Product contains a relationship to a User that created the record and User resides in a common module while Product is in inventory.

Many microservice advocates tend to suggest that each microservice be self contained and have it's own set of resources. This would imply it's own database, generally speaking but a self contained schema in a shared database is possible. We know foreign keys are available across schema boundaries, but certain not that of databases.

The question then becomes whether Product should merely store the id or name of the User and then have the service call the User service to get user details if some end point requires that additional data rather than imposing it via foreign keys?

Web/UI

In our case, there are often times when business wants to capture additional data points that require not only a UI adjustment but a domain model adjust. So, should the Web/UI be included along with the microservice and it's domain model classes in a single deployable artifact? There is inherent coupling between this code, but the coupling between layers is based on well defined interface contracts.

I guess the question is then around scalability. If the two were deployed separately, the backend service or the Web/UI could be scaled independently where-as being deployed together wouldn't allow for such design.

Best Answer

Regarding your first question: for proper decoupling services should only store IDs of objects belonging to other services 9if they can not avoid the dependency at all). Sometimes the dependency can be extracted to a separate "hub" service whose sole role is connecting data retrieved from other services which themselves are not aware of the dependency. An example could be having a "customer service", a "product service" and a "pricing service" which would by themselves not know at all about any other, and on top of that an "order service" which could store the IDs of the customer, order and pricing information that participate in an order and implement all business logic related to order processing. This way three services can do without any external dependencies or any knowledge about any other services' domain models.

Regarding the second question, it is usually good to separate the UI from backend services and their data models. It does require some additional boilerplate code and repackaging of data, but the UI model spilling back to domain model can be much worse (messy code, forcing this mess onto other cosumers of the service's data).