<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Adminer on Rindrics Mumbles</title>
    <link>https://rindrics.com/tags/adminer/</link>
    <description>Adminer</description>    
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sat, 25 Jul 2026 00:00:00 +0900</lastBuildDate>
    <atom:link href="https://rindrics.com/tags/adminer/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>データ登録サービスの構築 その1</title>
      <link>https://rindrics.com/posts/stock-assess-data-registry-1/</link>
      <pubDate>Sat, 25 Jul 2026 00:00:00 +0900</pubDate>
      
      <guid>https://rindrics.com/posts/stock-assess-data-registry-1/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://rindrics.com/posts/stock-assess-api-contract-postmortem/#:~:text=data%20service%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E7%8B%AC%E7%AB%8B%E3%81%97%E3%81%9F%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%AB%E6%80%9D%E3%82%8F%E3%82%8C%E3%82%8B&#34;&gt;データを登録するためのサービスが必要&lt;/a&gt;ということがわかったので、ここのところはClojureでできそうか技術検証をしていた。
検証は先日出した記事で終えたので、いよいよ実装していく。&lt;/p&gt;
&lt;p&gt;







&lt;div class=&#34;card&#34;&gt;
  &lt;a href=&#34;https://rindrics.com/posts/hello-clojure/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;card-link&#34;&gt;
    &lt;div class=&#34;card-content&#34;&gt;
      &lt;h4 class=&#34;card-title&#34;&gt;Clojureに入門した | rindrics.com&lt;/h4&gt;
      
      &lt;span class=&#34;card-url&#34;&gt;https://rindrics.com/posts/hello-clojure/&lt;/span&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;









&lt;div class=&#34;card&#34;&gt;
  &lt;a href=&#34;https://rindrics.com/posts/my-first-clojure-api/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;card-link&#34;&gt;
    &lt;div class=&#34;card-content&#34;&gt;
      &lt;h4 class=&#34;card-title&#34;&gt;ClojureでAPIを書いてみた | rindrics.com&lt;/h4&gt;
      
      &lt;span class=&#34;card-url&#34;&gt;https://rindrics.com/posts/my-first-clojure-api/&lt;/span&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;サービス名はdata-registryにしよう。&lt;/p&gt;
&lt;h2 id=&#34;data-registryが必要な背景&#34;&gt;data-registryが必要な背景&lt;/h2&gt;
&lt;p&gt;下の記事でもふり返ったが、&lt;a href=&#34;https://rindrics.com/posts/stock-assess-plumber/&#34;&gt;このあたり&lt;/a&gt;で定義していたmonolithサービスのAPIは、パラメータが多すぎて使いにくかった。








&lt;div class=&#34;card&#34;&gt;
  &lt;a href=&#34;https://rindrics.com/posts/stock-assess-api-contract-postmortem/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;card-link&#34;&gt;
    &lt;div class=&#34;card-content&#34;&gt;
      &lt;h4 class=&#34;card-title&#34;&gt;設計ミスをふりかえる | rindrics.com&lt;/h4&gt;
      
      &lt;span class=&#34;card-url&#34;&gt;https://rindrics.com/posts/stock-assess-api-contract-postmortem/&lt;/span&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;frasyrの&lt;code&gt;vpa()&lt;/code&gt;に渡す個々のパラメータをAPIに露出させるのではなく、登録済みデータセットの&lt;code&gt;versionId&lt;/code&gt;を渡すほうが
、データの監査的にも良さそうという見通し。&lt;/p&gt;
&lt;p&gt;そこで、データ登録を受け付け、登録済みデータセットの&lt;code&gt;versionId&lt;/code&gt;を返すサービス: data-registryが欲しいわけ。&lt;/p&gt;
&lt;p&gt;data-registryの使われ方は下図のような感じ:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-23-data/architecture.webp&#34;
    alt=&#34;BFFからのデータ登録を受付け、monolithからの問い合わせに応じる&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;BFFからのデータ登録を受付け、monolithからの問い合わせに応じる&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&#34;仕様を考える&#34;&gt;仕様を考える&lt;/h3&gt;
&lt;p&gt;いろいろ考えてみたのだが、data-registryには下記のようなリクエストを投げたい:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% curl /v0/catch-at-age \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --request POST \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --header &amp;#39;Content-Type: application/json&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --data &amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;metadata&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;species&amp;#34;: &amp;#34;マイワシ&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;stock&amp;#34;: &amp;#34;太平洋系群&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;assessmentYear&amp;#34;: 2026
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;dataset&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;valueUnit&amp;#34;: &amp;#34;ton&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;dataSet&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;0&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2025&amp;#34;: 123,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2026&amp;#34;: 456
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;1&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2025&amp;#34;: 234,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2026&amp;#34;: 567
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;2&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2025&amp;#34;: 345,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2026&amp;#34;: 678
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;3&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2025&amp;#34;: 456,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2026&amp;#34;: 789
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;4&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2025&amp;#34;: 789,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2026&amp;#34;: 890
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;5+&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2025&amp;#34;: 890,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;#34;2026&amp;#34;: 901
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑ポイントは、&lt;code&gt;metadata&lt;/code&gt;を持っていることと、&lt;code&gt;dataSet&lt;/code&gt;のキーに&lt;code&gt;5+&lt;/code&gt;（5歳以上）があること&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;p&gt;期待するレスポンスは下記:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#268bd2&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;019f8bff-a5b8-7014-bfc8-41561eaac24c&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑もちろん、これが返るまでにデータベースへのデータ登録がある。&lt;/p&gt;
&lt;h2 id=&#34;実装手順&#34;&gt;実装手順&lt;/h2&gt;
&lt;p&gt;data-registryの機能を実現するエッセンスは別記事で既に検証済みなので、さっそく実装手順を考えてみる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;API契約を書く&lt;/li&gt;
&lt;li&gt;ルーティングの動作確認&lt;/li&gt;
&lt;li&gt;db セットアップ&lt;/li&gt;
&lt;li&gt;リポジトリ・ハンドラの実装&lt;/li&gt;
&lt;li&gt;&lt;code&gt;datasetVersion&lt;/code&gt;生成ロジックの設計&lt;/li&gt;
&lt;li&gt;リファクタリング&lt;/li&gt;
&lt;li&gt;エラーハンドリングの追加&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;こんなところか。&lt;/p&gt;
&lt;h2 id=&#34;やってみる&#34;&gt;やってみる&lt;/h2&gt;
&lt;h3 id=&#34;api契約を書く&#34;&gt;API契約を書く&lt;/h3&gt;
&lt;p&gt;年齢別漁獲量データを登録するためのエンドポイントを作ってみる。
OpenAPI形式で下記のように書いた:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml:schema/openapi.yaml&#34; data-lang=&#34;yaml:schema/openapi.yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;3.2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;info&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;title&lt;/span&gt;: Data Registry API
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: |&lt;span style=&#34;color:#2aa198&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;    Immutable data service for stock assessment workflow.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;    Registers and versions biological datasets and parameter sets.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;    Returns version identifiers that other services reference for reproducibility and immutability.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;0.1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;contact&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;name&lt;/span&gt;: dev+yoshimoto-samonji@rindrics.com
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;license&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;name&lt;/span&gt;: MIT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;200&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;summary&lt;/span&gt;: Return version of catch-at-age dataset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;version&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;example&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;version&lt;/span&gt;: 019f8bff-a5b8-7014-bfc8-41561eaac24c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;/v0/catch-at-age&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;post&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;operationId&lt;/span&gt;: catch-at-age-POST
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;summary&lt;/span&gt;: Register catch-at-age dataset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Register a catch-at-age dataset with metadata
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;requestBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;required&lt;/span&gt;: &lt;span style=&#34;color:#cb4b16&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - metadata
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - dataset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    - species
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    - stock
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    - assessmentYear
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;species&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;example&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;マイワシ&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Name of target species
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;stock&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;example&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;太平洋系群&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Stock or population identifier
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;assessmentYear&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: integer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;example&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;2026&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Year of stock assessment
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;notes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Additional notes or comments
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    - valueUnit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    - dataSet
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;valueUnit&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;enum&lt;/span&gt;: [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;kg&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;ton&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Unit of catch weight
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;dataSet&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Mapping of age_class:{year:catch_weight}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;additionalProperties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Mapping of year:catch_weight&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#268bd2&#34;&gt;additionalProperties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#268bd2&#34;&gt;description&lt;/span&gt;: Catch weight
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: number
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#268bd2&#34;&gt;minimum&lt;/span&gt;: &lt;span style=&#34;color:#2aa198&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;200&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;summary&lt;/span&gt;: Return version of catch-at-age dataset
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: object
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#268bd2&#34;&gt;version&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt;: string
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;example&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#268bd2&#34;&gt;version&lt;/span&gt;: 019f8bff-a5b8-7014-bfc8-41561eaac24c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑レスポンスは、まずは正常系だけ書いたところ。&lt;/p&gt;
&lt;h3 id=&#34;ルーティングの動作確認&#34;&gt;ルーティングの動作確認&lt;/h3&gt;
&lt;p&gt;APIスキーマを変えたので、前回の記事で書いた&lt;code&gt;schema.clj&lt;/code&gt;を微修正する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:src/data_registry/schema.clj&#34; data-lang=&#34;diff:src/data_registry/schema.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#b58900&#34;&gt;eval &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;`&lt;/span&gt;(&lt;span style=&#34;color:#719e07&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sym-name&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;validate-favorite-fish-request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Validate favorite-fish request, throw if invalid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;validate-catch-at-age-request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Validate catch-at-age request, throw if invalid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#268bd2&#34;&gt;data&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;  (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:favorite-fish-request&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:catch-at-age-request&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#b58900&#34;&gt;if-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;error&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;m/explain&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;data&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;throw&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;ex-info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Invalid favorite-fish request&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;error&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;throw&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;ex-info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Invalid catch-at-age request&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;error&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;data&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑エンドポイント名を変えただけだが。&lt;/p&gt;
&lt;p&gt;続いて、ルーターのコードも対応して修正する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:src/data_registry/routes.clj&#34; data-lang=&#34;diff:src/data_registry/routes.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#b58900&#34;&gt;eval &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;`&lt;/span&gt;(&lt;span style=&#34;color:#719e07&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;sym-name&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;favorite-fish-handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;  &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;POST /v0/favorite-fish&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;catch-at-age-handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;POST /v0/catch-at-age&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#268bd2&#34;&gt;req&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;log/info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Request body:&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;req&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;body&lt;/span&gt; (&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;req&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;schema/validate-favorite-fish-request&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;n&lt;/span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:fish&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:name&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;sn&lt;/span&gt;   (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:fish&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:scientific_name&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:message&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Your favorite fish is %s (%s), right?&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;sn&lt;/span&gt;)} 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;validated-response&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;schema/validate-response&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:favorite-fish-200&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;schema/validate-catch-at-age-request&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;species&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:species&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;stock&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:stock&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;year&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:assessmentYear&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:message&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Registered %s (%s) for year %d&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;species&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;stock&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;year&lt;/span&gt;)}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;validated-response&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;schema/validate-response&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:catch-at-age-200&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          {&lt;span style=&#34;color:#2aa198&#34;&gt;:status&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-response&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;Exception&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;log/error&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Error in favorite-fish-handler&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:error&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;)})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;log/error&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Error in catch-at-age-handler&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:error&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;)})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&lt;span style=&#34;color:#2aa198&#34;&gt;:status&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;500&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:error&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;)}})))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;wrap-json-with-keywords&lt;/span&gt; [&lt;span style=&#34;color:#268bd2&#34;&gt;handler&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;wrap-json-body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;handler&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:key-fn&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;keyword&lt;/span&gt;, &lt;span style=&#34;color:#2aa198&#34;&gt;:charset&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#719e07&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;routes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;  [[&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;/v0/favorite-fish&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  [[&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;/v0/catch-at-age&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {&lt;span style=&#34;color:#2aa198&#34;&gt;:post&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:summary&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Register favorite fish&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:parameters&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema/favorite-fish-request&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:responses&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;200&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema/favorite-fish-200&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:handler&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;favorite-fish-handler&lt;/span&gt;}}]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:parameters&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema/catch-at-age-request&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:responses&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;200&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema/catch-at-age-200&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:handler&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;catch-at-age-handler&lt;/span&gt;}}]])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここから、Malliスキーマの生成やルーティングの動作確認をしたいので、&lt;a href=&#34;https://rindrics.com/posts/hello-clojure/&#34;&gt;こちらの記事&lt;/a&gt;で使っていた&lt;a href=&#34;https://gist.github.com/rindrics/aab992dc5a059a60cc3d06e01467479b&#34;&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/a&gt;を再利用しつつ、下記のような&lt;code&gt;Makefile&lt;/code&gt;を用意した:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.PHONY: run generate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LOG_LEVEL ?= DEBUG
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;COMPOSE_PROJECT_NAME ?= yoshimoto-samonji
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DOCKER_NETWORK := $(COMPOSE_PROJECT_NAME)_yoshimoto-samonji
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;generate:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	mkdir -p resources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	clj scripts/generate-from-openapi.clj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	DATA_REGISTRY_DEV_PORT=$(DATA_REGISTRY_DEV_PORT) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	LOG_LEVEL=$(LOG_LEVEL) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	docker compose -f ../../docker-compose.yml -p $(COMPOSE_PROJECT_NAME) run --rm -p $(DATA_REGISTRY_DEV_PORT):$(DATA_REGISTRY_DEV_PORT) repl clj -M -m data-registry.core
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;さっそくOpenAPIからMalliスキーマを生成してみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% make generate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p resources
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clj scripts/generate-from-openapi.clj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARNING: Implicit use of clojure.main with options is deprecated, use -M scripts/generate-from-openapi.clj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Found request schema: :catch-at-age-request
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Found response schema: :catch-at-age-200
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Generated resources/schemas.edn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{:catch-at-age-request [:map [:metadata [:map [:species :string] [:stock :string] [:assessment_year :int] [:notes :string]]] [:dataset [:map [:valueUnit :string] [:dataSet [:map]]]]], :catch-at-age-200 [:map [:detail :string]]}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑一応できたように見える。&lt;/p&gt;
&lt;p&gt;動作確認のためにAPIサーバを起動する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% make run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DATA_REGISTRY_DEV_PORT=31505 \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LOG_LEVEL=DEBUG \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        docker compose -f ../../docker-compose.yml -p yoshimoto-samonji run --rm -p 31505:31505 repl clj -M -m data-registry.core
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARN[0000] No services to build 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[+]  1/1t 1/11
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-db-1 Running       0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARN[0000] No services to build 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Container yoshimoto-samonji-repl-run-a5b67937303c Creating 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Container yoshimoto-samonji-repl-run-a5b67937303c Created 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2026-07-23 05:04:32.338:INFO::main: Logging initialized @873ms to org.eclipse.jetty.util.log.StdErrLog
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2026-07-23 05:04:34.225:INFO:oejs.Server:main: jetty-9.4.51.v20230217; built: 2023-02-17T08:19:37.309Z; git: b45c405e4544384de066f814ed42ae3dceacdd49; jvm 25.0.3+9-LTS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2026-07-23 05:04:34.248:INFO:oejs.AbstractConnector:main: Started ServerConnector@79ac50fe{HTTP/1.1, (http/1.1)}{0.0.0.0:31505}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑リッスンできた。&lt;/p&gt;
&lt;p&gt;リクエストを送ってみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% curl -X POST localhost:31505/v0/catch-at-age \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &amp;#39;{&amp;#34;metadata&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;species&amp;#34;: &amp;#34;マイワシ&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;stock&amp;#34;: &amp;#34;太平洋系群&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;assessmentYear&amp;#34;: 2026},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &amp;#34;dataset&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;valueUnit&amp;#34;: &amp;#34;ton&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;dataSet&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;0&amp;#34;: {&amp;#34;2025&amp;#34;: 123, &amp;#34;2026&amp;#34;: 456},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;1&amp;#34;: {&amp;#34;2025&amp;#34;: 234, &amp;#34;2026&amp;#34;: 567}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &amp;#34;Content-Type: application/json&amp;#34; &amp;amp;&amp;amp; echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&amp;#34;error&amp;#34;:&amp;#34;Invalid catch-at-age request&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑おや。&lt;/p&gt;
&lt;p&gt;API schemaに足した&lt;code&gt;required&lt;/code&gt;フィールドをパースできていなかった:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:scripts/generate-from-openapi.clj&#34; data-lang=&#34;diff:scripts/generate-from-openapi.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#719e07&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;!/usr/bin/env&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;clj&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;require&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;&amp;#39;&lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;clj-yaml.core&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;yaml&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Convert JSON Schema into Malli schema&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:type&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;cond&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;object&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:properties&lt;/span&gt; {})      
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;required&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;set &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:required&lt;/span&gt; []))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#268bd2&#34;&gt;fields&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;map &lt;/span&gt;(&lt;span style=&#34;color:#719e07&#34;&gt;fn &lt;/span&gt;[[&lt;span style=&#34;color:#268bd2&#34;&gt;prop-name&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;prop-schema&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;                          [(&lt;span style=&#34;color:#b58900&#34;&gt;keyword &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;prop-name&lt;/span&gt;) (&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;prop-schema&lt;/span&gt;)])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                          (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;kw&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;keyword &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;prop-name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                                &lt;span style=&#34;color:#268bd2&#34;&gt;is-required&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;contains? &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;required&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;kw&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                            (&lt;span style=&#34;color:#719e07&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;is-required&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                              [&lt;span style=&#34;color:#268bd2&#34;&gt;kw&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;prop-schema&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                              [&lt;span style=&#34;color:#268bd2&#34;&gt;kw&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:optional&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;true&lt;/span&gt;} (&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;prop-schema&lt;/span&gt;)])))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;)]                          
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#268bd2&#34;&gt;properties&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#b58900&#34;&gt;into &lt;/span&gt;[&lt;span style=&#34;color:#2aa198&#34;&gt;:map&lt;/span&gt;] &lt;span style=&#34;color:#268bd2&#34;&gt;fields&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#2aa198&#34;&gt;:string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;integer&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#2aa198&#34;&gt;:int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;number&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#2aa198&#34;&gt;:number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;boolean&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#2aa198&#34;&gt;:boolean&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;array&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;items&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:items&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#719e07&#34;&gt;if &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;items&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#2aa198&#34;&gt;:vector&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;items&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#2aa198&#34;&gt;:vector&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#2aa198&#34;&gt;:else&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:any&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;extract-schemas&lt;/span&gt; [&lt;span style=&#34;color:#268bd2&#34;&gt;openapi&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;paths&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;openapi&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:paths&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;atom&lt;/span&gt; {})]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#b58900&#34;&gt;doseq &lt;/span&gt;[[&lt;span style=&#34;color:#b58900&#34;&gt;path &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;path-item&lt;/span&gt;] &lt;span style=&#34;color:#268bd2&#34;&gt;paths&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#b58900&#34;&gt;doseq &lt;/span&gt;[[&lt;span style=&#34;color:#268bd2&#34;&gt;_method&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;operation&lt;/span&gt;] &lt;span style=&#34;color:#268bd2&#34;&gt;path-item&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#b58900&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;map? &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;operation&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#586e75&#34;&gt;; request schema&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#b58900&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;req-body&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;operation&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:requestBody&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#b58900&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;req-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:content&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:application/json&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:schema&lt;/span&gt;])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;schema-name&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;keyword &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;str &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;second &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;re-find &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;/([^/]+)$&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;path&lt;/span&gt;))) &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;-request&amp;#34;&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#b58900&#34;&gt;println &lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Found request schema:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema-name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#268bd2&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt; &lt;span style=&#34;color:#b58900&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema-name&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;json-schema&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#586e75&#34;&gt;; response schema&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#b58900&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;responses&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;operation&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:responses&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#b58900&#34;&gt;doseq &lt;/span&gt;[[&lt;span style=&#34;color:#268bd2&#34;&gt;status&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt;] &lt;span style=&#34;color:#268bd2&#34;&gt;responses&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                (&lt;span style=&#34;color:#b58900&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:content&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:application/json&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:schema&lt;/span&gt;])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;status-str&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;status&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#268bd2&#34;&gt;schema-name&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;keyword &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;str &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;second &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;re-find &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;/([^/]+)$&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;path&lt;/span&gt;))) &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;status-str&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    (&lt;span style=&#34;color:#b58900&#34;&gt;println &lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Found response schema:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schema-name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    (&lt;span style=&#34;color:#268bd2&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt; &lt;span style=&#34;color:#b58900&#34;&gt;assoc &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schema-name&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;json-schema-&amp;gt;malli&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;json-schema&lt;/span&gt;)))))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#719e07&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;-main&lt;/span&gt; [&lt;span style=&#34;color:#719e07&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;_args&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;openapi&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;yaml/parse-string&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;slurp &lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;schema/openapi.yaml&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;extract-schemas&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;openapi&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;edn-output&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;with-out-str &lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;pr &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;spit&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;resources/schemas.edn&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;edn-output&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#b58900&#34;&gt;println &lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Generated resources/schemas.edn&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#b58900&#34;&gt;println &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;schemas&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;-main&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑&lt;code&gt;required&lt;/code&gt;でないフィールドには&lt;code&gt;{:optional: true}&lt;/code&gt;が設定されるようにした。&lt;/p&gt;
&lt;p&gt;もういちど&lt;code&gt;make generate&lt;/code&gt;してからサーバーを起動したら、今度は成功した:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% curl -X POST localhost:31505/v0/catch-at-age \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &amp;#39;{&amp;#34;metadata&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;species&amp;#34;: &amp;#34;マイワシ&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;stock&amp;#34;: &amp;#34;太平洋系群&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;assessmentYear&amp;#34;: 2026},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &amp;#34;dataset&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;valueUnit&amp;#34;: &amp;#34;ton&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;dataSet&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;0&amp;#34;: {&amp;#34;2025&amp;#34;: 123, &amp;#34;2026&amp;#34;: 456},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;1&amp;#34;: {&amp;#34;2025&amp;#34;: 234, &amp;#34;2026&amp;#34;: 567}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &amp;#34;Content-Type: application/json&amp;#34; &amp;amp;&amp;amp; echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&amp;#34;message&amp;#34;:&amp;#34;Registered マイワシ (太平洋系群) for year 2026&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;バリデーションが利いているかを確認したいので、invalidなリクエストを投げてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% curl -XPOST localhost:31505/v0/catch-at-age \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-d &amp;#39;{&amp;#34;fish&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &amp;#34;name&amp;#34;: &amp;#34;マイワシ&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &amp;#34;scientific_name&amp;#34;: &amp;#34;Sardinops melanostictus&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-H &amp;#34;Content-Type: application/json&amp;#34; &amp;amp;&amp;amp; echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&amp;#34;error&amp;#34;:&amp;#34;Invalid catch-at-age request&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑想定通り、バリデーション失敗を確認できたのでOK!&lt;/p&gt;
&lt;h3 id=&#34;データベースのセットアップ&#34;&gt;データベースのセットアップ&lt;/h3&gt;
&lt;p&gt;次はデータをデータベースに登録できるようにする。
前掲の&lt;a href=&#34;https://gist.github.com/rindrics/aab992dc5a059a60cc3d06e01467479b&#34;&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/a&gt;と&lt;a href=&#34;https://gist.github.com/rindrics/368b9b44ad755ebe0a8bc98aa19bd3ec&#34;&gt;こちらの&lt;code&gt;Makefile&lt;/code&gt;&lt;/a&gt;を使って&lt;code&gt;make docker-up&lt;/code&gt;する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% make docker-up
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MONOLITH_IMAGE=yoshimotosamonji-monolith:latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        DATA_REGISTRY_IMAGE=yoshimotosamonji-data-registry:latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VALIDATE_RESPONSE= \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        docker compose up -d --no-build monolith data-registry db repl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[+] up 4/4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-db-1            Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-monolith-1      Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-repl-1          Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-data-registry-1 Recreated 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑データベースコンテナが立った（検証しながらやってるので他のも立ってる）。&lt;/p&gt;
&lt;h4 id=&#34;マイグレーション&#34;&gt;マイグレーション&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://rindrics.com/posts/hello-clojure/&#34;&gt;データベース操作の検証&lt;/a&gt;では手動でセットアップをしたが、今後の開発効率を考えてマイグレーションを仕組み化しておきたい。
マイグレーションツールには&lt;a href=&#34;https://hub.docker.com/r/flyway/flyway&#34;&gt;コンテナ版のFlyway&lt;/a&gt;を使うことにして、下記のようなマイグレーションスクリプトを作った:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql:resources/migrations/V001__init.sql&#34; data-lang=&#34;sql:resources/migrations/V001__init.sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;TABLE&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;IF&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;EXISTS&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;data_versions&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  id SERIAL &lt;span style=&#34;color:#719e07&#34;&gt;PRIMARY&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;KEY&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  version_id &lt;span style=&#34;color:#dc322f&#34;&gt;VARCHAR&lt;/span&gt;(&lt;span style=&#34;color:#2aa198&#34;&gt;64&lt;/span&gt;) &lt;span style=&#34;color:#719e07&#34;&gt;UNIQUE&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#cb4b16&#34;&gt;NULL&lt;/span&gt;,   &lt;span style=&#34;color:#586e75&#34;&gt;-- SHA-256 content hash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;  data_type &lt;span style=&#34;color:#dc322f&#34;&gt;VARCHAR&lt;/span&gt;(&lt;span style=&#34;color:#2aa198&#34;&gt;50&lt;/span&gt;) &lt;span style=&#34;color:#719e07&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#cb4b16&#34;&gt;NULL&lt;/span&gt;,           &lt;span style=&#34;color:#586e75&#34;&gt;-- catch_at_age, weight_at_age, maturity_at_age, parameter_set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;  metadata JSONB &lt;span style=&#34;color:#719e07&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#cb4b16&#34;&gt;NULL&lt;/span&gt;,                  &lt;span style=&#34;color:#586e75&#34;&gt;-- {species, stock, assessment_year, ...}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;  data JSONB &lt;span style=&#34;color:#719e07&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#cb4b16&#34;&gt;NULL&lt;/span&gt;,                      &lt;span style=&#34;color:#586e75&#34;&gt;-- The actual normalized data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;  created_at &lt;span style=&#34;color:#dc322f&#34;&gt;TIMESTAMP&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;DEFAULT&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;CURRENT_TIMESTAMP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;-- Indexes for common queries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#586e75&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;INDEX&lt;/span&gt; idx_data_versions_version_id &lt;span style=&#34;color:#719e07&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;data_versions&lt;/span&gt;(version_id);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;INDEX&lt;/span&gt; idx_data_versions_data_type &lt;span style=&#34;color:#719e07&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;data_versions&lt;/span&gt;(data_type);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;INDEX&lt;/span&gt; idx_data_versions_created_at &lt;span style=&#34;color:#719e07&#34;&gt;ON&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;data_versions&lt;/span&gt;(created_at);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑プライマリキーにはレスポンスの&lt;code&gt;versionId&lt;/code&gt;に使う&lt;code&gt;version_id&lt;/code&gt;ではなく、自動インクリメントの&lt;code&gt;id&lt;/code&gt;を使うことにした。&lt;/p&gt;
&lt;p&gt;マイグレーション用の&lt;code&gt;make&lt;/code&gt;ターゲットを追加する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ migrate-data-registry:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	docker run --rm \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  --network $(DOCKER_NETWORK) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  -v $$(pwd)/services/data-registry/resources/migrations:/flyway/sql \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  flyway/flyway:latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  -url=jdbc:postgresql://$(POSTGRES_HOST):$(POSTGRES_PORT)/$(POSTGRES_DB) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  -user=$(POSTGRES_USER) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  -password=$(POSTGRES_PASSWORD) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  -baselineOnMigrate=true \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	  migrate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ migrate: migrate-data-registry
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;マイグレーションしてみる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% make migrate       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run --rm \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          --network yoshimoto-samonji_yoshimoto-samonji \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          -v $(pwd)/services/data-registry/resources/migrations:/flyway/sql \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          flyway/flyway:latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          -url=jdbc:postgresql://db:5432/yoshimoto_samonji \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          -user=yoshimoto \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          -password=samonji \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          -baselineOnMigrate=true \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          migrate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WARNING: Storing migrations in &amp;#39;sql&amp;#39; is not recommended and default scanning of this location may be deprecated in a future release
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Flyway OSS Edition 13.0.0 by Redgate
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;See release notes here: https://help.red-gate.com/help/flyway-cli13/help_0.aspx?topic=release-notes-and-older-versions/release-notes-for-flyway-engine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Database: ******** (PostgreSQL 18.4)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Schema history table &amp;#34;public&amp;#34;.&amp;#34;flyway_schema_history&amp;#34; does not exist yet
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully validated 1 migration (execution time 00:00.013s)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;All configured schemas are empty; a baseline marker will not be added to Flyway&amp;#39;s schema history table. A baseline or migration script with a lower version than the baseline version may execute if available. Check the Schemas parameter if this is not intended. See https://help.red-gate.com/help/flyway-cli13/help_0.aspx?topic=baseline-on-migrate for more info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Creating Schema History table &amp;#34;public&amp;#34;.&amp;#34;flyway_schema_history&amp;#34; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Current version of schema &amp;#34;public&amp;#34;: &amp;lt;&amp;lt; Empty Schema &amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Migrating schema &amp;#34;public&amp;#34; to version &amp;#34;001 - init&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Successfully applied 1 migration to schema &amp;#34;public&amp;#34;, now at version v001 (execution time 00:00.012s)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;%
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑マイグレーションできた。&lt;/p&gt;
&lt;p&gt;DBの状況を確認したいのでデータベースビューアを導入する。
&lt;a href=&#34;https://hub.docker.com/_/adminer/&#34;&gt;コンテナ版adminer&lt;/a&gt;を使うことにした:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:docker-compose.yaml&#34; data-lang=&#34;diff:docker-compose.yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+   db-viewer&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+     image&lt;/span&gt;: adminer:latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+     ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+       - &amp;#34;${DB_VIEWER_PORT:-8080}:8080&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+     depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+       - db
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+     networks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+       - yoshimoto-samonji
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+     environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+       ADMINER_DEFAULT_SERVER&lt;/span&gt;: db
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;make&lt;/code&gt;ターゲットにも&lt;code&gt;db-viewer&lt;/code&gt;を追加しておく:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  	MONOLITH_IMAGE=$(MONOLITH_LOCAL_IMAGE):latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  	DATA_REGISTRY_IMAGE=$(DATA_REGISTRY_LOCAL_IMAGE):latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  	VALIDATE_RESPONSE=$(VALIDATE_RESPONSE) \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- 	$(DOCKER_COMPOSE) up -d --no-build monolith data-registry db repl
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+ 	$(DOCKER_COMPOSE) up -d --no-build monolith data-registry db repl db-viewer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再度&lt;code&gt;make docker-up&lt;/code&gt;する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% make docker-up                                   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MONOLITH_IMAGE=yoshimotosamonji-monolith:latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        DATA_REGISTRY_IMAGE=yoshimotosamonji-data-registry:latest \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        VALIDATE_RESPONSE= \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        docker compose up -d --no-build monolith data-registry db repl db-viewer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[+] up 5/5
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-db-1            Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-monolith-1      Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-data-registry-1 Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-repl-1          Running                                                                                                                     0.0s 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ✔ Container yoshimoto-samonji-db-viewer-1     Created    
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑&lt;code&gt;db-viewer&lt;/code&gt;が起動した。&lt;/p&gt;
&lt;p&gt;adminerの画面を見てみる:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-23-data/db-viewer.webp&#34;
    alt=&#34;マイグレーションによってテーブルdata_versionsができている&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;マイグレーションによってテーブル&lt;code&gt;data_versions&lt;/code&gt;ができている&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

↑マイグレーションによって意図通りの状態になっていた。&lt;/p&gt;
&lt;h3 id=&#34;リポジトリハンドラの実装&#34;&gt;リポジトリ・ハンドラの実装&lt;/h3&gt;
&lt;p&gt;リポジトリを下記のように実装する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure:repository.clj&#34; data-lang=&#34;clojure:repository.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;data-registry.repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#2aa198&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#268bd2&#34;&gt;next.jdbc&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;jdbc&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#268bd2&#34;&gt;next.jdbc.connection&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;connection&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#268bd2&#34;&gt;cheshire.core&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;json&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#268bd2&#34;&gt;clojure.tools.logging&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;log&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#2aa198&#34;&gt;:import&lt;/span&gt; [&lt;span style=&#34;color:#268bd2&#34;&gt;com.zaxxer.hikari&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;HikariDataSource&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#719e07&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;^&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;:private&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;atom&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;nil&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;init-pool&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#b58900&#34;&gt;if-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;db-url&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;System/getenv&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;DATABASE_URL&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;reset!&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;connection/-&amp;gt;pool&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;HikariDataSource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&lt;span style=&#34;color:#2aa198&#34;&gt;:jdbcUrl&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;db-url&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#2aa198&#34;&gt;:maximumPoolSize&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#2aa198&#34;&gt;:connectionTimeout&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;30000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#2aa198&#34;&gt;:maxLifetime&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;600000&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;log/warn&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;DATABASE_URL not set, skipping pool initialization&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;get-pool&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#b58900&#34;&gt;or &lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#719e07&#34;&gt;do &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;log/warn&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Pool not initialized, initializing now&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#268bd2&#34;&gt;init-pool&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#719e07&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;.addShutdownHook&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;Runtime/getRuntime&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;Thread.&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;^&lt;/span&gt;{&lt;span style=&#34;color:#2aa198&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;db-pool-shutdown&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#719e07&#34;&gt;#&lt;/span&gt;(&lt;span style=&#34;color:#b58900&#34;&gt;when-let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#719e07&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#268bd2&#34;&gt;log/info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Closing database pool&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#268bd2&#34;&gt;.close&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;p&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;insert-catch-at-age&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Insert catch-at-age dataset into database&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-pool&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;result&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;jdbc/execute!&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;INSERT INTO data_versions (version_id, data_type, metadata, data) VALUES (?, ?, ?, ?)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;catch_at_age&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;log/info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Inserted catch-at-age data with version_id:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#268bd2&#34;&gt;result&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;Exception&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;log/error&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Failed to insert catch-at-age data:&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;必要な依存も下記のように追加する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:deps.edn&#34; data-lang=&#34;diff:deps.edn&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;com.github.seancorfield/next.jdbc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  {&lt;span style=&#34;color:#2aa198&#34;&gt;:mvn/version&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;1.3.894&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;org.postgresql/postgresql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  {&lt;span style=&#34;color:#2aa198&#34;&gt;:mvn/version&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;42.7.3&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;cheshire/cheshire&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  {&lt;span style=&#34;color:#2aa198&#34;&gt;:mvn/version&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;5.13.0&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;com.zaxxer/HikariCP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  {&lt;span style=&#34;color:#2aa198&#34;&gt;:mvn/version&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;5.1.0&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;ch.qos.logback/logback-classic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;  {&lt;span style=&#34;color:#2aa198&#34;&gt;:mvn/version&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;1.5.3&amp;#34;&lt;/span&gt;}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;coreは下記のようにコネクションプールを確保するようにする:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:src/data-registry/core.clj&#34; data-lang=&#34;diff:src/data-registry/core.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;data-registry.core&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#2aa198&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#268bd2&#34;&gt;ring.adapter.jetty&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;jetty&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;            [&lt;span style=&#34;color:#268bd2&#34;&gt;data-registry.routes&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;routes&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;            [&lt;span style=&#34;color:#268bd2&#34;&gt;data-registry.routes&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;routes&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;            [&lt;span style=&#34;color:#268bd2&#34;&gt;data-registry.repository&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;repository&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;start-server&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;+.&lt;/span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;repository/init-pool&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;port&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;Integer/parseInt&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;or &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;System/getenv&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;CONTAINER_PORT&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;3000&amp;#34;&lt;/span&gt;))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;jetty/run-jetty&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;routes/app-router&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:port&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;port&lt;/span&gt;})))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;-main&lt;/span&gt; [&lt;span style=&#34;color:#719e07&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;args&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;start-server&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ルータは下記のように変更する:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:src/data-registry/routes.clj&#34; data-lang=&#34;diff:src/data-registry/routes.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;catch-at-age-handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;POST /v0/catch-at-age&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#268bd2&#34;&gt;req&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;log/info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Request body:&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;req&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;body&lt;/span&gt; (&lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;req&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;schema/validate-catch-at-age-request&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;species&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:species&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;stock&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:stock&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;year&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-in&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt; [&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:assessmentYear&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:message&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Registered %s (%s) for year %d&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;species&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;stock&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;year&lt;/span&gt;)}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt; (&lt;span style=&#34;color:#2aa198&#34;&gt;:metadata&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt; (&lt;span style=&#34;color:#2aa198&#34;&gt;:dataset&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt; (&lt;span style=&#34;color:#b58900&#34;&gt;str &lt;/span&gt;(&lt;span style=&#34;color:#268bd2&#34;&gt;System/currentTimeMillis&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;_&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;repository/insert-catch-at-age&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:detail&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Registered %s (%s)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                                     (&lt;span style=&#34;color:#2aa198&#34;&gt;:species&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                                     (&lt;span style=&#34;color:#2aa198&#34;&gt;:stock&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;))}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;validated-response&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;schema/validate-response&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:catch-at-age-200&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;response&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&lt;span style=&#34;color:#2aa198&#34;&gt;:status&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;validated-response&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;Exception&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#268bd2&#34;&gt;log/error&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Error in catch-at-age-handler&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:error&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;)})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {&lt;span style=&#34;color:#2aa198&#34;&gt;:status&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;500&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;:body&lt;/span&gt; {&lt;span style=&#34;color:#2aa198&#34;&gt;:error&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;)}})))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑ひとまず現時点では、リポジトリを直接使うことにする。&lt;/p&gt;
&lt;p&gt;これまで通り、&lt;code&gt;make up&lt;/code&gt;でサーバーを立ち上げ、リクエストを投げる:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% curl -X POST localhost:31505/v0/catch-at-age \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &amp;#39;{&amp;#34;metadata&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;species&amp;#34;: &amp;#34;マイワシ&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;stock&amp;#34;: &amp;#34;太平洋系群&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;assessmentYear&amp;#34;: 2026},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &amp;#34;dataset&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;valueUnit&amp;#34;: &amp;#34;ton&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;dataSet&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;0&amp;#34;: {&amp;#34;2025&amp;#34;:123, &amp;#34;2026&amp;#34;: 456},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;1&amp;#34;: {&amp;#34;2025&amp;#34;:234, &amp;#34;2026&amp;#34;: 567}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &amp;#34;Content-Type: application/json&amp;#34; &amp;amp;&amp;amp; echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&amp;#34;error&amp;#34;:&amp;#34;ERROR: column \&amp;#34;metadata\&amp;#34; is of type jsonb but expression is oftype hstore\n  Hint: Youwill need to rewrite or cast the expression.\n  Position: 83&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑おや。&lt;/p&gt;
&lt;p&gt;JSONにシリアライズするのを忘れていた:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff:src/data_registry/repository.clj&#34; data-lang=&#34;diff:src/data_registry/repository.clj&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#268bd2&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#268bd2&#34;&gt;insert-catch-at-age&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Insert catch-at-age dataset into database&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [&lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#268bd2&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#719e07&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;get-pool&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;metadata-json&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;json/generate-string&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;          &lt;span style=&#34;color:#268bd2&#34;&gt;dataset-json&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;json/generate-string&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;)    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#268bd2&#34;&gt;result&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;jdbc/execute!&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;pool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;                   [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;INSERT INTO data_versions (version_id, data_type, metadata, data) VALUES (?, ?, ?, ?)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                   [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;INSERT INTO data_versions (version_id, data_type, metadata, data) VALUES (?, ?, ?::jsonb, ?::jsonb)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;catch_at_age&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;metadata&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;- &lt;/span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;dataset&lt;/span&gt;])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;metadata-json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#b58900&#34;&gt;+ &lt;/span&gt;                    &lt;span style=&#34;color:#268bd2&#34;&gt;dataset-json&lt;/span&gt;])]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#268bd2&#34;&gt;log/info&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Inserted catch-at-age data with version_id:&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;version-id&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#268bd2&#34;&gt;result&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#268bd2&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;Exception&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#268bd2&#34;&gt;log/error&lt;/span&gt; &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;Failed to insert catch-at-age data:&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#268bd2&#34;&gt;.getMessage&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#268bd2&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#268bd2&#34;&gt;e&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再度リクエスト:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;% curl -X POST localhost:31505/v0/catch-at-age \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &amp;#39;{&amp;#34;metadata&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;species&amp;#34;: &amp;#34;マイワシ&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;stock&amp;#34;: &amp;#34;太平洋系群&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;assessmentYear&amp;#34;: 2026},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &amp;#34;dataset&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;valueUnit&amp;#34;: &amp;#34;ton&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &amp;#34;dataSet&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;0&amp;#34;: {&amp;#34;2025&amp;#34;:123, &amp;#34;2026&amp;#34;: 456},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &amp;#34;1&amp;#34;: {&amp;#34;2025&amp;#34;:234, &amp;#34;2026&amp;#34;: 567}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &amp;#34;Content-Type: application/json&amp;#34; &amp;amp;&amp;amp; echo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&amp;#34;detail&amp;#34;:&amp;#34;Registered マイワシ (太平洋系群)&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;↑今度は保存できた。&lt;/p&gt;
&lt;p&gt;何度か叩いてみてからデータベースの状態を見てみると、無事データが登録されていることを確認できた:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-07-23-data/registered.webp&#34;
    alt=&#34;JSONB型はデータを目視できる点も楽&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;JSONB型はデータを目視できる点も楽&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;ここまでで一段落だが、現時点の実装では&lt;code&gt;versionId&lt;/code&gt;がただの現在時刻になってしまっている。
&lt;code&gt;versionId&lt;/code&gt;は結果に追跡性をもたせるために重要な値なので、次はここを直していく。&lt;/p&gt;
&lt;p&gt;ちょっと力尽き気味なので今回はここまで。&lt;/p&gt;
&lt;p&gt;本記事でやったことと残作業↓:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; API契約を書く&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; ルーティングの動作確認&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; db セットアップ&lt;/li&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; リポジトリ・ハンドラの実装&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; datasetVersion生成ロジックの設計&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; リファクタリング&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; エラーハンドリングの追加&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;所感&#34;&gt;所感&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一人で手探りでやってると観点漏れ（セキュリティ、リソース管理、データキャパシティ設計など）が起こりがち&lt;/li&gt;
&lt;li&gt;このプロジェクトを始めてから、OSSコミュニティへの感謝の念がさらに強まっている。ありがとうございます。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;高齢魚は個体数が少ない傾向にあるので、資源評価ではある年齢以上をひとくくりの階級にすることが多い。「5+」は「5歳以上」の意味&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
    </item>
    
  </channel>
</rss>
