Kotlin Springboot -- Part 13 Usecase 以降で REST で受けった POST の JSON を Entity まで運ぶ。(モジュール分割前)
Tags: ca, kotlin, springboot
Published: 2022-10-16 13:12:26


## 前回

前回の記事では Rest 層で Postmapping を使って POST リクエストを受け取り、ReqeustBody で、そのリクエストのボディを受け取り、関数内部で受け取ったリクエストのボディの処理を表示するところまで確認した。

とりあえず動くようにする。
エラーハンドリングやレスポンスコードの対応は後日。

---

## 今回

今回はその関数で受け取った JSON を Usecase に渡して処理していく。

---

## Port

依存性逆転しているので、中央のポートから実装していく。

```kotlin
interface PersonPort {
    fun getAllPersons(): Persons
    fun postPerson(): Person
}
```

インターフェースで postPerson として作成して

---

## Gateway

```kotlin
    override fun postPerson(): Person {
        TODO("Not yet implemented")
    }
```

Alt Enter で Implement Abstract Function を実行して

実装が TODO 状態で Gateway に作成される。

---

## Usecase

ここまでで、Usecase から呼び出してみる。

```kotlin
  fun postPerson(person: Person) {
    personPort.postPerson(person)
  }
```

返り値はないので返り値と型はなく、
引数だけ型を指定して実行させる。

---

## Rest

```kotlin
  @PostMapping("/persons")
  fun postPerson(@RequestBody request: PersonJson): String {
    personsUsecase.postPerson(Person(Name(request.name), Age(request.age)))
    return request.toString()
  }
```

Rest で Usecase を呼び出す。
request から中身を取り出して、
Person ドメインと内部の Name, Age ドメインにいれて呼び出す。

---

## Curl でリクエストする

Gateway が TODO の状態で外部から実行してみる

```php
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"test", "age":20}' \
http://localhost:8080/persons
```

```json
{
"timestamp":"2022-10-16T12:22:33.962+00:00",
"status":500,
"error":"Internal Server Error",
"path":"/persons"
}
```

ターミナルのレスポンスには 500 が返ってきて

```php
kotlin.NotImplementedError: 
An operation is not implemented: Not yet implemented
```

未開発エラーが想定通りでる。
TODO だからね。

---

## Gateway でドメインの中身を .value で出して Driver に渡す

```kotlin
  override fun postPerson(person: Person) {
    personsDriver.add(person.name.value, person.age.value)
  }
```

Person ドメインで渡されたデータの中身を取り出して
追加するための Driver に渡す

エラーハンドリングは後日。

---

## Driver で Entity に追加する

```kotlin
package com.example.springboot

import org.springframework.stereotype.Component

@Component
class PersonsDriver {
  data class PersonEntity(val name: String , val age: Int)

  val taro = PersonEntity("taro", 3)
  val hana = PersonEntity("hana", 5)
  val dom = PersonEntity("Dominique", 11)
  val jack = PersonEntity("Jackson", 11)
  val persons = listOf<PersonEntity>(taro,hana,dom,jack)

  fun findAll(): List<PersonEntity> {
    return persons
  }
  fun add(name: String, age: Int){
    val currentPersons = findAll()
  }
}
```

前回まではこうやって、PersonEntity のインスタンスである persons をデータの本体として、そこから findAll していた。

```kotlin
  val persons = mutableListOf(
    PersonEntity("taro", 3),
    PersonEntity("hana", 5),
    PersonEntity("Dominique", 11),
    PersonEntity("Jackson", 11),
  )
```

persons を少し見やすくして、mutable にした。
この persons に付け加えるように今回は実装する。

---

## データストアにいれたい

現状、ちゃんとデータを保持していなかった

gauge E2E の回でやったデータストアを使ってみる

https://codelabs.developers.google.com/codelabs/cloud-spring-datastore#2

ググると GCP のデータストアがでてくる

他は Android のデータストアしかでてこないので諦める。

---

## Driver で add する

```kotlin
  fun add(name: String, age: Int){
    persons.add(
      PersonEntity(name, age),
    )
    println(persons)
  }

```

persons という変数に引数の値からエンティティを追加して、
一時的に persons を全員表示して確認する

```php
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"test", "age":20}' \
http://localhost:8080/persons
PersonJson(name=test, age=20)
```

```kotlin
[PersonEntity(name=taro, age=3), PersonEntity(name=hana, age=5), PersonEntity(name=Dominique, age=11), PersonEntity(name=Jackson, age=11), PersonEntity(name=test, age=20)]
```

無事に追加された。

---

## まとめ

Rest から POST で送られてきた JSON データをインメモリで保存するためには

Usecase から Port を通じて渡して

Gateway では Domain から中身を抜いて渡して

Driver では Entity に詰めてエンティティのインスタンスとして作った変数に追加する。

これで実装できる


---

## 今後
 
POST まで作ったのでまず E2E を追加したい。
しかし、DB ならアサートできるが、変数作っただけのデータでどう保存されたことをテストできるかは課題。

UUID も発行してないので、テストする前にそれをつくってエラーハンドリングして 200 or 500 を返すようにしたい