Slide 1

Slide 1 text

最新のSpring Shellの使い方 中尾正剛 PayPayカード株式会社 https://x.com/web_shogo_nakao

Slide 2

Slide 2 text

私について 経歴 2011/04 SES(中小企業) 2015/01 (Web系)株式会社セレス 2020/10 (Web系)エキサイト株式会社 2023/11 (金融系)PayPayカード株式会社

Slide 3

Slide 3 text

はじめに 本日話すこと SpringBootは、Webアプリケーションフレームワークというのが一般的な認識だと思います が、Batch処理を作ることも出来ます。 使うライブラリで一番最初に候補に出てくるのはSpring Batchだと思います。 もちろんSpring Batchでも良いのですが、Webアプリケーションフレームワークの使い方と 違って独特な部分が多く、つまずきポイントが多いのではないでしょうか? そこで、少しマイナーですが、Spring Shellというライブラリも存在します。 Spring Shellのほうが、Spring Batchよりシンプルで使いやすいと思います。 その理由と、最新のSpring Shellの使い方について説明します。

Slide 4

Slide 4 text

はじめに Batchとは コンピューターの処理において一度に複数のタスクや処理を実行するための方法のことを指し ます。主に以下の特徴があります: プログラムやジョブを一括して自動的に実行する処理方式です。 1. データやタスクを連続して処理できます。 2. レポート生成などで使用され、効率的な大量処理に適しています。 3. リアルタイム処理と異なり、データを一定量蓄積してから処理を行う特徴があります。 4. リアルタイム処理で不要な処理を実行するのに適しています。 5.

Slide 5

Slide 5 text

目次 Spring Batchとは 01 02 03 04 05 Spring Shellとは なぜシンプルなのか? Spring Shellの使い方 まとめ

Slide 6

Slide 6 text

Spring Batchとは 概要 Spring Batch は、ログ/トレース、トランザクション管理、ジョブ処理統計、ジョブの再開、 スキップ、リソース管理など、大量のレコードを処理する上で不可欠な再利用可能な機能を提 供します。また、最適化とパーティショニングの手法により、非常に大容量で高性能なバッチ ジョブを可能にする、より高度な技術サービスと機能も提供します。単純なバッチ ジョブも 複雑なバッチ ジョブも、非常にスケーラブルな方法でフレームワークを活用し、大量の情報 を処理できます。

Slide 7

Slide 7 text

Spring Batchとは 特徴 処理の流れを定型化する機能 タスクレットモデル シンプルな処理 自由に処理を記述する方式である。SQLを1回発行するだけ、コマンドを発行す るだけ、といった簡素なケースや 複数のデータベースやファイルにアクセスし ながら処理するような複雑で定型化しにくいケースで用いる。 チャンクモデル 大量データを効率よく処理 一定件数のデータごとにまとめて入力/加工/出力する方式。データの入力/ 加工/出力といった処理の流れを定型化し、 一部を実装するだけでジョブが実 装できる。 ジョブの管理 実行状況の永続化、データ件数を基準にしたリスタートなどを可能にする。

Slide 8

Slide 8 text

Spring Batchとは Spring Batch バッチ処理という比較的複雑な処理を抽象化するために、多くの概念 (Job, Step, ItemProcessor, ItemReader, ItemWriterなど)を 持ち合わせています。

Slide 9

Slide 9 text

Spring Batchとは Spring Batch Jobの登録 Stepの設定 データを読み込むreader() データを処理するprocessor() CSVファイルに書き出すwriter()

Slide 10

Slide 10 text

Spring Batchとは Spring Batch @Bean public Job outputUserDataJob() { return jobBuilderFactory.get("outputUserData") .start(outputUserDataStep()) .build(); } @Bean public Step outputUserDataStep() { return stepBuilderFactory.get("outputUserDataStep") .tasklet(fileProcessingTasklet()) // -> タスクレットの場合 .reader(reader()) // -> チャンクモデルの場合 .processor(processor()) // -> チャンクモデルの場合 .writer(writer()) // -> チャンクモデルの場合 .build(); }

Slide 11

Slide 11 text

Spring Batchとは タスクレット @Bean public Tasklet fileProcessingTasklet() { Files .lines(Paths.get(inputPath)) // ItemReader .map(line -> String.join(",", line.parts[0], line.parts[1].toUpperCase(), line.parts[2])) // ItemProcessor .forEach(processedLine -> Files.write(Paths.get(outputPath), processedLine.getBytes())); // ItemWriter }

Slide 12

Slide 12 text

Spring Batchとは チャンクモデル @Bean public FlatFileItemReader reader() { return new FlatFileItemReaderBuilder() .name("userItemReader") .resource(new FileSystemResource("input.csv")) .delimited() .names(new String[]{"id", "name", "email"}) .targetType(User.class) .build(); } @Bean public ItemProcessor processor() { return user -> user.setName(user.getName().toUpperCase()); } @Bean public FlatFileItemWriter writer() { return new FlatFileItemWriterBuilder() .name("userItemWriter") .resource(new FileSystemResource("output.csv")) .delimited() .names(new String[]{"id", "name", "email"}) .build(); }

Slide 13

Slide 13 text

Spring Shellとは 概要 Spring Shell プロジェクトのユーザーは、Spring Shell jar に依存し、独自のコマンド (Spring Bean のメソッドとして提供される) を追加することで、フル機能のシェル (別名、コ マンド ライン) アプリケーションを簡単に構築できます。 コマンド ライン アプリケーションを作成すると、プロジェクトの REST API と対話したり、 ローカル ファイル コンテンツを操作したりするときに便利です。

Slide 14

Slide 14 text

Spring Shellとは 特徴 カスタムコマンドを提供するための、シンプルで注釈駆動型のプログラミングモデル コマンドプラグイン戦略の基礎として Spring Boot の自動構成機能を使用する タブ補完、カラー化、スクリプト実行 コマンドプロンプト、シェル履歴ファイル名、結果とエラーの処理のカスタマイズ ドメイン固有の基準に基づいたコマンドの動的な有効化 Bean検証APIとの統合 画面クリア、ゴージャスヘルプ、終了などの組み込みコマンド 書式設定、配置、装飾的な境界線などを備えた ASCII アート テーブル。

Slide 15

Slide 15 text

Spring Shellとは バッチ処理という比較的複雑な処理を抽象化するために、多くの概念 (Job, Step, Tasklet, ItemReader, ItemWriterなど)を 持ち合わせています。 Spring Shellに こんな概念はなし

Slide 16

Slide 16 text

Spring Shellとは どちらかというとSpring Webに近い Controller -> Service -> Repository のController部分のアノテーションが変わるイメージ @Controller,@RestController,@RequestMapping -> @Command(command = "xxx") @RequestParam -> @Option 引数 @Operation -> @Description 概要 (Springdoc-openapi)

Slide 17

Slide 17 text

Spring Shellとは 先ほどのSpring Batchの例をSpring Shellで実装 @Command public class MyCommands { @Command(command= "outputUserData") @Description(desc = “ユーザーデータの作成”) public void mycommand(@Option String userId) throws IOException { Files .lines(Paths.get(inputPath)) // ItemReader .map(line -> String.join(",", line.parts[0], line.parts[1].toUpperCase(), line.parts[2])) // ItemProcessor .forEach(processedLine -> Files.write(Paths.get(outputPath), processedLine.getBytes())); // ItemWriter } }

Slide 18

Slide 18 text

controller service repository domain なぜシンプルなのか? Spring Webの全体像(自分なりの解釈)

Slide 19

Slide 19 text

controller service repository domain なぜシンプルなのか? 自分なりの解釈の解像度を上げる フレームワークに依存しない フレームワークに依存する

Slide 20

Slide 20 text

controller service repository domain なぜシンプルなのか? 自分なりの解釈の解像度を上げる フレームワークに依存しない 外から中に入る つなぎこむ 中から外へ取りに行く フレームワークに依存する

Slide 21

Slide 21 text

controller service repository domain なぜシンプルなのか? 自分なりの解釈の解像度を上げる フレームワークに依存しない 外から中に入る つなぎこむ 中から外へ取りに行く フレームワークに依存する

Slide 22

Slide 22 text

@Controller @Service なぜシンプルなのか? 自分なりの解釈の解像度を上げる @RestController @Command Web API Batch Spring Batch

Slide 23

Slide 23 text

Spring Shellの使い方 最新ではデフォルトで非対話モード // 非対話モードで必要だったコード @Component @Order(InteractiveShellApplicationRunner.PRECEDENCE - 1) public class NonInteractiveRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { InteractiveShellApplicationRunner.disable((configurableEnvironment)); final Object evaluate = shell.evaluate(() -> String.join(" ", args.getSourceArgs())); if (evaluate != null) { System.out.println(evaluate); } } }

Slide 24

Slide 24 text

Spring Shellの使い方 アノテーションが少し変わっている @ShellComponent @ShellMethod ->@Command @ShellOption -> @Option

Slide 25

Slide 25 text

Spring Shellの使い方 helpでコマンド一覧が出てくる @Command(command = "user-create", description = "ユーザーを作成するコマンド") public String createUser( @Option(shortNames = 'n', longNames = "name", description = "ユーザー名") String name, @Option(shortNames = 'a', longNames = "age", description = "ユーザーの年齢") Integer age ) {} @Command(command = "database-connect", description = "データベースに接続するコマンド") public String connectDatabase( @Option(shortNames = 'h', longNames = "host", description = "データベースホスト") String host, @Option(shortNames = 'p', longNames = "port", description = "データベースポート") Integer port ) {}

Slide 26

Slide 26 text

Spring Shellの使い方 helpでコマンド一覧が出てくる Available commands: user-create ユーザーを作成するコマンド -n, --name ユーザー名 -a, --age ユーザーの年齢 database-connect データベースに接続するコマンド -h, --host データベースホスト -p, --port データベースポート

Slide 27

Slide 27 text

Spring Shellの使い方 helpでコマンド一覧が出てくる > user-create --help Command: user-create Description: ユーザーを作成するコマンド Arguments: name String ユーザー名 age Integer ユーザーの年齢 Options: -n, --name ユーザー名 -a, --age ユーザーの年齢

Slide 28

Slide 28 text

まとめ Spring Shell 使い方簡単でしたよね? Spring Batchとは全くの別物 どちらかというとSpring Webに近い @Controller,@RestController,@RequestMapping -> @Command(command = "xxx") @RequestParam -> @Option 引数 @Operation -> @Description 概要 (Springdoc-openapi) デフォルトで非対話モード アノテーションに変更有(旧も使えます) helpでコマンド一覧を出せる