buto > /dev/null

だいたい急に挑戦してゴールにたどり着かずに飽きる日々です

Java Recordsの使いドコロを探る

Java15にスキルをアップデート

未だに仕事ではJava8を使い続けているのでそれにかまけてJavaキャッチアップできてなかった…

これからも仕事、趣味共にバックエンドはJavaを使っていくことになりそうなので今日久しぶりに最新Javaを調べてみた!

(資格もJavaGold11にアップデートしなきゃ)

新しいデータの扱い方 Records

JDK 14でPreview ReleaseされるRecordsが素敵なのでJShellで試そう

前から存在は知っていたのですが、試したことなかったのでRecordsを使ってみます!

getter/setterの記述不要でコンストラクタでフィールドに値をセットしてくれる仕組みなのかー

RESTAPIで使ってみた

私はJavaAPI開発で使うことが多いのでSpringBootのRESTAPIでRecordsを試してみました

(家事や仕事で気づいたこと、嬉しかったことなどを記録するアプリを想定)

  • 開発環境
    • MacbookAir
    • OracleJDK15
    • SpringBoot2.4.1

JDK15でもRecordsはプレビューリリースなのでbuild.gradleに以下の設定を記述しないとrecordsがコンパイルエラーになります

tasks.withType(JavaCompile) {
    options.compilerArgs += ['--enable-preview']
}

またIDEの実行環境設定でJVM引数が必要です f:id:butorisa:20201226235935p:plain

お試しなのでコントローラーにRecords書いちゃってます(本来はモデルクラスに書くべき?)

package com.calico.controller;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JournalController {

    /**
     * 記録の登録
     *
     * @param request 記録(画面入力値)
     * @return response 登録結果
     */
    @RequestMapping(value = "/journals", method = RequestMethod.POST)
    public journalResponse postJournal(@RequestBody journalRequest request) {
        journalResponse response = new journalResponse(1, request.category(), request.eval(), request.memo());
        // TODO データ登録処理
        return response;
    }

    /**
     * 記録登録APIリクエストRecords
     * @param category 記録カテゴリー
     * @param eval 記録内容のポジティブ度(0-10 ポジティブになるほど値が大きくなる)
     * @param memo 記録内容
     */
    public record journalRequest(Categories category, int eval, String memo) {
    }

    /**
     * 記録登録APIレスポンスRecords
     */
    public record journalResponse(int id, Categories category, int eval, String memo) {
        public int getId() {
            return id;
        }

        public Categories getCategory() {
            return category;
        }

        public int getEval() {
            return eval;
        }

        public String getMemo() {
            return memo;
        }
    }

    /**
     * 記録カテゴリー
     */
    public enum Categories {
        Home,
        Job,
        Community,
        Other
    }
}

APIのリクエスト、レスポンスにRecordsを使っています

ちなみに実行結果はこちらです まだDB接続していないのでリクエストをそのままレスポンスするだけです f:id:butorisa:20201226235801p:plain

ここで注意なのですが、レスポンスのRecordsはgetterが必要です

getterを書かないと以下のエラーが発生します

org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type

これは@RestControllerをつけているAPIメソッドではSpringBootがレスポンスをjsonに変換する時にgetCategory()メソッドが必要なのに定義されていないからっぽい

Recordsが暗黙で用意するメソッドはgetCategory()ではなく、プロパティ名ままのcategory()だからSpringBootはgetterと認識してくれないみたい。。。

SpringBootがRecords対応してくれたらすごく便利かも!!