LoginSignup
0

posted at

updated at

【kabusapp-restserver】自前のRESTサーバーを作成する

はじめに

過去記事は「auカブコム証券のkabuステーションREST APIに関する記事一覧」。

そろそろスタンドアロン前提だと、作れば作るほどPC環境が辛くなってくるので、自前のRESTサーバーを立てて、auカブコム証券APIに直接関係ない処理をスケールアウトできるようにする。

レポジトリとプロジェクト

プロジェクトの種類が異なるため、レポジトリ(kabusapisrv)を新規に作成した。
mavenプロジェクトをspring-bootを選んだが、バージョンが古くて、自分でpom.xmlを編集するのとあまり変わらなかった。

  • org.springframework.boot / spring-boot-starter-parent / 2.7.4
  • org.apache.httpcomponents / httpclient (HTTP接続テスト用)

実装

パッケージとクラス

RDBを使っていない自前でテキストファイルのI/Oの永続化だが、MVCぽくパッケージとクラスを作成する。
保存先は、今まで/tmp/chart/だったので、競合しないように/tmp/server/chart/にする。

  • server.rest / ChartDataController
  • server.service / ChartDataService
  • server.repository / ChartDataRepository

テストPGM

他のPGMからHTTPアクセスすることになるが、将来自動テストのために、自分自身にHTTPアクセスするテストPGMも作って、接続確認/単体テストに使う。

  • test / MainTestClient

Spring Bootを選ぶと、標準でjacksonが使えるので、これを使って、Javaインスタンス→JSON文字列変換を行う。
なお、既存のPGMに組み込もうと思ったら、swaggerがgsonを使っているので、この部分が違うソースになる。

	private static String jsonData(ChartData cd) throws JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(cd);
		return json;
	}

HTTPアクセスはcommons httpClientのころから使っていたので、Apache HttpClientを使う。
JSONをまるごとPOSTしたいので、StringEntityを作成する。この部分はString dataを渡すので、JSONパーサーは関係しない。

		StringEntity entity = new StringEntity(data, ContentType.APPLICATION_JSON);
		try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(uri);
			httpPost.setEntity(entity);
			try (CloseableHttpResponse response = httpclient.execute(httpPost)) {

テスト

SampleTomcatApplicationを実行して、ポート8080でHTTPサーバーを立ち上げる。
MainTestClientを実行すると、架空のcode=123で3レコードが送信され、/tmp/server/chart/123にChartData.csvが作成される。

追記:重複チェック付きのチャートデータ登録

r1版は無条件に追記していたが、r2版として、メモリ上のListとSetに読み込み、Setに含まれているかどうかのチェックを追加する。

追記:チャートDBの登録

別URI(/chartDb/r1)でチャートDBの上書き保存するAPIを追加する。

追記:レポジトリのロードと一覧

ディレクトリ内のすべてのファイルをロードするURI(/repo/load)と、ロードされている一覧を返すURI(/repo)を追加する。
レスポンスはHTMLではないが、RESTでなくWeb扱いのコントローラーで作る(server.web.RepositoryController)。

追記:マージツールをRESTサーバーへ移植

v38.MainMergeChartData_r10を、RESTサーバーのマージURI(/merge)に移植する。
ただし、/tmp/server/dbと/tmp/server/chartから毎回ファイルを読んでいるが、ChartDbRepositoryとChartDataRepositoryに持っている。
/tmp/server/chart/*のディレクトリ一覧のみChartDataRepository.list()が用意している。

追記:CalendarLogicとChartDbRepositoryが連携

CalendarLogic.readCalendar()を廃止し、ChartDbRepositoryからListをinitCalendar()に渡す。
ChartDbRepositoryは、load()とwrite()のタイミングで、CalendarLogicに反映する。

追記:MergeChartDataCommon_r10とChartDbRepositoryが連携

MergeChartDataCommon_r10.readDbChartData()にChartDbRepositoryを渡すことで、ファイルを直接読まずに、Repositoryが管理している最新のリストを取得する。

追記:MergeChartDataCommon_r10とChartDataRepositoryが連携

MergeChartDataCommon_r10.readCsvChartData()にChartDataRepositoryを渡すことで、ファイルを直接読まずに、Repositoryが管理している最新のリストを取得する。

追記:テクニカル指標計算ツールをRESTサーバーへ移植

v38.MainCalcIndicator_r10を、RESTサーバーのテクニカル指標計算URI(/calc)に移植する。
マージツールと同様に、/tmp/server/chartから毎回ファイルを読んでいる。
ただし、今回の入力ファイルは、マージツールの出力ファイルのため、ChartDbRepositoryには登録されずに、直接ファイルに保存されている。
効率化のため、ファイルに保存せずにパイプのようなデータ連携をしたいので、別途Repositoryを作成する。

追記:MergeChartDataCommon_r10とCalcIndicatorServiceの間にMergeDataRepositoryが連携

MergeDataRepositoryを作成して、MergeChartDataCommon_r10の出力と、CalcIndicatorServiceの入力につなげる。

追記:gitレポジトリ名の変更(kabusapisrv -> kabusapp-restserver)

後からgitレポジトリを追加していくと、紛らわしい名前で勘違いするので、ハイフンを付けた名前に変更する。

追記:イベントトリガー発火ツールをRESTサーバーへ移植

v39.MainTriggerIndicator_r11を、RESTサーバーのトリガーURI(/trigger)に移植する。
テクニカル指標計算ツールと同様に、/tmp/server/chartから毎回ファイルを読んでいる。
後から、効率化のため、テクニカル指標計算ツールの出力ファイルのために、別途Repositoryを作成する。

追記:CalcCoordinator_r10とTriggerCoordinator_r11の間にIndicatorDataRepositoryが連携

IndicatorDataRepositoryを作成して、CalcCoordinator_r10の出力と、TriggerCoordinator_r11の入力をつなげる。

ファイル数が多くなってきたので、従来の/repoを以下のようなサマリーにして、/repo/listがファイルリストを表示する。

ChartDataRepository: File: 14 , Line: 60228
ChartDbRepository: File: 161 , Line: 401295
MergeDataRepository: File: 196 , Line: 784320
IndicatorDataRepository: File: 1568 , Line: 69742

追記:イベントトリガー発火ツールをRESTサーバーへ移植(Tickデータ監視)

v40.MainTriggerChartData_r12を、RESTサーバーのトリガーURI(/trigger/tick)に移植する。
TickデータはChartDataRepositoryで管理されているので、ファイルから読まない。

なお、v39.MainTriggerIndicator_r11のイベントトリガーとは監視対象が異なるため、こちらをトリガーURI(/trigger/indicator)に変更し、両方を順番に実行するトリガーURI(/trigger)の3つのエントリーポイントを用意する。

ほとんどChartDataという名称を使ってきたが、Tickデータは、4本値と違い同一時刻の複数レコードを持つことが出来るため、コンソールアプリ側から出来る限りChartDataをTickDataに変更する。ツールエントリv40.MainTriggerChartData_r12はv40.MainTriggerTickData_r12となる。なお、4本値とTickデータの両方を含む場合(広義のChartData)は、マージ後の4本値(狭義のChartData)と区別しない。

追記:名称ChartDataをTickDataに変更

イベントトリガーに関連する部分のみ、ChartDataをTickDataに変更する。

クラス名
v40.MainTriggerChartData_r12 to v40.MainTriggerTickData_r12
v40.TriggerChartData_r12 to v40.TriggerTickData_r12

javadocコメント
チャート to ティック
マージ to 抽出

ファイル名
TriggerIndicator.out to TriggerTickData.out

追記:マージツールを先頭カラムのタイムスタンプに対応する

マージURI(/merge)を/merge_r10に変更する。
v45(r17)をRESTサーバーへ移植し、マージURI(/merge)とする。

以下の修正を反映する。

  • 定数名CHART_CSV_FILENAMEに統一
  • 同じChartData.csvの読み込みを1回にする
  • fix 置換時にprevが代入されていない/readCsvChartData()からreadCsvChartLine()を切り出し
  • CSVファイルのコメント行チェック

追記:Tickデータのトリガーを先頭カラムのタイムスタンプに対応する

トリガーURI(/trigger/tick)を対応する。

以下の修正を反映する。

  • MergeChartInfo_r10をv43.beanからbeanに移動
  • CalcIndicatorInfo_r10をv43.beanからbeanに移動
  • TriggerIndicatorInfo_r11をv39.beanからbeanに移動/EventInfo_r11に変更
  • EventInfo_r11にComparable実装/idの変更(日付を前へ)
  • コピーコンストラクタに置き換え(未使用)

追記:未使用のURIを削除

旧バージョンのソースを残すと、メンテが大変なので、未使用のURIを削除する。
アーカイブしようかと思ったが、依存性が強く、まるごとコピーとほとんど変わらないので、止める。
なお、APIバージョンは先頭の方がよかった(/r1/chartData)。

  • /chartData/r1
  • /merge_r10
  • /calc_r10
  • /trigger_r10
  • /trigger/indicator_r10
  • /trigger/tick_r10

追記:監視URI(/watch)、/chartDataと関連付け

コンソールアプリのファイル監視がWatchChartDataであったため、URIを/watchとしたが、WatchChartDataがChartData.csvの更新を監視するのと同様に、/chartData/r2にチャートデータを受信したときに、連携して起動する。
URIは、手動でテスト目的。

githubソース

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0