ToDo状態更新のREST API

ToDoの状態を更新するために使用するREST APIを実装します。

ToDoを更新する処理の実装

まず、ToDoの状態を更新する処理を実装します。ここはREST APIと直接関係が無い部分であるため、詳細な説明は省略します。

Todoクラスに追加

ToDoの状態を変更したインスタンスを生成するchangeStatusメソッドを追加します。

public Todo changeStatus(TodoStatus status) {
    return new Todo(id, text, status, userId);
}

TodoRepositoryインターフェースに追加

TodoRepositoryインターフェースに、ToDoを取得するためのgetメソッド、ToDoを更新するためのupdateメソッドを追加します。

    Todo get(TodoId todoId);

    void update(Todo todo);

TodoServiceクラスに追加

ToDoの状態を更新するためのupdateStatusメソッドを実装します。

public Todo updateStatus(TodoId todoId, TodoStatus status) {
    Todo todo = todoRepository.get(todoId);
    Todo changedTodo = todo.changeStatus(status);
    todoRepository.update(changedTodo);
    return changedTodo;
}

JdbcTodoRepositoryクラスに追加

先ほどTodoRepositoryインターフェースにgetメソッドとupdateメソッドを追加したため、実装クラスにも処理を実装します。

    @Override
    public Todo get(TodoId todoId) {
        TodoEntity todoEntity = UniversalDao.findById(TodoEntity.class, todoId.value());
        return createTodo(todoEntity);
    }

    @Override
    public void update(Todo todo) {
        TodoEntity todoEntity = new TodoEntity();
        todoEntity.setTodoId(todo.id().value());
        todoEntity.setText(todo.text().value());
        todoEntity.setCompleted(todo.status() == TodoStatus.COMPLETED);
        todoEntity.setUserId(todo.userId().value());
        UniversalDao.update(todoEntity);
    }

getメソッドでは、ToDoのIDからDBに登録されているToDoを取得します。ToDoのIDは主キーであるため、SQLファイルは書かずにUniversalDao#findByIdを使用して検索することができます。(参考:Nablarch SQLを書かなくても単純なCRUDができる

updateメソッドでは、引数のToDoからDBを更新しています。

REST APIの作成

TodoActionクラスの作成

今回は、単一のToDoを表現したパスに変わるため、新しくTodoActionクラスを作成します。(同じアクションクラスでも実装可能ですが、ここでは分けます)

package com.example.todo.api;

import com.example.todo.application.TodoService;
import com.example.todo.domain.*;
import nablarch.core.repository.di.config.externalize.annotation.SystemRepositoryComponent;
import nablarch.core.validation.ee.ValidatorUtil;
import nablarch.fw.ExecutionContext;
import nablarch.fw.web.HttpRequest;

import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@SystemRepositoryComponent
@Path("/todos/{todoId}")
public class TodoAction {

    private final TodoService todoService;

    public TodoAction(TodoService todoService) {
        this.todoService = todoService;
    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public TodoResponse put(HttpRequest request, ExecutionContext context, PutRequest requestBody) {
        ValidatorUtil.validate(requestBody);

        TodoId todoId = new TodoId(Long.valueOf(request.getParam("todoId")[0]));
        TodoStatus status = requestBody.completed ? TodoStatus.COMPLETED : TodoStatus.INCOMPLETE;

        Todo todo = todoService.updateStatus(todoId, status);

        return new TodoResponse(todo.id(), todo.text(), todo.status());
    }

    public static class PutRequest {
        @NotNull
        public Boolean completed;
    }

    public static class TodoResponse {

        public final Long id;

        public final String text;

        public final Boolean completed;

        public TodoResponse(TodoId id, TodoText text, TodoStatus status) {
            this.id = id.value();
            this.text = text.value();
            this.completed = status == TodoStatus.COMPLETED;
        }
    }
}

putメソッドは以下の処理を実装します。

  • 登録と同じように、ValidatorUtilを使用してBean Validationを実行
  • ToDoのIDをパスパラメータから取得
  • ToDo状態のオブジェクトを生成
  • TodoServiceの状態更新メソッドを呼び出し
  • 更新結果をレスポンスのオブジェクトに変換

REST APIのテスト

テスト用Javaディレクトリのcom.example.todo.apiパッケージに、TodoUpdateRestApiTestクラスを作成します。

package com.example.todo.api;

import com.example.openapi.OpenApiValidator;
import com.example.system.nablarch.FlywayExecutor;
import nablarch.core.repository.SystemRepository;
import nablarch.fw.web.HttpResponse;
import nablarch.fw.web.RestMockHttpRequest;
import nablarch.test.core.http.SimpleRestTestSupport;
import org.junit.BeforeClass;
import org.junit.Test;

import javax.ws.rs.core.MediaType;
import java.nio.file.Paths;
import java.util.Map;

import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

public class TodoUpdateRestApiTest extends SimpleRestTestSupport {

    public static OpenApiValidator openApiValidator = new OpenApiValidator(Paths.get("rest-api-specification/openapi.yaml"));

    @BeforeClass
    public static void setUpClass() {
        FlywayExecutor flywayExecutor = SystemRepository.get("dbMigration");
        flywayExecutor.migrate(true);
    }

    @Test
    public void RESTAPIでToDoの状態を更新できる() throws Exception {
        RestMockHttpRequest request = put("/api/todos/2002")
                .setHeader("Content-Type", MediaType.APPLICATION_JSON)
                .setBody(Map.of("completed", true));
        HttpResponse response = sendRequest(request);

        assertStatusCode("ToDoのステータス更新", HttpResponse.Status.OK, response);

        assertThat(response.getBodyString(), hasJsonPath("$.id", equalTo(2002)));
        assertThat(response.getBodyString(), hasJsonPath("$.text", equalTo("やること2")));
        assertThat(response.getBodyString(), hasJsonPath("$.completed", equalTo(true)));

        openApiValidator.validate("putTodo", request, response);
    }
}

実装要領は登録と同じです。

続いて、テストを実行する前準備として、PostgreSQLを起動しておきます。PostgreSQLのコンテナを起動していない場合は、backendディレクトリで次のコマンドを実行します。

$ docker-compose -f docker/docker-compose.dev.yml up -d

続いて、次のコマンドでコンテナが起動していることを確認します。

mvn test

特にエラーが発生せず、テストが成功することを確認します。

これで、ToDo状態更新のREST APIの実装は完了です。

results matching ""

    No results matching ""