Task definition You should create service for aggregating users data from multiple databases. Application must provide single rest endpoint for selecting data, selected from all databases GET /users Success response body example:
[
{
"id": "example-user-id-1",
"username": "user-1",
"name": "User",
"surname": "Userenko"
},
{
"id": "example-user-id-2",
"username": "user-2",
"name": "Testuser",
"surname": "Testov"
}
]Application must have declarative configuration for specification of data sources, maximal quantity of data sources is infinite (when need to add/remove new datasource only yaml configuration must be edited): data-sources:
- name: data-base-1
strategy: postgres #this property is optional, only if you implements multiple database type support (Postgres, ORACLE, MySQL...)
url: jdbc://.....
table: users
user: testuser
password: testpass
mapping:
id: user_id
username: login
name: first_name
surname: last_name
- name: data-base-2
strategy: postgres
url: jdbc://.....
table: user_table
user: testuser
password: testpass
mapping:
id: ldap_login
username: ldap_login
name: name
surname: surnameStrong requirements • Use Spring Boot for writing this application • Use OpenApi contracts specification for declare endpoint definition • Project must be pushed to git repository with readme file
Optional requirements • Add integration test using testcontainers • Add selecting filters in api and queries
TestTask -| ------------| -- testtask-api ------------| -- testtask-service
testtask-api - module contains test-api.yaml. You may change the contract specification and update the API and model automatically. Alternatively, you may use SwaggerEditor to generate API, server, and client code (and I used it to create UsersApiController)
It needs to rebuild the application to update the API and model. See the Installation section.
testtask-service - module with the implementation.
Some words about the implementation:
- Data sources - as I need to use dynamic config, I don't consider the usage of the JPA repositories and injected data source beans in the app configuration. Instead, I added properties config to be able to create data sources dynamically.
- Perfomance - I understand there are better solutions than this, which can be overloaded with huge amounts of data. On the other hand, as we use the sync method and JSON as responses, I don't expect big volumes of information; otherwise, we need to use another approach (pipes, streams, or so). Datasource initialization is better to move outside the module with AOP or additional bean definitions. I assumed that all database tables contain the same number of rows. Otherwise, SQL maybe optimized to use
select field1, field2, field3....instead of
select *- Test containers - I added support to the tests but did not try to use more than one docker due to slow work. It was tested with Postres/MySQL separately.
- Pagination - as I can not (or don't know how) use the Pagable interface, I see the possible solution to apply limits and offsets on the accumulated result list. I did not add to the implementation because I was unsure the solution was okay. From my calculation, if we have a result list with four fields and one million result records, it will take approximately 0.5G memory to operate, not so much so that if we are sure we have no overload, then it can be applied
For building and running the application you need:
Rebuild the api
cd TestTask
mvn clean installThere are several ways to run a Spring Boot application on your local machine. One way is to execute the main method in the com.testmethod.TestTaskApplication class from your IDE.
Alternatively you can use the Spring Boot Maven plugin like so:
cd TestTask/testtask-service/
mvn spring-boot:runSwagger UI configuration autogenerated with the Swagger Editor default port and path is on application.properties file, you may edit it on your own
springdoc.api-docs.path=/api-docs
server.servlet.contextPath=/
server.port=8080default url is localhost:8080/ if you start application locally
There are several ways to run a Spring Boot application on your local machine. One way is to execute the main method in the com.testmethod.TestTaskApplication class from your IDE.
Alternatively you can use the Spring Boot Maven plugin like so:
cd TestTask
mvn testOutput example
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 12.152 s - in com.testmethod.module.UserModuleTest
2024-02-08 17:36:08,387 INFO [SpringContextShutdownHook] o.s.s.c.ThreadPoolTaskExecutor - Shutting down ExecutorService 'applicationTaskExecutor'
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for TeskTask 0.0.1-SNAPSHOT:
[INFO]
[INFO] TeskTask ........................................... SUCCESS [ 0.002 s]
[INFO] testtask-api ....................................... SUCCESS [ 1.548 s]
[INFO] testtask-service ................................... SUCCESS [ 15.708 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.387 s
[INFO] Finished at: 2024-02-08T17:36:08+02:00
[INFO] ------------------------------------------------------------------------Some free for all license.