@Async と @RequestScope を同時につかうとどうなるか

@RequestScope、これは @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) と同じ意味。この Bean はスレッドローカルにひもづけられているHttpServletRequestに保持されている。

@Async は別スレッドで処理を実行するため、間接的にでも @RequestScope な Bean を使っていると以下のような実行時エラーとなる。処理中のスレッドには該当する Bean が保持されていないという旨。

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

ScopedProxyMode.TARGET_CLASS なのでスタックトレースがややこしい。cglib を使ってクラスのプロキシを作って、プロキシクラス内で Bean をどこかからとってきて呼ぶという動きになっている。おかげでスコープに関わらずコード上は Singleton のように扱えているが、黒魔術はひっかかったとき大変です。

解決方法

https://stackoverflow.com/questions/23732089/how-to-enable-request-scope-in-async-task-executor に良い解決方法が書いてあって、これを使えばよい。やってることは単純で @Async で別スレッドで実行しようとする際に、呼び出し元スレッドのBeanを渡してあげるという感じ。

ただし、どうもコピペでは動かなくて、以下のようにかえてうまくいった。結局 Executor インターフェイスのメソッドだけオーバーライドしたら良い。

@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
    // Default task executor for @Async annotation
    @Override
    @Bean
    public Executor getAsyncExecutor() {
        val executor = new ContextAwarePoolExecutor();
        executor.setCorePoolSize(25);
        executor.setQueueCapacity(25);
        executor.setMaxPoolSize(25);
        executor.setThreadNamePrefix("AsyncTask-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }

    @SuppressWarnings("serial")
    public static class ContextAwarePoolExecutor extends ThreadPoolTaskExecutor {
        /**
         * Override Executor interface
         */
        @Override
        public void execute(Runnable task) {
            super.execute(new ContextAwareRunnable(task, RequestContextHolder.currentRequestAttributes()));
        }
    }

    public static class ContextAwareRunnable implements Runnable {
        private final Runnable task;
        private final RequestAttributes context;

        public ContextAwareRunnable(Runnable task, RequestAttributes context) {
            this.task = task;
            this.context = context;
        }

        @Override
        public void run() {
            if (context != null) {
                RequestContextHolder.setRequestAttributes(context);
            }

            try {
                task.run();
            } finally {
                RequestContextHolder.resetRequestAttributes();
            }
        }
    }
}
  1. トップ
  2. tech
  3. Spring MVC で @Async と @RequestScope を共存させるには?

await x は await Promise.resolve(x) という意味なので、どのような値がきても問題ない。同期関数を await しても問題は起こらない。呼び出し先の関数が Promise をかえすかどうかを悩む必要はない。

Promise.all も同様で、(別に意味はないけど) 即値を渡しても問題ない。

  1. トップ
  2. tech
  3. async 関数内では全ての関数呼び出しに await を書けば良い

3M 絆創膏 ネクスケア キズ キレイに 治す ハイドロ コロイド メディカルパッド M サイズ 10枚 HCD10M - スリーエム(3M)

スリーエム(3M)

5.0 / 5.0

【Amazon.co.jp限定】BAND-AID(バンドエイド) キズパワーパッド ふつうサイズ 10枚+ケース付き 防水 指先 指 絆創膏 早く きれいに 治す 痛みを和らげる ハイドロコロイド - BAND-AID(バンドエイド)

BAND-AID(バンドエイド)

5.0 / 5.0

ハイドロコロイド系の絆創膏だとキズパワーパッドがメジャーな気がするが、3M のネクスケアも試してみたら使い勝手が全然違って感動したので書く。(特に理由なく安いっぽいから買って常備しておいたのだけど、なかなか使う機会がなかった)

ネクスケアのカバーフィルムがすごい

キズパワーパッドは全面がハイドロコロイド素材になっていて、直接それを貼りつけて固定する感じになっている。密着しにくい部分にはったりするとどうしても剥れてしまい、その部分に水がかかってしまうと剥れた部分が白く変化して使えなくなってしまう。

ネクスケアの場合、ハイドロコロイド素材の上に防水フィルムがさらに貼り付けてあり、周囲10mmぐらいを、かなり薄い透明なフィルムでカバーするようになっている。上の写真だと指の間にフィルムがはみ出してるのでわかりやすい。

とにかく、このカバーフィルムがすごい。めちゃくちゃ薄くて透明で皮膚に密着するので、貼ってあるのか貼ってないのか心配になるぐらい見えない。伸縮性もあって密着しているので水がかかっても全く問題なくなる。不思議。

これだけ薄くて密着するので剥すのに苦労するかなと思ったけど、普通に端を爪で擦ったら特に強くひっぱられることもなく剥すことができた。

貼り付け方法も工夫してあって使いやすい。極薄のフィルムを貼り付けるのは普通は難しいのだけど、4ステップで貼ることで何の苦労もなく貼れるようになっている。

欠点としてはフィルム分、患部に対して貼り付け範囲は広くなってしまうことぐらいか。今回自分は手のひらだったので問題ないが、指先とかだともしかすると使いにくいかも。

しかもネクスケアのほうが安いぽい。完全にオススメ。


しかし酒飲んで転んで怪我をするという実績を解除してしまった…… 人生の先輩がたにおかれましてはそれで骨折している人も多くいるので、転んだ瞬間それがよぎった。結果的には擦り傷ぐらいですんだけど、気をつけたい。

「NEMA 17 Vibration Damper」 あたりで ebay を検索して出てきたやつを買ってみた。5個で520円ほど。中古品みたいな汚れたのが送られてくる。5個のうち1つはプレートが歪んでいて使えない感じ。よく見るとわかるが5個のうち2つは穴の大きさが違っていて、すこし大きい。というかそもそも商品説明の穴の形と違う。だいぶ謎仕様。まぁ機能が果たせれば文句をいえる値段ではないが……

取り付け

X軸とY軸だけ取り替える。Z軸も動いてるときはそれなりにうるさいのだけど、ほぼ全部分解しないといけないので大変だし、3Dプリンタの場合Z軸はほとんど動かないのでやらないことにした。E軸はそもそもうるさいと思ったことがない。

Originai Prusa i3 MK2.5 で、X軸は簡単に取り替えられる。シャフトの長さがギリギリなのがちょっとこわいか。

Y軸はちょっとややこしくて、Prusa i3 MK2: 3 Point Y Motor Holder を使って元々のパーツを3点支持型に変更するか、Prusa i3 MK2S Y axis stepper damper attachment plateを使ってあげるなどしないといけない。前者はフレームの組みなおしが必要になってしまうので、後者でなんとかした。

効果はどうか?

かなり効果がある。High Power モードでも Silent モードにしたぐらいの静かさになる。

もしかすると造形精度に影響があるかもしれないが、いまのところは大丈夫そう。耐久性も疑問があるけど、ヘタってきたら単に戻せばいいだけなので、気軽に導入できる。

  1. トップ
  2. tech
  3. 3Dプリンタの静音化のためにステッピングモーターにダンパーを追加

#240 なら1インチ(25.4mm)あたり240の目のあるメッシュを通してふるいをかけた砂を使っているという意味らしい。#240 なら 25.4 / 240 ≈ 0.106mm 未満の粒度。

なお #240は「メッシュにひゃくよんじゅう」と読む。

3Dプリンタの仕上げに平滑性を求める場合

#100〜#150 から初めるのが良いっぽい。

ref.

  1. トップ
  2. tech
  3. サンドペーパーの番手


スマフォ用に充電ドックをつくったら思いのほか便利だった。片手でさくっと置ける。上の画像はバージョン1で、これはこれで使っているけど、もうちょっと構造を改良したものを ZenFone3 用にもつくった。

意外と市販品がないので 3D プリンタの出番といえそう。つけるケースとかによってサイズが変わってきてしまうので接触式ドックは大量生産しにくいのだろう。

USB Type-C はコネクタの位置あわせがそれほど厳密でなくとも挿しこめるので、割と雑につくってもうまく機能させることができる。

そういえば Nintendo Switch で Type-C を直接ドックコネクタとして採用していてびっくりしたけど、あれはさすがに本体側とドック側で位置あわせする凹凸があって、位置があわない限りドック側コネクタが露出しないような仕組みになっている。横から適当にさしこんでも位置があうとうまくドッキングする。

  1. トップ
  2. tech
  3. 3Dプリンタでスマフォドック。もっと早くつくっていればよかった

この番号の意味は「3.6m×5.4mサイズでの重さ(g)」を表現している。用紙の厚さの目安を重さで表現するのと似ている。

メジャーなのは表題の通り #3000 や #2000 あたりのようだ。軽さと耐久性のトレードオフがあり、このあたりがバランス良い。#3000 はテントのグランドシートにも代用される。

とりあえず買うなら #2000 でいいと思う。#2000 ぐらいならすぐに破けそうな感じはしない一方、新品でもゴワゴワ固くて扱いにくいということもない。

100均とかで売ってる激安シートはめちゃくちゃ薄いが、あれがだいたい#1000ぐらいだと思われる。#1000 は敷物としてまるで使えないレベルだと思ったほうがよい。

マキタ(Makita) 充電式レシプロソー 10.8V 1.5Ah 本体のみ JR104DZ - マキタ(Makita)

マキタ(Makita)

5.0 / 5.0

ストローク13mm。切断能力50mm。掃除機やドリルとバッテリー兼用にしたいので10.8Vにした。

文字通りのこぎりの代替の目的もあるが、基本的には粗大ゴミを好きなときに自由に解体して一般ゴミで出したいという目的のほうが大きい。

替刃

レシプロソーはメジャーメーカーで統一規格のようで、基本的にどれも挿さる。

またこのレシプロソーはジグソー B タイプのブレードも使える。本体を立ててシューを押しあてればジグソー風につかえる。

Bタイプのブレードって何だ?と思うが、最近のモデルはメーカー共通でこのBタイプ(Boch互換という意味)になっているらしい。

ブレード取り付けは六角レンチで行う。結構キツく締めないと動いてるときに抜けやすいので、必ずレンチはトルクがかかりやすいように使う。


正直、どれを買うかよくわからないので一通り買ってみた。

 -

5.0 / 5.0

USマキタ純正。

  • 円切り用 (取り付け部が違うだけで機能的にはジグソーブレードと一緒)
  • 6TPI 複合材用
  • 10TPI 複合材・メタル用
  • 18TPI メタル用
  • 厚さが違うプログレッシブ刃2枚
    • よくわからない。解体用ってこと?

髙儀(Takagi) 高速度鋼 コンビネーション ジグソーブレードEARTH MAN Bタイプ 5本組 - 髙儀(Takagi)

髙儀(Takagi)

5.0 / 5.0

ジグソーブレード。小物を切りたいときに使うかな?と思って買ってみた。使わないかも。

切り方

ある程度速度を出さないと刃がひっかかって余計にあぶない。できるだけシューとワークが密着するほうが楽に切れやすい。

やってみた感じだと、金属切断には解体用ではなく金属用を使うのが正解っぽい気がする。まだ木製品の解体はしてないがMDFは普通になんでも切れる。

薄板にはどうしても細かい刃が必要。

しばらくパワー出して使うと結構熱くなって心配。

備考

軍手 防刃 防刃手袋 作業用 手袋 作業グローブ 切れない手袋 耐切創手袋 - Ministore Direct

Ministore Direct

5.0 / 5.0

防刃手袋も買いました。電動工具は制御外の力が出易く、どうしても事故りやすいので念のため。回転工具のように巻きこまれる危険がないなら手袋はつけたほうが安全みたい。

3M バーチュア V4 保護めがね 11672 - スリーエム(3M)

スリーエム(3M)

5.0 / 5.0

保護メガネもかけましょう。

ref

  1. トップ
  2. tech
  3. マキタ レシプロソー 10.8V JR104D 買ってみた

Aliexpress を利用しているとサインイン時に自動的にログインする仕組みが導入されていることに気付く。知らない人のために説明すると、以下のような挙動をする。

  • ログインページにいくと「Google Smart Lock で保存したアカウントを使ってログイン」というブラウザのUIが表示される
    • そのまま「ログイン」ボタンを押すと自動的にサイトにログインしてページ遷移する
  • セッション切れのときに My Orders などにアクセスしようとすると、一度ログインページに遷移した後、自動的にログインして My Orders ページに遷移しなおす (ログイン済みになって見れるようになる)

あまり他のサイトだと見ない挙動なので最初は驚いたけど、便利。

仕組み

これは Credential Management API という仕組みを使うと実現できる。現状では Chrome しか対応していないようだ。Google が公開しているエントリにこれの実現方法も書いてある。https://developers.google.com/web/updates/2017/06/credential-management-updates 割と詳しい説明が書いてあるのでこれを読めばよろしい。が、自分でも試してみたのでメモしておく。

雑に自分のサイトに自動ログインを導入したい、と思った場合、ログインページに以下のようなコードを仕込むだけで実現できてしまう。

(async function () {
	const cred = await navigator.credentials.get({
		password: true
	});
	// console.log(cred);

	document.getElementById('username').value = cred.id;
	document.getElementById('password').value = cred.password;
	document.getElementById('login').submit();
})();

もちろんこれだけだと欠点がある。すなわち、ログインページを表示した際に強制的にログインしてしまう。もしあなたのサイトが認証状態がないときにログインページにリダイレクトして戻ってくるような仕様だとすると「ログアウト」が不可能になってしまいます。この実装だけではダメですね。

これを防ぐにはログアウト時に preventSilentAccess() を使ったり、 get() に指定する mediation の値を変更したりする必要があります。詳しくは前述の Google のエントリを読むと良いでしょう。

コードを見るとわかるが全く複雑なことはないですね。id と password が JavaScript から取得できるため、それを既設のフォームに埋めているだけ。console.log() のコメントアウトをはずすと、自分のパスワードが console に表示されるのでビビることができます。

JSからパスワードとれんの??? こわくない??

こわいわ〜と直感的に思いますね。その感覚は正しいと思うんです。でもね、「ブラウザに保存しているパスワード」は実情、自動フィルインされるわけですが、このフィルインされたパスワードって Credential Management API に関係なく、そもそも input.value で JS から読めるんですよね。

そう考えると、このAPIは単にフィルイン+ログインボタンクリックという操作を、確実かついい感じに(ログアウトも考慮して)行える方法で代行しているだけという仕組みになりますね。複数アカウントを考慮しつつ1クリック減らせるという感じです。

  1. トップ
  2. tech
  3. Chrome で保存したパスワードをウェブサイト側から利用する

リングスター スーパーピッチ クリア L300×W206×H39mm 仕切板20枚付 5個セット SP-3000D-5S - リングスター(Ring Star)

リングスター(Ring Star)

4.0 / 5.0

リングスター スーパーピッチ SP-3000D に納めるようにクシ型の仕切りをつくってた。

  1. トップ
  2. tech
  3. ジャンプワイヤー整理

リングスター スーパーピッチ クリア L300×W206×H39mm 仕切板20枚付 5個セット SP-3000D-5S - リングスター(Ring Star)

リングスター(Ring Star)

4.0 / 5.0

リングスター スーパーピッチ SP-3000D というケースをねじの整理に使っている。おおむね良いんだけど、ワッシャーの類だけはどうしても仕切りを超えてややこしいことになることがある。

考えた結果、ワッシャーに関しては蓋つきのインナーケースを作ってハメこむことにしてみた。

https://www.thingiverse.com/thing:3171559

  1. トップ
  2. tech
  3. ワッシャー用のインナーケース

GitHub Pull Request Builder Plugin の PR ブランチビルドの挙動は以下のような状態で実行する

  • マージ可能な場合はベースブランチにマージされた状態 (origin/pr/{pr}/merge)
  • コンフリクトしている場合はPRブランチのHEAD状態 (commit hash)

表題の「手元ではテストが通るのに Jenkins では通らない場合」は表面上はコンフリクトはしないにも関わらず、ベース側に入った変更によってPRブランチ側が壊れることによって起こる。つまりコード上の意味がコンフリクトしているにも関わらず、表面的にマージされてテストされるため不可解な結果を生むことがある。

解決方法

  • ベースブランチをPRブランチにマージする(または rebase する)
    • 重要:GitHub 上でコンフリクト表示が出ているか否かは関係ない

PRのテスト結果の表示

GitHub 上に表示されるテスト結果のインジケータには上記のように2つのケースがあり、Jenkins 側のログを見ないと厳密に判断することができない。

GitHub 上での Conflict 表示でもある程度判断できるが、CI を通ったあとにベースブランチに変更が入って Conflict した場合は PR ブランチで再テストが走るまで過去の結果が表示されるため正確ではない。

備考

  • origin/pr/{pr}/merge は普通に clone すると含まれないため、Jenkins が存在しない謎のコミットをビルドしているようにみえる
  1. トップ
  2. tech
  3. GitHub Pull Request Builder Plugin 使っている環境で手元ではテストが通るのに Jenkins では通らない場合