This is one of the microservices for the 9Kicks project. It is written in Kotlin and uses the Spring Boot framework.
Implemented features:
Install AWS CLI and use aws configure
command to configure your aws.
Below are the settings for this project:
AWS Access Key ID: <YOUR-ACCESS-KEY>
AWS Secret Access Key: <YOUR-SECRET-ACCESS-KEY>
Default region name: ap-southeast-1
Default output format: json
In case you want to use another IntelliJ for development or use another pair of Access Key
and Secret Key
.
You can add the following environment variable in IntelliJ.
AWS_ACCESS_KEY_ID=<YOUR-ACCESS-KEY>;
AWS_SECRET_ACCESS_KEY=<YOUR-SECRET-ACCESS-KEY>;
AWS_DYNAMODB_TABLE_NAME=<DYNAMODB-TABLE-NAME>;
CORS_ORIGINS=<FRONTEND-URL-HOST>;
STRIPE_KEY=<YOUR-STRIPE-KEY>;
GO_BACKEND_URL=<BACKEND-GO-URL-HOST>
.env
In case you want to use .env
for development or use another pair of Access Key
and Secret Key
.
You can add the following environment variable.
cp .env.example .env
Input your credentials in the .env
file.
AWS_ACCESS_KEY_ID=<YOUR-ACCESS-KEY>
AWS_SECRET_ACCESS_KEY=<YOUR-SECRET-ACCESS-KEY>
AWS_DYNAMODB_TABLE_NAME=<DYNAMODB-TABLE-NAME>
CORS_ORIGINS=<FRONTEND-URL-HOST>
STRIPE_KEY=<YOUR-STRIPE-KEY>
GO_BACKEND_URL=<BACKEND-GO-URL-HOST>
Build and Run Spring Boot:
make
For any variable, function naming we use Camel Case
e.g. demoVar
, demoFunc()
For any dependency injection in Kotlin Spring Boot, we will use constructor dependency injection
class DemoController(
private val demoController: DemoRepositoryImpl
) {
fun demo(){ }
}
The project will be based on 4 major components
Controller | Define all API endpoints |
Service | Perform all the business logic |
Repository | Perform all pure CRUD |
Model | Define all Class |
For any CRUD operations, it must follow the following naming:
Operation | Naming | Example |
---|---|---|
Create | add<Object>() |
addUser() |
Read | get<Object>() |
getUser() |
Update | update<Object> () |
updateUser() |
Delete | delete<Object>() |
deleteUser() |
get()
and find()
For any function name in Service
Layer, we will use find()
.
e.g. fun findUserById()
For any function name in Repository
Layer, we will use get()
.
e.g. fun getUserById()
For any API we follow the following standard /api/v1/<controller-name>/<resources>
e.g./api/v1/account-summary/user-details
For any API we use hyphen -
to separate words
e.g./api/v1/account-summary/user-details
s
and without s
For any API that retrieves only 1 resource, we use singular form to indicate
e.g./api/v1/user/<user-id>
For any API that retrieves more than 1 resources, we use plural form, s
, to indicate
e.g./api/v1/users
all
and without all
For any functions that retrieve 1 object only, we use singular form
e.g. getUser()
For any functions that retrieve more than 1 object, we use plural form
e.g. getAllUsers()
For any model class/object, we will use Kotlin Data Class to construct
Non-Nested Class
data class Person(
val age: Int,
val height: Int
)
Nested Class
data class Person(
val age: Int,
val detail: Detail
) {
data class Detail(
val height: Int,
val weight: Int
)
}
For any object that we receive from remote calls (backend, frontend, database),
we create a DTO
object for it.
Beware: It is different from the main model class UserDTO != User
For example:
We want to send an User
object from backend
to frontend - Account Summary
.
We define a UserDTO
:
data class UserDTO(
val age: Int
)
It encapsulates some data that frontend - Account Summary
does not need to know, e.g. creditCardNumber
For any object that is received as a response. We use place response
after the object name.
e.g. UserResponse
For any object that is being sent as a request. We use place request
after the object name.
e.g. UserRequest