Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / Azure

[TinyERP: SPA for Enterprise Application]Cross Modules/ Domains Communication

4.67/5 (2 votes)
26 Nov 2018Apache3 min read 5.7K  
[TinyERP: SPA for Enterprise Application]Cross Modules/ Domains Communication

Overview

Please make sure that you read an overview (config and run hello sample), retrieving the list of staff (Part 1 & Part 2) and create new staff also.

As mentioned in the previous article, the whole project will be split into multiple smaller modules/ domains. This raises a new problem which is "how could those modules/domains communicate with each other", as some business flows span through more than 1 module. Let's investigate more detail, how can we solve this problem.

Note: In this series of articles, module and domain can be used interchangeably, except, a module can contain more than 1 domain run as monolithic application. So you can apply the rules both module and domain in a similar way.

Let's take a look at this scenario: with new requirement, we want our staff to be logged into system, so it means that system should create a new login account along with "create new staff" process.

And this login feature can be re-used for other in the future, such as, customer, .....

Update "Add New Staff" Feature

Let's add 2 more fields email and password into "add new staff" screen:

Image 1

We also need to update on StaffHandler, change CreateStaffRequest as below:

C#
public class CreateStaffRequest : IBaseCommand
{
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public string Email { get; set; }
	public string Password { get; set; }
	public CreateStaffRequest(string firstName, string lastName, string email, string password)
	{
		this.FirstName = firstName;
		this.LastName = lastName;
		this.Email = email;
		this.Password = password;
	}
}

Let's update Handle(CreateStaffRequest request) in StaffCommandHandler class:

C#
public CreateStaffResponse Handle(CreateStaffRequest command)
{
	this.Validate(command);
	IAccountFacade accountFacade = IoC.Container.Resolve<IAccountFacade>();
	using (IUnitOfWork uow = this.CreateUnitOfWork<TinyERP.HRM.Aggregate.Staff>()) {
		CreateAccountRequest createAccountRequest = new CreateAccountRequest
        (command.FirstName, command.LastName, command.Email, command.Password, command.Password);
		createAccountRequest.Roles.Add(new Role(SecurityRoleType.Administrator, 
        SecurityRoleType.Administrator, SecurityRoleType.Administrator, Modules.All, 
        TinyERP.Common.ItemStatus.Active));
		CreateAccountResponse createAccountResponse = 
                         accountFacade.CreateAccount(createAccountRequest);
		TinyERP.HRM.Aggregate.Staff staff = new Aggregate.Staff();
		staff.UpdateBasicInfo(command);
		staff.UpdateAccount(createAccountResponse.AccountId);
		IStaffRepository repository = IoC.Container.Resolve<IStaffRepository>(uow);
		repository.Add(staff);
		uow.Commit();
		staff.PublishEvents();
		return ObjectHelper.Cast<CreateStaffResponse>(staff);
	}
}

With a minor change at line number 4,6,7,8. We call the security module for creating a new login account with provided information from "CreateStaffRequest".

Then, a reference to this account will be updated as partial information of Staff aggregate. See line number 11.

We can see that, "creating new account" and "creating new staff" was not in the same transaction. We will talk again about this in "Saga pattern".

For TinyERP.Security package, please install it from nuget package. See TinyERP.Security (https://www.nuget.org/packages/TinyERP.Security/) for more information.

Check the reference part of TinyERP.HRM project. We can see that there are many sub-projects added also:

Image 2

Security was implemented as micro-service and also using CQRS pattern for high performance system.

System may throw some exception, ignore it for now. We will fix them in future. What we need to do now is providing the connection string for TinyERP.Security, as mentioned. This was implemented using CQRS, so we need to config both write (MSSQL) and read database (MongoDB), add below configuration into "configuration.debug.config\aggregates" sections:

XML
<add name="TinyERP.Security.Share.Context.ISecurityQueryDbContext" 
repoType="MongoDb" connectionStringName="DefaultMongoDb"></add>
<add name="TinyERP.Security.Share.Context.ISecurityDbContext" 
repoType="MSSQL" connectionStringName="DefaultMSSQL"></add>

The result for this config file was similar to:

XML
<aggregates>
	<add name="TinyERP.HRM.Context.IHRMQueryContext" repoType="MongoDb" 
connectionStringName="DefaultMongoDb"></add>
	<add name="TinyERP.HRM.Context.IHRMContext" repoType="MSSQL" 
connectionStringName="DefaultMSSQL"></add>

	<add name="TinyERP.Security.Share.Context.ISecurityQueryDbContext" 
repoType="MongoDb" connectionStringName="DefaultMongoDb"></add>
	<add name="TinyERP.Security.Share.Context.ISecurityDbContext" 
repoType="MSSQL" connectionStringName="DefaultMSSQL"></add>
</aggregates>

Please be aware and input the correct value for repoType, currently, value can be 1 of "MSSQL" or "MongoDb". We can support more repository later, such as: RavenDb, ElasticSearch, Json file, Azure Blob, ....

ISecurityQueryDbContext and ISecurityDbContext were used as read and write context into appropriated database.

We also install TinyERP.Security package into TinyERP.Api also.

Let's compile and run the app again. The UI looks like this:

Image 3

Please do not be concerned about the missing "confirm password" field. It is not important at the moment.

Click on Save and navigate back to "Staffs" page:

Image 4

It was the same as the previous part. Let's check MSSQL database, there were 2 new tables named App_Security_User_Roles and App_Security_Users.

Those was generated automatically by TinyERP.Security, open those tables, we have:

Image 5

There are 2 users:

  • contact@tranthanhtu.vn was created by system, there are many roles attached to this user. See all roles with userId is "ECB06DF4-CC65-4134-9E44-EC1AFC9EF3EF".
  • tu.tran@email.com: this was new login account that was just created.

In mongodb, open AccountSummary, we have:

Image 6

We can see that, 1 record for AccountSummary in mongodb (read-site) contains all necessary information related to the account. So in future, we do not need to join between tables to get this information, this also improves performance for your system.

There is some awareness for enterprise application development:

  • The app should be divided into smaller modules/ domains.
  • Each module/ domain should have a single purpose.
  • Each module/ domain will manage its behavior/ data and should be isolated with others.
  • Each module/ domain should access data in other module/ domain through single public interface.

For more information about the source code for this part, please have a look at https://github.com/tranthanhtu0vn/TinyERP (in feature/module_communication).

Thank you for reading!

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0