Call Center application has been implemented using following technologies:
- Spring Boot as a backend REST micro-service.
- MongoDB as a persistence storage
- RabbitMQ for queuing calls.
Pre-requisites:
The micro-service contains the following components:
- Employee Controller - Allows for creation and fetch details of employees
- Employee Service - Business logic to process controller requests
- Employee Repository - Persistence layer for storing domain objects.
- Call Handler Controller - Allows for dispatching and ending call
- Call Handler Service - Business logic to process incoming calls
- Call Info Repository - Persistence layer to store call logs
- User makes a
POST
request to create an employee of one of the allowed types -DIRECTOR
,MANAGER
,RESPONDENT
- Employee service handles the call and processes the request
- Employee object is persisted to mongodb's collection
- Caller makes a
POST
request to place a call to call center - Call handler service creates an entry in the database of the with the call information and marks
queued
boolean properties astrue
. - A scheduler job runs at a configurable time checking for available employee. If an employee is availed to handle the call.
6A) Call handler service will
dequeue
the call from the queue and proceed to assign it to the employee. This process will also mark the employee's status as "ON_CALL".
Call center application uses a number of open source projects:
- Spring Boot - Creating spring based application for the web!
- RabbitMQ - Messaging queue for internet scale systems
- MongoDB - NoSQL data storage.
- Docker - great for containerzing your app to be ran on multiple platforms without worry for underlying OS.
Running the application requires docker installed locally. The application also uses docker compose to run multi-container. See Install Docker Compose | Docker Documentation
Given that the application uses MongoDB and RabbitMQ broker, it has been packaged with docker compose file which starts up docker container for both of those dependencies. The application is setup to talk to those two containers.
Navigate to the root of the project
$ cd callcenter
Cleaning and building the project also runs unit test and integration test for the application.
For integration test, it spins up an embedded mongodb instance and a Apache QPid AMQP broker with in-memory store for queueing the calls. This command below also bundles up the whole application as fat jar to be ran standalone. NOTE: this doesn't bundle up mongo and rabbitmq.
$ ./gradlew clean build
In order to start up all the three containers: callcenter, mongodb, rabbitmq. The command below starts all the required dependencies before starting the application.
$ docker compose up -d
Once the container is up and running. It will be available on:
$ localhost:8080
-
Creating an employee
Request
curl --request POST \ --url http://localhost:8080/callcenter/employees/create \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data '{ "firstName": "John", "lastName": "Doe", "role": "DIRECTOR" }'
Response
{ "id": "5b1c4bf32ab79c000134b9b1", "firstName": "John", "lastName": "Doe", "role": "DIRECTOR", "status": "AVAILABLE" }
-
Getting a list of employees by role
- Supported types:
RESPONDENT
,MANAGER
, andDIRECTOR
Request
curl --request GET \ --url 'http://localhost:8080/callcenter/employees?role=DIRECTOR'
Response
{ "content": [ { "id": "5b19c58b2ab79c0001378b30", "firstName": "098769fd-cae0-4ef0-b9ec-f5b5529df5ed", "lastName": "Patel", "role": "DIRECTOR", "status": "AVAILABLE" }, { "id": "5b19c58c2ab79c0001378b31", "firstName": "c157437c-6ee8-4d39-960b-554c8ee5db65", "lastName": "Patel", "role": "DIRECTOR", "status": "AVAILABLE" }, { "id": "5b1be3fe2ab79c00019401b2", "firstName": "c40343e8-27dd-495b-af87-8b765ccd9a8b", "lastName": "Patel", "role": "DIRECTOR", "status": "AVAILABLE" }, { "id": "5b1be3fe2ab79c00019401b3", "firstName": "b041b016-8eff-436a-b1b9-b125bae1940e", "lastName": "Patel", "role": "DIRECTOR", "status": "AVAILABLE" }, { "id": "5b1c4bf32ab79c000134b9b1", "firstName": "John", "lastName": "Doe", "role": "DIRECTOR", "status": "AVAILABLE" } ], "pageable": { "sort": { "sorted": false, "unsorted": true }, "pageNumber": 0, "pageSize": 20, "offset": 0, "unpaged": false, "paged": true }, "totalElements": 5, "totalPages": 1, "last": true, "sort": { "sorted": false, "unsorted": true }, "first": true, "numberOfElements": 5, "size": 20, "number": 0 }
- Supported types:
-
Dispatch a call Response
curl --request POST \ --url http://localhost:8080/callcenter/callhandler/dispatchCall \ --header 'content-type: application/json' \ --data '{ "callerId":"+f064e60d-35b1-482c-a567-d3779cecd53d", "callerName": "CALLNAME-35e8b8b0-6cb3-11e8-91cf-974ff98e0897" }'
Response
{ "id": "5b1be4272ab79c00019401b4" }
- Get queued calls Request
curl --request GET \ --url http://localhost:8080/callcenter/callhandler/queuedCalls
Response
{ "content": [ { "id": "5b1d2a432ab79c0001e63741" } ], "pageable": { "sort": { "sorted": false, "unsorted": true }, "pageSize": 20, "pageNumber": 0, "offset": 0, "unpaged": false, "paged": true }, "last": true, "totalPages": 1, "totalElements": 1, "sort": { "sorted": false, "unsorted": true }, "first": true, "numberOfElements": 1, "size": 20, "number": 0 }
- End a call Request
curl --request GET \ --url http://localhost:8080/callcenter/callhandler/endcall/5b1d2cb62ab79c000171e27f
Response
{ "duration": "1 minutes", "callerId": "+485cca3b-a64d-418b-9e66-ed9b460cd284", "callerName": "CALLNAME-3a995d90-6cb5-11e8-91cf-974ff98e0897" }
The proect uses Gradle as a build tool. It uses the gradle wrapper functionality so that the user does not have to have gradle installed on their system.
|-- main
| |-- java
| | `-- com
| | `-- callcenter
| | |-- ApplicationBootstrap.java
| | |-- Constants.java
| | |-- RabbitMQConfiguration.java
| | |-- controller
| | | |-- CallController.java
| | | |-- EmployeeController.java
| | | |-- request
| | | | |-- CallRequest.java
| | | | `-- EmployeeRequest.java
| | | `-- response
| | | |-- CallEndedResponse.java
| | | |-- CallResponse.java
| | | `-- EmployeeResponse.java
| | |-- dao
| | | |-- DataModelConstants.java
| | | |-- model
| | | | |-- CallInfo.java
| | | | `-- Employee.java
| | | `-- repository
| | | |-- CallInfoRepository.java
| | | `-- EmployeeRepository.java
| | |-- exception
| | | |-- CallCenterServiceException.java
| | | `-- RestResponseEntityExceptionHandler.java
| | `-- service
| | |-- CallHandlerService.java
| | |-- EmployeeService.java
| | `-- impl
| | |-- DefaultCallHandlerService.java
| | `-- DefaultEmployeeService.java
| `-- resources
| `-- application.yml
- package:
com.callcenter
root dir containsApplicationBootstrap.java
which runs the application - package:
com.callcenter
'sRabbitMQConfiguration.java
contains rabbitmq broker connection configuration to be used byspring-data-amqp
- package:
com.callcenter.controller
contains the controller class for the application. These are the main entry points for rest calls. The subpackages for containsrequest
andresponse
object types. - package:
com.callcenter.service
contains the service layer, which encapsulates the business logic for the application. This is where the application puts the call on rabbitmq queue, assigns a call to available employee etc. - package:
com.callcenter.dao
contains the dao layer of the application. The exit point for data sinks. This is wherespring-data-mongodb
comes in to play. - package:
com.callcenter.exception
contains utils class for exceptions thrown by the service. It uses spring's@ControllerAdvice
to translate exceptions thrown by the service into a http status code. src/main/resources
containsapplication.yml
which stores the application configuration properties. All the properties are externalized so that they can be set by passing via environment variables.
`-- test
|-- java
| `-- com
| `-- callcenter
| `-- test
| |-- integration
| | |-- BaseIntegrationTest.java
| | |-- dao
| | | `-- repository
| | | |-- CallInfoRepositoryTest.java
| | | `-- EmployeeRepositoryTest.java
| | |-- service
| | | |-- CallHandlerServiceIntegrationTest.java
| | | |-- EmployeeServiceIntegrationTest.java
| | | `-- HandleQueuedCallsSchedulerTest.java
| | `-- utils
| | `-- EmbeddedAMQPBroker.java
| `-- unit
| |-- controller
| | |-- CallControllerTest.java
| | `-- EmployeeControllerTest.java
| `-- service
| `-- impl
| |-- DefaultCallHandlerServiceTest.java
| `-- DefaultEmployeeServiceTest.java
`-- resources
|-- initial-config.json
`-- integration-test.properties
- package:
com.callcenter.test.integration
contains integrations test for the application. The integration test runs an embedded mongodb instance and an embedded amqp broker for running end to end test on the service. Each component is test individuals in isolation, plus it has been tested in integration with others. - package:
com.callcenter.test.unit
contains unit test for each component. This package contains mock test for all the components. src/test/resources
containsintegration-test.properties
which is used to override environment configuration properties for the application. It also containsinitial-config.json
which is used by the embedded AMQP broker to configure itself.