Este post é uma continuação do Kotlin para backend?. Cada parte desta série está em branchs diferentes no github. Na primeira parte criamos as classes controller e service, vamos terminar a implementação e adicionar o banco de dados agora, mas antes precisamos refator alguns pontos:
Data Transfer Object
A camada Controller é a nossa interface com o front-end e devemos utilizar objetos que tenham a função de transferir os dados que precisamos, sejam estes dados de entrada ou de saída. Vamos renomear a classe Game para GameDTO e acrescentar o campo id:
data class GameDTO(
val id: String,
val title: String,
val releaseDate: LocalDate
)
Vamos também criar uma classe para representar os dados de criação e atualização do Game. Esta classe não deve conter o ID pois esta não é uma informação que o front-end deve passar na criação, vamos deixar para o back-end a função de gerenciar estes ids.
data class CreateGameDTO (
val title: String,
val releaseDate: LocalDate
)
CRUD
Vamos agora criar as opeções básicas no Controller:
@GetMapping
fun getGames(): List<GameDTO> = gameService.getGames()
@GetMapping("/{id}")
fun findGameById(@PathVariable id: String): GameDTO = gameService.getGameById(id)
@PostMapping
fun createGame(@RequestBody createGameDTO: CreateGameDTO): GameDTO = gameService.createGame(createGameDTO)
@PutMapping("/{id}")
fun updateGame(@PathVariable id: String,
@RequestBody createGameDTO: CreateGameDTO): GameDTO = gameService.update(id, createGameDTO)
@DeleteMapping("/{id}")
fun deleteGame(@PathVariable id: String) = gameService.delete(id)
Estas operações ainda não existem na nossa camada de Service, então precisamos atualizar a interface GameService:
interface GameService {
fun getGames(): List<GameDTO>
fun getGameById(id: String): GameDTO
fun createGame(createGameDTO: CreateGameDTO): GameDTO
fun update(id: String, createGameDTO: CreateGameDTO): GameDTO
fun delete(id: String)
}
Por último vamos implementar estes novos métodos na classe GameServiceImpl. Dica: No IntelliJ podemos clicar no nome da classe e utilizar o atalho alt+enter -> “Implement members”.
Repository
Para usufruirmos de todos os benefícios da programação reativa, vamos utilizar o MongoDB como banco de dados pois já temos o driver reativo. Até o momento da publicação deste post temos driver reativo para Cassandra, Mongo, Redis e, ainda em fase experimental, para bancos SQL.
Adicionar a dependência no build.gradle.kts:
implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive")
Para facilitar, vamos rodar o mongo local através utilizando docker:
$ docker run -p 27017:27017 --name mongolocal -d mongo:4.0
O mapeamento da entitade Game:
@Document
data class GameEntity(
@Id
val id: String? = null,
val title: String,
val releaseDate: LocalDate
)
E a interface que extende ReactiveMongoRepository:
@Repository
interface GameRepository : ReactiveMongoRepository<GameEntity, String>
Um ponto interessante a se notar é que não precisamos abrir o escopo se a classe ou interface não tiver nada a ser declarado.
Vamos criar uma classe para habilitar os repositórios do mongo.
package io.redspark.games.config
import com.mongodb.reactivestreams.client.MongoClient
import com.mongodb.reactivestreams.client.MongoClients
import org.springframework.context.annotation.Bean
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories
@EnableReactiveMongoRepositories
class MongoReactiveApplication : AbstractReactiveMongoConfiguration() {
@Bean
fun mongoClient(): MongoClient {
return MongoClients.create()
}
override fun getDatabaseName(): String {
return "gamereactive"
}
override fun reactiveMongoClient(): MongoClient {
return mongoClient()
}
}
e fazer a configuração do acessos ao banco:
spring:
data:
mongodb:
host: 127.0.0.1
port: 27017
[/et_pb_text][/et_pb_column][/et_pb_row][/et_pb_section]