Implementation of getAll and create products endpoints.
This commit is contained in:
11
bruno-rest/GiteaActionsWorkshop/Get all products.bru
Normal file
11
bruno-rest/GiteaActionsWorkshop/Get all products.bru
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
meta {
|
||||||
|
name: Get all products
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{url}}/api/products
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
9
bruno-rest/GiteaActionsWorkshop/bruno.json
Normal file
9
bruno-rest/GiteaActionsWorkshop/bruno.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "GiteaActionsWorkshop",
|
||||||
|
"type": "collection",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
".git"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
vars {
|
||||||
|
url: http://localhost:8080
|
||||||
|
}
|
||||||
@@ -1,12 +1,45 @@
|
|||||||
package com.example.demo.application.product
|
package com.example.demo.application.product
|
||||||
|
|
||||||
|
import com.example.demo.domain.core.error.FunctionalError
|
||||||
|
import com.example.demo.domain.product.inputport.ProductInputPort
|
||||||
import com.example.demo.domain.product.model.Product
|
import com.example.demo.domain.product.model.Product
|
||||||
import com.example.demo.domain.product.port.ProductPort
|
import com.example.demo.domain.product.model.ProductType
|
||||||
|
import com.example.demo.domain.product.outputport.ProductOutputPort
|
||||||
|
import com.github.michaelbull.result.*
|
||||||
|
import com.github.michaelbull.result.coroutines.coroutineBinding
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class ProductUseCases(
|
class ProductUseCases(
|
||||||
private val productPort: ProductPort
|
private val productOutputPort: ProductOutputPort
|
||||||
) {
|
) : ProductInputPort {
|
||||||
fun getAll(): List<Product> = productPort.getAll()
|
override suspend fun getAll(): Result<List<Product>, FunctionalError> = productOutputPort.getAll()
|
||||||
|
.mapError { FunctionalError(it.message) }
|
||||||
|
|
||||||
|
// override suspend fun create(name: String, type: ProductType): Result<Product, FunctionalError> {
|
||||||
|
// if (name.isBlank()) {
|
||||||
|
// return Err(FunctionalError("Product name should be set."))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val newProduct = Product(id = UUID.randomUUID(), name, type)
|
||||||
|
// return productOutputPort.save(newProduct)
|
||||||
|
// .mapError { FunctionalError(it.message) }
|
||||||
|
// .map { newProduct }
|
||||||
|
// }
|
||||||
|
|
||||||
|
override suspend fun create(name: String, type: ProductType): Result<Product, FunctionalError> = coroutineBinding {
|
||||||
|
validateName(name).bind()
|
||||||
|
|
||||||
|
val newProduct = Product(id = UUID.randomUUID(), name, type)
|
||||||
|
productOutputPort.save(newProduct)
|
||||||
|
.mapError { FunctionalError(it.message) }
|
||||||
|
.map { newProduct }
|
||||||
|
.bind()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateName(name: String): Result<Unit, FunctionalError> = when {
|
||||||
|
name.isBlank() -> Err(FunctionalError("Product name should be set."))
|
||||||
|
else -> Ok(Unit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.demo.domain.core.error
|
||||||
|
|
||||||
|
open class DomainError(val message: String)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.demo.domain.core.error
|
||||||
|
|
||||||
|
class FunctionalError(message: String) : DomainError(message)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example.demo.domain.core.error
|
||||||
|
|
||||||
|
class TechnicalError(message: String) : DomainError(message)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.example.demo.domain.product.inputport
|
||||||
|
|
||||||
|
import com.example.demo.domain.core.error.FunctionalError
|
||||||
|
import com.example.demo.domain.product.model.Product
|
||||||
|
import com.example.demo.domain.product.model.ProductType
|
||||||
|
import com.github.michaelbull.result.Result
|
||||||
|
|
||||||
|
interface ProductInputPort {
|
||||||
|
suspend fun create(name: String, type: ProductType): Result<Product, FunctionalError>
|
||||||
|
suspend fun getAll(): Result<List<Product>, FunctionalError>
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.example.demo.domain.product.outputport
|
||||||
|
|
||||||
|
import com.example.demo.domain.core.error.TechnicalError
|
||||||
|
import com.example.demo.domain.product.model.Product
|
||||||
|
import com.github.michaelbull.result.Result
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
interface ProductOutputPort {
|
||||||
|
fun getById(id: UUID): Product?
|
||||||
|
|
||||||
|
suspend fun getAll(): Result<List<Product>, TechnicalError>
|
||||||
|
|
||||||
|
fun save(product: Product): Result<Unit, TechnicalError>
|
||||||
|
|
||||||
|
fun deleteById(id: UUID)
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.example.demo.domain.product.port
|
|
||||||
|
|
||||||
import com.example.demo.domain.product.model.Product
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
interface ProductPort {
|
|
||||||
fun getById(id: UUID): Product?
|
|
||||||
|
|
||||||
fun getAll(): List<Product>
|
|
||||||
|
|
||||||
fun save(product: Product)
|
|
||||||
|
|
||||||
fun deleteById(id: UUID)
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,28 @@
|
|||||||
package com.example.demo.exposition.product
|
package com.example.demo.exposition.product
|
||||||
|
|
||||||
import com.example.demo.application.product.ProductUseCases
|
import com.example.demo.domain.core.error.FunctionalError
|
||||||
|
import com.example.demo.domain.product.inputport.ProductInputPort
|
||||||
|
import com.example.demo.domain.product.model.Product
|
||||||
|
import com.example.demo.exposition.product.model.ProductCreationRequest
|
||||||
import com.example.demo.exposition.product.model.ProductDto
|
import com.example.demo.exposition.product.model.ProductDto
|
||||||
|
import com.github.michaelbull.result.Result
|
||||||
|
import com.github.michaelbull.result.map
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/products")
|
@RequestMapping("/api/products")
|
||||||
class ProductController(
|
class ProductController(
|
||||||
private val productUseCases: ProductUseCases
|
private val productInputPort: ProductInputPort
|
||||||
) {
|
) {
|
||||||
@GetMapping
|
@GetMapping
|
||||||
fun getAll(): List<ProductDto> = productUseCases.getAll().map(::ProductDto)
|
suspend fun getAll(): Result<List<ProductDto>, FunctionalError> = productInputPort.getAll()
|
||||||
|
.map { products -> products.map(::ProductDto) }
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
suspend fun create(@RequestBody request: ProductCreationRequest): Result<Product, FunctionalError> =
|
||||||
|
productInputPort.create(request.name, request.type)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.example.demo.exposition.product.core.advice
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
class ResultControllerAdvice {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.example.demo.exposition.product.model
|
||||||
|
|
||||||
|
import com.example.demo.domain.product.model.ProductType
|
||||||
|
|
||||||
|
data class ProductCreationRequest(
|
||||||
|
val name: String,
|
||||||
|
val type: ProductType
|
||||||
|
)
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
package com.example.demo.infrastructure.product
|
package com.example.demo.infrastructure.product
|
||||||
|
|
||||||
|
import com.example.demo.domain.core.error.TechnicalError
|
||||||
import com.example.demo.domain.product.model.Product
|
import com.example.demo.domain.product.model.Product
|
||||||
import com.example.demo.domain.product.model.ProductType.LIQUID
|
import com.example.demo.domain.product.model.ProductType.LIQUID
|
||||||
import com.example.demo.domain.product.model.ProductType.SOLID
|
import com.example.demo.domain.product.model.ProductType.SOLID
|
||||||
import com.example.demo.domain.product.port.ProductPort
|
import com.example.demo.domain.product.outputport.ProductOutputPort
|
||||||
|
import com.github.michaelbull.result.Ok
|
||||||
|
import com.github.michaelbull.result.Result
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class ProductInMemoryAdapter : ProductPort {
|
class ProductInMemoryAdapter : ProductOutputPort {
|
||||||
private val products = mutableListOf(
|
private val products = mutableListOf(
|
||||||
Product(
|
Product(
|
||||||
id = UUID.randomUUID(),
|
id = UUID.randomUUID(),
|
||||||
@@ -24,15 +27,11 @@ class ProductInMemoryAdapter : ProductPort {
|
|||||||
|
|
||||||
override fun getById(id: UUID): Product? = products.find { product -> product.id == id }
|
override fun getById(id: UUID): Product? = products.find { product -> product.id == id }
|
||||||
|
|
||||||
override fun getAll(): List<Product> = products
|
override suspend fun getAll(): Result<List<Product>, TechnicalError> = Ok(products)
|
||||||
|
|
||||||
override fun save(product: Product) {
|
override fun save(product: Product): Result<Unit, TechnicalError> {
|
||||||
if (getById(product.id) == null) {
|
products += product
|
||||||
products.add(product)
|
return Ok(Unit)
|
||||||
} else {
|
|
||||||
deleteById(product.id)
|
|
||||||
save(product)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteById(id: UUID) {
|
override fun deleteById(id: UUID) {
|
||||||
|
|||||||
Reference in New Issue
Block a user