Apache Commons Email でメール本文に画像を埋め込む

Apache Commons Email でメール本文に画像を埋め込む方法。備忘録。

HtmlEmail email = new HtmlEmail();
// ... (略)
File file = Paths.get("duke.jpg").toFile();
String cid = email.embed(file);
email.setMsg("本文1<br><img src=\"cid:" + cid + "\"><br>本文2");
email.send(); //=> 本文1<br><img src="cid:yektmylwmn"><br>本文2

img タグの src に指定する cid (Content-ID) は、HtmlEmail.embed の戻り値 (ランダムな値) を使うか、第2引数に任意の値を指定する。

2019年のふりかえりと2020年に向けて

年末年始は帰省先で過ごしております。

2018年のふりかえりと2019年のこと - kntmr-blog

2019年はあっという間に過ぎた感じ。前半は仕事が忙しくなかなか大変で、後半は仕事が落ち着いたので個人的にいろいろと動き回ってましたが、自分のスキルや経験の不足を改めて痛感...。

2018年夏頃から始めたスタディサプリ ENGLISH の進捗はこんな感じ。基本的に通勤時間を使ってコツコツやっています。日常英会話の Lv.3 はひと通り終わって、今は Lv.4 を 1/3 くらい。帰省先にいるので今週はやってないけど。

f:id:knt_mr:20191231152315j:plain

2020年は、個人的に興味/関心があることを調べたり勉強したりということをもっと意欲的に&習慣的にやっていきたい。ただ、これらがあまり直接業務に関係しないところが悩ましい...。

  • GraphQL
  • Vue.js + TypeScript
  • OCJP Gold SE 11
  • AWS 認定資格
  • 英語/TOEIC

なんとなく、ここ数年同じようなことばかりやってるような気がするので、もう少し目線を変えた方がいいのかなと思っている今日この頃です。

Windows 向けキーボード周りの設定

備忘録。Windows マシンをセットアップする際に最初にやるキーボード周りの設定。

CapsLock を Ctrl に

レジストリエディタから HKEY_LOCAL_MACHINE > SYSTEM > CurrentControlSet > Control > Keyboard Layout を開いてバイナリ値を追加。

f:id:knt_mr:20191227133023p:plain

IME ON/OFF

Mac のキーボードと同様に、スペースキーの隣に IME の ON/OFF を配置する。

  1. IME のプロパティ
  2. 詳細設定
  3. 全般タブ > 編集操作 > 変更
  4. 無変換 ⇒ IME-オフ / 変換 ⇒ IME-オン

Spring Fest 2019 に行ってきた #jsug

Spring Fest 2019 に行ってきました。簡単に所感をまとめます。

springfest2019.springframework.jp

所感

3回目の参加。朝イチで仕事の打ち合わせが入ってしまい基調講演は聴けず。

GraalVM や RSocket, Quarkus, コンテナ/クラウドなど、個人的に気になるキーワードが並んでたのですが、このあたりは普段の JSUG 勉強会でもテーマになりそうかなと思って、今回はあえてそれ以外のテーマを中心にピックアップしてみました。とはいえ、コンテナ関連の話は聴いておけばよかったかな...。

個人的には Micrometer や Spring Cloud Contract + Pact あたりのセッションがよかったです。

以下、メモから抜粋。

Spring Boot爆速開発超絶技巧

  • キーマップはデフォルトがおすすめ (ペアプロが捗る)
  • 入力ソースはUSキーボードで
    • 日本語IMEの半角英数モードだとショートカットが衝突する
  • タッチバー無効化 (Fnキーの方が高機能)
  • 検索/ファイルオープン系
  • ナビゲーション系
  • ポップアップでは絞り込みを使う
  • 指定クラスの指定行にジャンプ
  • Tab/Enterの補完の違い
    • Tabで補完すると以前の記述を置換できる
  • ステートメントを完結 (その行をフォーマットしてセミコロンを付けてくれる)
  • Live Template
  • Postfix completion
  • ブレークポイントを条件指定で止める/標準出力
  • Spring Dashboard + Services
  • Docker コンテナないのファイルが見れる
  • Actuator のエンドポイントから HTTP リクエス
  • Git でコミット時にフォーマットしたり壊れたコードを検出したり
  • プルリクを作成したり確認したりコメント追加/確認したり
  • おすすめプラグイン
    • Key Promoter X
    • Presentation Assistant
    • Rainbow Bracket

普段は Eclipse ユーザーなのですが、IDE をこんな感じに使って生産性向上できるという視点で参考になりました。IntelliJ IDEA ならではの機能もあるかと思いますが、Eclipse でも同じようなことができるか試してみようかな。Postfix completion は便利そう。あと、Eclipse では View で表示されるものが IntelliJ IDEA ではポップアップで表示されたりしてていい。ブレークポイントを条件指定で止めたり、標準出力に処理結果を出力したりというのはよくやります。

ローコード開発プラットフォームと、ドメイン駆動設計と、Springの関係

yoshinorinie.hatenablog.com

  • 会社を横断して設計のノウハウを共有できないか (業界ごととか)
  • Wagby のデモ
  • ローコード開発 == 少ないコードで実装を進める
    • ノーコードを含む
    • 非エンジニアがツールで実装を手掛ける
  • Java 側の設計情報と実装コードを一致させる
  • 影響分析と自動更新
    • Excel 設計書とソースコードでは影響分析に時間がかかる
    • Excel 設計書からプログラムを自動生成するのは無理
  • ビジネスプロセスプログラミング
  • 自由度が高すぎると自動生成ができない

DDDとローコード開発の共通点は設計情報と実装コードの乖離をなくして変更容易性を向上すること。そこにローコード開発というか Wagby の自動更新を組み合わせることで常に変更可能な基盤を作ることがポイントっぽいです。

徹底解剖Spring MVCアーキテクチャー -DispatcherServletの中身を覗いてきました-

www.slideshare.net

  • HandlerMethodArgumentResolver インタフェース
    • 引数になりえるクラスがそれぞれ実装している
  • 引数に指定可能な型はあらかじめ設定してある (戻り値の型も同様)
    • RequestMappingHandlerAdapter#getDefaultArgumentResolvers
    • RequestMappingHandlerAdapter#getDefaultReturnValueHandlers
  • 戻り値が void の場合はリクエストURLが論理View名となる
  • DispatcherServlet#doDispatch

Spring でコードリーディングする際のポイントとして参考になる内容でした。次回は Spring Boot アプリの起動処理のセッションを期待。

実践 Spring Boot Actuator + Micrometer ⇒ 無茶振りMicrometerの話

docs.google.com

  • Micrometer 自体は Spring に依存しているわけではない
    • いろいろなバックエンドに対応
  • 運用やデバッグで役立つエンドポイント
  • Application metrics
    • アプリケーションだけが知っているメトリクス
  • Tag / dimension / label
  • レスポンスタイムやメモリ使用量のメトリクスをもとにアラートをあげる
  • Gauge
    • Up/Downする値を計測する
  • Counter
    • カウントアップする値を計測する
    • 基本的にクリアしない (バックエンドに送信するときにクリアするのもあり)
    • 値がオーバーフローしなければ問題ない
  • Timer
    • ストップウォッチ
    • 時間計測して max / average したり?
  • Distribution Summary
  • JVM など主要なメトリクスはデフォルトで収集してくれる
  • Actuator を depend に追加しておけば Controller のエンドポイントごとに処理時間を計測してくれる
  • デフォルトはインメモリ
  • バックエンドに送信する場合は必要なものを depend に追加する
    • Auto Configuration がなければ Bean を登録する
  • 複数のバックエンドに送信可
  • AWS Cloud Watch は対応済み、Zabbix は未対応
  • MeterRegistry からカスタムメトリクスを登録できる

代打セッションだったけど、個人的にいちばん興味深い内容でした。今、レガシーなシステムの保守をしていて、アプリケーションログをいい感じに集計するツールを作ろうかと思ってたけど、Micrometer でメトリクスを集計する仕組みを作ってもいいのかなと思いました。導入できそうかちょっと調べてみようかと。

Enterprise Angular Development

  • 画面デザインしてアプリケーションを作る
    • jQuery で実装されたデザインは Angular に移植しにくい
  • 構造をデザインしてアプリケーションを作る
  • Atomic Design
  • Angular Library
  • UI のコンポーネント構成を yaml で定義

もう少し Spring に絡めた内容を期待してましたが、割とフロント寄りの内容でした。JS フレームワークと Spring の組み合わせるときの事例紹介とか聴きたい。

JSP/JSF から Spring Web + Thymeleaf への移行

www.slideshare.net

  • 汎用テンプレートエンジン
  • Thymeleaf はソースコードがきれい
  • Standard dialect + Thymeleaf-Spring パッケージ
  • HTML5 対応済み
  • Spring との高い親和性
  • サーバー起動しなくてもブラウザでレンダリング可能
  • デフォルトの挙動がセキュア☆
  • カスタムタグの開発のしやすさ
  • 時代はクライアントサイドレンダリング?SPA?
  • カスタムダイアレクトによる共通化/再利用
    • (中級者向け) AbstractAttributeTagProcessor / AbstractElementTagProcessor
    • (上級者向け) AbstractElementModelProcessor
  • attoparser
    • HTML パーサー
  • unbescape
    • エスケープライブラリ

Thymeleaf はソースコードがきれいとのこと。パーサーやエスケープのライブラリもおすすめとのことなので、コードリーディングしてるか。

Springアプリケーションのテスト道具 使いどころ、使わないどころ

  • モックのパワフルさが設計を歪める
  • Boot 2.2 から JUnit 5 がデフォルトに
    • vintage は外して JUnit 4 のコードと混在しないようにする
  • CI のビルド/テスト、デプロイ、e2e テスト では Docker を使う
  • レイヤードアーキテクチャではテストは包含関係になりえる
    • どの単位でテストするか
    • できることとすることを区別する
  • 権限のテストは Controller でやる
  • テストしたいことの近くでテストすることが原則
  • 近いところでテストするためにモックがある
  • 使わないどころの判断
    • できる/できない、向き/不向き
    • 不向きなものを無理やり使わない
  • 評価軸☆
    • 作成、保守、実行、評価
  • MockRestServiceServer
  • モックを使うことで何がテストできて何がテストできなくなるか

「モックのパワフルさが設計を歪める」「どのようなテストでも何かしらをモックしている」などのメッセージはなるほどという感じ。普段、気が付かない観点だったり、分かってはいるけどできてないことだったり、評価軸のあたりは参考になりました。

Spring with React for Enterprise Application

  • 要件定義/設計はイベントストーミングで
    • データだけで業務が回っているわけではない
    • モデル化するべき業務プロセスの開始点を探る (Domain Event)
    • (Domain Event) 何が起こったか、起こる条件、与える影響
  • Bounded Context で Deployment unit がわかる
  • モデリングして作ろうとしているものを共有する
  • 一貫性のあるUI、変更に強いUI
    • styled components
    • Storybook
    • Atomic Design
  • サービス/モジュール分割
    • Bounded Context で分割する
    • 各サービスは Boot アプリケーション
    • 各サービスがどのように連携するか (Query or Pub/Sub)
  • Spring のエコシステムは何を使うか
    • 作る機能の特徴によって何を使うか
    • Spring Data REST, Spring MVC, Spring Cloud Stream, ...
  • TDD
  • Integration Test
    • 連携するサービスがたくさんあると大変
    • 起動が遅い
    • モックは信用できない
  • Contract Testing
    • Pact
    • Contract = Pact file
    • Consumer 側でモックを使ってテスト
      • リクエストとレスポンスの期待値を Contract として出力する
    • Broker に Contract ファイルを渡す (モック?)
    • Spring Cloud Contract が Pact から Contract を取得してテストする?
    • モックの信頼性向上

このセッションもとても面白かったです。Spring エコシステムに何を使うか、Spring Cloud Contract + Pact の組み合わせ、などいろいろ興味深い話が聴けました。Spring Fest 2018 でもセッションがあったっぽい。要復習。

blog.tagbangers.co.jp

その他

あとで読む。

www.slideshare.net

www.slideshare.net

docs.google.com

Micronaut で CLI アプリケーション + Picocli

シンプルな CLI アプリを作る機会があり、ちょうど Micronaut を試してみたかったので Micronaut で作ってみました。備忘録。

Standalone Command Line Applications - Micronaut

準備

Micronaut は Scoop でインストール。

> scoop search micronaut
'main' bucket:
    micronaut (1.2.6)

> scoop install micronaut
Installing 'micronaut' (1.2.6) [64bit]
micronaut-1.2.6.zip (12.3 MB) [=================================================================================================] 100%
Checking hash of micronaut-1.2.6.zip ... ok.
Extracting micronaut-1.2.6.zip ... done.
Linking ~\scoop\apps\micronaut\current => ~\scoop\apps\micronaut\1.2.6
Creating shim for 'mn'.
'micronaut' (1.2.6) was installed successfully!

> mn --version
| Micronaut Version: 1.2.6
| JVM Version: 1.8.0_212

Scoop についてはこちら。

Scoop on Windows - kntmr-blog

今回試したサンプルのプロジェクトはこちら。

kntmr/playground/micronaut-cli-examples - GitHub

プロジェクト作成

--featuresコンポーネントを指定すると依存関係に追加してくれる。

> mn create-cli-app com.example.app --features http-client

Picocli

Micronaut では Picocli を使って CLI アプリを作る。この Picocli がとても便利。

Micronaut Picocli Configuration - Micronaut

コマンドライン引数は @Option アノテーションを付与したフィールドにバインドされる。さらに、カンマ区切りの値を配列にしてくれたり、ファイルパスを File オブジェクトにしてくれたり。

@Option(names = {"-a"}, split = ",")
String[] array = {}; // 初期値
@Option(names = {"-f"})
File file;

@Mixinコマンドライン引数を1つのオブジェクトにまとめてくれるものかと思ってたけどそうではない。ドキュメントには共通のオプションとパラメータを再利用するためにあると書いてある。

@Mixin
private Options options;
static class Options {
    @Option(names = {"-v", "--verbose"}, description = "...")
    boolean verbose;
    @Option(names = {"-a"}, split = ",")
    String[] array = {};
    @Option(names = {"-f"})
    File file;
}

IDE 上からコマンドライン引数を渡す場合は Gradle Tasks で --args="-v" で実行する。ただ、2つ目以降の引数を正しく認識してくれない...。要調査

run --args="-v -a=foo,bar" #=> Unknown command-line option '-a'.

CLI アプリ終了時に任意のステータスコードを返したい場合は Callable<Integer> を実装して call() の中でステータスコードを返す。もう少しいい書き方があるかもしれない。

@Command(name = "app")
public class AppCommand implements Callable<Integer> {
    public static void main(String[] args) throws Exception {
        int exitStatus = PicocliRunner.execute(AppCommand.class, args);
        System.exit(exitStatus);
    }
    @Override
    public Integer call() throws Exception {
        return 0;
    }
}

その他

Maven を使う場合、mvnw compile exec:execmvnw package でコケることがある。以下の通り、pom.xml を修正する。

CLI generates a non working pom.xml for cli apps (1.2.0) #2031 - GitHub

あと、先日の JJUG CCC 2019 Fall で Picocli のひとが来てたらしい。(家庭の事情で CCC には参加できず...)

remkop.github.io

JSUG勉強会 2019 その10 SpringOne Platform 2019 報告会 に行ってきた #jsug

JSUG勉強会 2019 その10 SpringOne Platform 2019 報告会 に行ってきました。簡単にまとめます。

jsug.doorkeeper.jp

SpringOne Platform 2019概要 + Resilience4j + LTした話

  • SpringOne Platform
    • Spring, Microservices, CF, k9s などのセッション
  • Resilience4j
    • OSSのサーキットブレーカー
    • マイクロサービスで障害の伝播を防ぐ
    • メンテモードの Hystrix の代わりに Resilience4j
  • 処理は関数かアノテーションで記述する
  • Prometheus でモニタリングできる
  • 状態遷移
    • CLOSE ⇒ OPEN ⇔ HALF OPEN ⇒ CLOSE
  • Spring Cloud Circuit Breaker には Actuator のエンドポイントがない

LTの資料はこちら。

Spring Initializrをハックする

  • Spring Initializr
    • Web, IDE, CLI で Spring Boot のプロジェクトを生成するツール
  • 2013年誕生
  • UI, フォルダ構成や生成するファイルなどをカスタマイズできる
  • 昔に比べるとアーキテクチャは複雑になっている
  • @ProjectGenerationConfiguration

Let's イベント駆動 on Spring Cloud Stream

www.slideshare.net

  • Spring Cloud Stream
    • イベント駆動な Microservices アーキテクチャが簡単に構築できる
    • Kafka の接続が簡単
  • Source, Sink, Processor

Spring 18年の歴史

www.slideshare.net

  • 2001年に最初のコミット
    • GitHub はなく CVS を使っていたらしい
  • 当時のエンタープライズアプリケーション開発
    • 複雑な機能を実現するために1つのモノリスに詰め込んでいた
  • Design and Development 出版
  • 議論が巻き起こる尖ったアイデア
  • Jürgenize
  • 少数精鋭チームでスタート
    • 徐々にスケールアップ
  • Spring コミュニティは常にオープン

Spring HATEOAS

  • PayPal, AWS (API Gateway) などで使われている
  • 1.0 リリース
  • レスポンスにハイパーリンク情報を持たせる
    • 自分との関連を示すことができる (Affordance)
  • Hypermedia + REST
  • HATEOAS
    • アプリケーションの状態を持つもの
  • Separate Resource / Inline Resource
    • メタデータが多い場合は Separate Resource
    • ドキュメントのリンクを返す
  • Traverson
    • リンクをネストして1発で取る?(GraphQLみたいな?)

あとで読む。

blog.tagbangers.co.jp

Pack to the future

Google スライド - オンラインでプレゼンテーションを作成/編集できる無料サービスです

  • Dockerfile を書きたくない
  • Dockerfile は煩雑になりがち
  • Docker != Dockerfile
  • CF, Heroku
    • ソースコードを push してコンテナイメージを作る
    • Buildpack: プラットフォーム非依存
  • Cloud Native Buildpack
  • ソースコード ⇒ Buildpack ⇒ Dockerfile
  • Pack CLI 組み込み Builder

Google Nest Hub で自作アプリを動かしてみる

先日、Google Nest Hub を購入しました。Google Nest Hub のようなスマートディスプレイでは Actions on Google と組み合わせて自作したアプリを動かせるようです。

aogdevs.jp

ちょうど妻から Google Nest Hub に『ねずみタイマー』が欲しいというリクエストが。

ねずみタイマー

ねずみタイマー

  • LITALICO Inc.
  • 教育
  • 無料
apps.apple.com

一応、Google Nest Hub にもタイマーはありますが、子供向けにもう少しかわいい感じのタイマーが欲しいということで、上記のチュートリアルを参考にねずみタイマーを作ってみました。基本的にチュートリアルの流れに沿って作れます。

シミュレーターで動かすとこんな感じ。3分はカップラーメン用。

f:id:knt_mr:20191112122953p:plain

タイマーが進むにつれてねずみがチーズに迫っていきます。(以下はテストのためタイマーを15秒固定にしてあります)

f:id:knt_mr:20191112123125p:plain

時間になったら終了。子供が宿題するときに使うことを考えてお疲れ様でしたのメッセージ付き。ここでタイマーをリセットできる。

f:id:knt_mr:20191112123621p:plain

一応、実機でも動かせますが、起動するときに「テスト用アプリにつないで」と言う必要がある。要調査

アプリは Firebase にホストしています。ソースコードはこちら。

GitHub - kntmr/rat-timer


以下、備忘録。

> node -v
v8.16.0
> npm -v
6.4.1
> firebase --version
7.6.1

タイマー終了

Dialogflow にタイマー終了のインテントを定義する。

タイマーは普通に JavaScriptsetInterval で実装。時間になったら interactiveCanvas#sendTextQuery で Dialogflow のインテントにリクエストを投げる。画面の更新は interactiveCanvasイベントハンドラ (onUpdate) の中に実装。

タイマーリセット

アプリの再開や終了には Follow-up インテントを使う。タイマーをリセットするためにタイマー終了のインテントに再開用の Follow-up インテントを追加。

中断

タイマーを途中で終了するための Dialogflow インテントを定義。

Default Fallback Intent

Default Fallback Intent は Dialogflow にデフォルトで定義されているインテント。どのインテントにもマッチしない場合に Default Fallback Intent が呼び出される。

で、タイマーが作動中に想定外のリクエストを受け付けると Default Fallback Intent が呼び出されてしまう。パッといいアイデアが思い付かなったのでインテントのハンドラの中で握りつぶす...。

app.intent('Default Fallback Intent', conv => {
  conv.ask(new HtmlResponse({
    url: `https://${firebaseConfig.projectId}.firebaseapp.com/`
  }));
});

一応、これでタイマーを動かしたままにできるが、次のリクエストを受け付けなくなってしまう。要調査