Skip to content
/ ems Public

Entity Management Service - COMS4156 MVC Masters

License

Notifications You must be signed in to change notification settings

nehCG/ems

Repository files navigation

Entity Management Service

A comprehensive service that can be integrated by clients to manage all aspects related to their entities.

license Build Status codecov

Table of Contents

Build and Run the Service using Docker

Prerequisites

  1. Ensure you have Docker installed on your machine.
  2. Ensure you have Docker Compose installed.

1. Clone the Repository

If you haven't already, clone the repository to your local machine.

2. Build the Docker Image

Navigate to the directory containing the Dockerfile and run:

docker build -t ems-image .

This will build a Docker image named ems-image from the Dockerfile in the current directory.

3. Run the Service using Docker

Navigate to the directory containing the docker-compose.yml and run:

docker-compose up

Then give it a couple of minutes because MySQL might take a little while to be ready, especially on the first run when it's initializing data.

4. Access the Service

Then, the service will run on http://localhost:8080/ems.

Troubleshooting

  • If you encounter port conflicts (e.g., port 8080 is already in use), either stop the service using the port or bind the application to a different port when running the Docker container.
  • Ensure your Docker daemon is running before executing Docker commands.
  • Check application logs in the Docker container for any issues related to the Spring Boot application.

About the Client App

Our client app is an application tailored for pre-K school internal management. It provides a centralized platform for administrators, teachers, and other school roles to collaborate and manage various aspects of the pre-K education experience. Key Features:

  • Announcement board: the announcement board uses CRUD APIs from /announcement in our service. Pre-K school teachers and administrators can post announcements, which will be visible to all Pre-K school employees. The announcement board serves as an effective notification platform.

  • Role management: the authorization of each role can be customized. This functionality uses /role/list, /role/toAddOrUpdateRolePage, /role/delete, and /module/toAddGrantPage. The administrators or other authorized roles are able to manage the authorization of each role in the Pre-K school. They are also able to create/delete/edit each role. This role management functionality helps to manage the scope of roles within Pre-K school.

  • User management: users can be added, edited, or removed by authorized entities. The user management uses CRUD APIs from /user. The administrators or other authorized roles are able to manage all employees within the Pre-K school. This user management functionality provides the flexibility for adding new teachers or employees.

  • User setting: users are able to update their password. This functionality uses /updatePwd from /user in our service After login, individual can change the default password to their choice. This user setting helps Pre-K school individual to customize their password and provides data security.

The users of our app can have comprehensive role management and user management functionalities, while before they may only can communicate using their internal app.

Access the Client App

Once you build and run the Service, the client app will run on http://localhost:8080/ems/index automatically.

You can use our admin account to log in and use our client.

Username: admin
Password: 123456

How to Build Your Own Client Using the Service

Our front-end code files are stored under src/main/java/resources. You can make appropriate modifications or refactor the entire front-end. If you want to develop more front-end functions, you can refer to our API Documentation.

Unit Tests of the Service

Run all unit tests

./mvnw test -Dcheckstyle.skip=true -Dspotbugs.skip=true

If you want to generate a test coverage report, you can choose the following two commands:

Clean old build artifacts, run tests, and verify the package is correct.

./mvnw clean verify -Dcheckstyle.skip=true -Dspotbugs.skip=true

Clean old build artifacts, run tests, create the package, and install it to the local Maven repository.

./mvnw clean install -Dcheckstyle.skip=true -Dspotbugs.skip=true

Our unit tests have 99.54% code coverage. Codecov report

Integration Tests of the Service

We employed the Big Bang Integration Testing approach, where the integration of multiple units are tested simultaneously. Then, the entire system is tested as a whole.

Internal Integration Test

In this phase, we focused on two key integration. The first one is the interaction between Controller Layer and Service Layer, which involved mocking the HTTP request and allow the service layer to process. The second one is the interaction between Service Layer and Repository Layer, which involved mocking the database. After these targeted tests, we proceeded to the External Integration Test, where we examined the entire service through RESTful API testing.

External Integration Test

Our service has two external components, which are RESTFul API and the MySQL database. Thus, we tested the interaction between the Mapper files and the external MySQL database. Next, we used @RestTemplate to call each API endpoints, where the service is tested as a whole.

Both Internal and External Integration Tests are located in src/test/java, which will be run automatically during CI. The folder containing external integration tests is excluded for the 'mvn test' build during CI.

System Tests Corresponding to API

System-level Tests of every API Entry Point

Please see details on below API Documentation section.

System-level Tests of Multiple Clients

We use the Runner in Postman to mock multiple clients are sending requests simultaneously.

We performed several API functional and performance tests that may face multiple clients requesting and high concurrency. You can check details here.

Login: http://localhost:8080/ems/user/login

Get all users: http://localhost:8080/ems/user/all

Get all announcements: http://localhost:8080/ems/announcements/all

End-to-End Testing Checklist

Please see details in E2E Testing Checklist

Multiple Simultaneous Client Instances Tests

To ensure robust performance under high load, we used Apache JMeter for performance testing on key endpoints.

Our focus was on scenarios likely to experience heavy traffic:

  • Concurrent User Logins: Tested the system's response to 100 simultaneous user logins View Screenshot
  • Bulk Announcement Posting: Assessed system stability with 100 announcements posted concurrently View Screenshot

Alongside Apache JMeter tests, we conducted real-world scenario tests to validate our system's performance and responsiveness:

  • Manual Multi-Instance Testing: Simulated user activities by opening multiple browsers, logging in as different users, and performing actions like posting announcements and adjusting role assignments.

  • Real-Time Responsiveness: Verified that changes made by one user (e.g., role adjustments) were immediately reflected for other users, ensuring real-time data consistency and dynamic interaction.

Style Checker

We use CheckStyle with Sun Checks

Run Checkstyle

./mvnw checkstyle:check

Our checkstyle results are clean. Checkstyle report

Bug Finder

We use SpotBugs Bug Detector

Run SpotBugs

./mvnw spotbugs:check

Our Spotbugs results are clean. SpotBugs report

To generate report, run ./mvnw clean compile site

API Documentation

FrontEnd Entry Points

Base URL: http://localhost:8080/ems

GET: /index

  • Description: Display the login page.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

GET: /main

  • Description: Display the main page of the service.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

GET: /welcome

  • Description: Display the welcome pag.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

User Management Entry Points

Base URL: http://localhost:8080/ems/user

POST /login

  • Description: Authenticate a user.
  • Request Params:
    • userName(String): The username of the user.
    • userPwd(String): The password of the user.
  • Response: UserModel object for valid credentials.
  • Status Codes:
    • 200 OK: Authentication successful.
    • 400 BAD REQUEST: If userName or userPwd is empty, or if credentials are incorrect.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

POST /updatePwd

  • Description: Update the password of an authenticated user.
  • Request Params:
    • userId(Integer): The ID of the user.
    • oldPassword(String): The current password of the user.
    • newPassword(String): The new password for the user.
    • repeatPassword(String): Confirmation of the new password.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: Password updated successfully.
    • 400 BAD REQUEST: If userId does not exist, oldPassword is incorrect, or new passwords do not match/are empty.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

POST /add

  • Description: Register a new user.
  • Request Params:
    • userName(String): The username of the user.
    • email(String): The email of the user.
    • phone(String): The phone number of the user.
  • Request Body: User object.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: User added successfully.
    • 400 BAD REQUEST: If input parameters are invalid or missing, or if the username already exists.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

POST /update

  • Description: Update an existing user's information.
  • Request Params:
    • id(Integer): The ID of the user.
    • userName(String): The username of the user.
    • email(String): The email of the user.
    • phone(String): The phone number of the user.
  • Request Body: User object.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: User updated successfully.
    • 400 BAD REQUEST: If the User object is invalid, the user does not exist, or if the updated username already exists.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

POST /delete

  • Description: Delete one or more users.
  • Request Params:
    • id(Integer): The ID of the user.
  • Request Body: Array of user ids.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: Users deleted successfully.
    • 400 BAD REQUEST: If the ids array is empty or if any of the ids do not correspond to existing users.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

GET /list

  • Description: Retrieve a list of users based on provided parameters.
  • Request Params:
    • page (Integer): The page number. Default: 1
    • pageSize (Integer): The number of users per page. Default: 10
    • username (String): The username to filter by. Optional
    • email (String): The email address to filter by. Optional
  • Response: Map with user information.
  • Status Codes:
    • 200 OK: Request successful.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

GET /index

  • Description: Direct to the main user page.
  • Response: A string representing the path the main user management page.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

GET /toPasswordPage

  • Description: Direct to the password management page.
  • Response: A string representing the path to the password management page.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

GET /toAddOrUpdateUserPage

  • Description: Direct to the page for adding or updating a user.
  • Request Params:
    • roleId (Integer): The ID of the user to be updated, or null if adding a new user. Optional
  • Response: A string representing the path to the view for adding a new user or updating an existing one.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

Role Management Entry Points

Base URL: http://localhost:8080/ems/role

GET /queryAllRoles

  • Description: Retrieve all roles associated with a given user ID.
  • Request Params:
    • roleId (Integer): The role ID used for querying roles. Default: 1
  • Response: A list of maps, each representing a role and its information.
  • Status Codes:
    • 200 OK: Request successful.
    • 500 Internal Server Error: The server encountered an error

GET /list

  • Description: Retrieve a list of roles based on provided parameters.
  • Request Params:
    • roleName (Integer): The name of the role being queried. Default: 1
  • Response: Map with user information.
  • Status Codes:
    • 200 OK: Request successful.
    • 500 Internal Server Error: The server encountered an error

POST /add

  • Description: Add a new role into the system.
  • Request Params:
    • roleName(String): The name of the role.
  • Request Body: Role object.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: Role added successfully.
    • 400 BAD REQUEST: If input parameters are invalid or missing, or if the rolename already exists.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error

POST /update

  • Description: Update an existing role information in the system.
  • Request Params:
    • roleId(Integer): The ID of the role.
    • roleName(String): The name of the role.
  • Request Body: Role object.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: Role updated successfully.
    • 400 BAD REQUEST: If the Role object is invalid, the roleID does not exist, or if the updated rolename already exists.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error

POST /delete

  • Description: Delete a role from the system.
  • Request Params:
    • roleId(Integer): The ID of the role.
  • Request Body: The role id.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: Role deleted successfully.
    • 400 BAD REQUEST: If the roleId is empty or if the roleId does not correspond to existing users.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error

POST /addGrant

  • Description: Grant permissions to a specific role
  • Request Params:
    • roleId(Integer): The ID of the role.
    • mId(Integer): ModuleID that is to be granted to the role.
  • Request Body: The roleId and Array of module mIds.
  • Response: Success message for a valid request.
  • Status Codes:
    • 200 OK: Role deleted successfully.
    • 400 BAD REQUEST: If the roleId is empty or if the roleId does not correspond to existing users.
    • 300 CUSTOM CODE: Represents business logic errors.
    • 500 Internal Server Error: The server encountered an error

GET /index

  • Description: Direct to the role index page.
  • Response: A string representing the path to the role index view.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

GET /toAddOrUpdateRolePage

  • Description: Direct to a page for adding or updating a role.
  • Request Params:
    • roleId(Integer): The ID of the role to edit, or null for adding a new role.
  • Response: A string representing the path to the role index view.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

Module Operations Entry Points

Base URL: http://localhost:8080/ems/module

GET /queryAllModules

  • Description: Retrieve all modules based on the given role ID.
  • Request Params:
    • roleId (Integer): The role ID used for querying modules. Default: 1
  • Response: List of TreeModel representing Module Information.
  • Status Codes:
    • 200 OK: Request successful.
    • 500 Internal Server Error: The server encountered an error

GET /toAddGrantPage

  • Description: Directs the user to the page for adding grants to a role.
  • Request Params:
    • roleId (Integer): The ID of the role to add grants to. Default: 1
  • Response: The path to the "grant" view under the "role" directory.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

Shared Space Entry Points

Base URL: http://localhost:8080/ems/announcement

POST /post

  • Description: Add a new shared data entry.
  • Request Body: SharedDataModel object, with non-null subject and content.
  • Response: "Shared data added successfully!" for valid input.
  • Status Codes:
    • 200 OK: Successfully added.
    • 400 BAD REQUEST: If the SharedDataModel object is null, or subject or content is null/empty.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

GET /{id}

  • Description: Retrieve a specific shared data entry by its ID.
  • Path Variable: id - The ID of the shared data entry.
  • Response: SharedDataModel object for valid ID.
  • Status Codes:
    • 200 OK: Successfully retrieved.
    • 400 BAD REQUEST: If id does not exist.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

GET /all

  • Description: Retrieve all shared data entry in the database.
  • Response: Map with SharedDataModel objects.
  • Status Codes:
    • 200 OK: Successfully retrieved.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

PUT /update/{id}

  • Description: Update a specific shared data entry by its ID.
  • Path Variable: id - The ID of the shared data entry.
  • Request Body: SharedDataModel object, with non-null uid, subject and content.
  • Response: "Shared data updated successfully!" for valid input and ID.
  • Status Codes:
    • 200 OK: Successfully updated.
    • 400 BAD REQUEST: If id does not exist, or the SharedDataModel object is null, or uid is null, or subject or content is null/empty.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

DELETE /delete/{id}

  • Description: Delete a specific shared data entry by its ID.
  • Path Variable: id - The ID of the shared data entry.
  • Response: "Shared data deleted successfully!" for valid ID.
  • Status Codes:
    • 204 NO CONTENT: Successfully deleted.
    • 400 BAD REQUEST: If id does not exist.
    • 500 Internal Server Error: The server encountered an error
  • Postman API tests:

GET /index

  • Description: Direct to the shared space index page.
  • Response: A string representing the path to the shared space index view.
  • Status Codes:
    • 200 OK: Page loaded successfully.
    • 404 Not Found: Cannot find the request page.
    • 500 Internal Server Error: The server encountered an error

Change In API Implementation From Proposal

We decided to make the following changes to our API implementation, which are different from our proposal:

  1. Add role management:

    Role management allows for the definition of roles, each with specific permissions. This is crucial in an entity management system to control who can perform certain actions on entities. For data protection, different roles should have different levels of access to sensitive information. Role management ensures that only authorized individuals can view or modify specific entities, contributing to data security.

  2. Remove customizable workflow:

    Our entity management system focuses on handling and organizing data related to entities (e.g., information of the entities, roles) and we decided not to add the complexity of managing intricate workflows.

  3. Remove multi-language translation:

    We found that many browsers on the market support translation functions. For example, Chrome browser supports the use of Google Translate. Therefore, we did not introduce translation functionality into our service and focused more on core management functionality.

Persistent Data Storage of our Service

Based on the provided docker-compose.yml, the MySQL database container is set up to ensure data persistence through Docker volumes. Specifically, the volumes directive under the mysql-db service maps db-data to /var/lib/mysql, which is the default location where MySQL stores its data files. By doing so, any data changes made within the database are stored in this Docker-managed volume, named ems_db-data. As a result, even if the MySQL container is stopped, deleted, or recreated, the data remains intact and can be reattached to a new instance of the MySQL container.

This volume-driven approach guarantees the resilience and persistence of data across container lifecycle events, ensuring that our database changes are consistently retained and not ephemeral.

In the course of our comprehensive System-level Testing for the Service, we rigorously executed all CRUD (Create, Read, Update, Delete) operations utilizing Postman as our primary testing interface. For each individual operation, there was a direct and verifiable reflection in the MySQL database. This consistent alignment between the API calls and the resulting database modifications unequivocally confirms the robust interaction and integration of our service layer with the persistent data layer. Our meticulous testing approach ensures that our application not only responds to API requests as expected but also effectively manages the underlying data in a reliable and consistent manner.

Third Party Code References

We use some third-party code in our frontend scripts under src/main/resources/public

Font Awesome 4.7.0

  • Purpose: Provides scalable vector icons that can instantly be customized — size, color, drop shadow, and anything that can be done with the power of CSS.
  • License: SIL OFL 1.1 for the font, and MIT License for the CSS.
  • Website: Font Awesome
  • Usage Example: Icons are used in buttons, forms, and as standalone graphics.

jq-Module

  • Purpose: A lightweight module for handling DOM manipulation, event handling, and AJAX.
  • License: MIT License.
  • Documentation: jq-Module GitHub
  • Usage Example: Used for creating dynamic content and managing DOM elements efficiently.

jQuery 3.4.1

  • Purpose: A fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, and animation much simpler with an easy-to-use API that works across a multitude of browsers.
  • License: MIT License.
  • Website: jQuery
  • Usage Example: AJAX calls for asynchronous data fetching, and manipulating HTML elements.

Layui v2.5.5

  • Purpose: A UI framework for building web interfaces, providing a range of components and widgets.
  • License: MIT License.
  • Website: Layui
  • Usage Example: Used for building the UI layout and integrating various UI components like tables, forms, etc.

Licensing and Compliance

All the libraries used in this project are under MIT License, except for Font Awesome which is under SIL OFL 1.1 for the font, and MIT License for the CSS. We ensure compliance with these licenses in our use of these libraries.