表題の通り、 Functional Spring Hands On に行ってきた。
ハンズオンの資料はこれ
基本的に手を動かさないと理解が遅いので、わりとハンズオンは好きです(用意する方は大変)
内容は、 Spring(WebFlux) アプリケーションを @SpringBootApplication
なしで記述するというもの。さらに R2DBC もついてた。
R2DBC はまだ開発が進んでいる最中で、以前のエントリーは完全に無意味になってた…
続きを読む表題の通り、 Functional Spring Hands On に行ってきた。
ハンズオンの資料はこれ
基本的に手を動かさないと理解が遅いので、わりとハンズオンは好きです(用意する方は大変)
内容は、 Spring(WebFlux) アプリケーションを @SpringBootApplication
なしで記述するというもの。さらに R2DBC もついてた。
R2DBC はまだ開発が進んでいる最中で、以前のエントリーは完全に無意味になってた…
続きを読む当然といえば当然ですが、意外と気づかない。
例えば、特定の条件を満たさないとリクエストを処理しないような WebFilter
を記述する。
@Bean WebFilter webFilter() { return (exchange, chain) -> { Optional<String> requestDate = extractRequestDate(exchange); return Mono.justOrEmpty(requestDate) .flatMap(date -> Mono.defer(() -> chain.filter(exchange))) .switchIfEmpty(() -> forbidden(exchange)); }; }
このような感じで何らかのヘッダーの値がある場合は処理を行った結果を返すが、ない場合は 403 Forbidden を返すみたいな WebFilter
を書いたのだが、
これは常に 403 Forbidden を返し続ける。
WebFilterChain#filter(ServerWebExchange)
は Mono<Void>
を返すが、タイトルにあるように Mono<Void>
は(Void
のインスタンスが作れないため)常に empty になる
ここでは、 Mono
を連鎖させるのではなく、 Optional
の値によって取り回すほうがよい
@Bean WebFilter webFilter() { return (exchange, chain) -> { Optional<String> requestDate = extractRequestDate(exchange); return requestDate .map(date -> Mono.defer(() -> chain.filter(exchange))) .orElseGet(() -> forbidden(exchange)); }; }
resilience4j の RateLimiter を少しだけいじったので、そのメモ。 ここの実装はダメな実装になってるので、ちゃんとした使い方を調べてる人は他をあたった方が良い(強く推奨)。
続きを読む表題の通り、 project loom の JDK をビルドしてみた。
以下の環境でビルドした。癖で(バーストしない方がよいかなと思って)インスタンスタイプは m5a.large にしたけど、 t3a.micro とかでもいいかもしれない(よくわからん)。
boot JDK には jdk12 または jdk13 しか選べない。 Java 8 や Java 11 ではビルドできないので注意。
project loom の mercurial レポジトリーをクローンして、 configure
すれば必要なソフトウェアがわかるので、上記 OS 以外の人は configure
の際に表示される案内に従うこと。
また、 configure
の際に、 --prefix=$HOME/loom
みたいなパラメーターをつけると、 make install
でインストールされるディレクトリーが設定できる。デフォルトは /usr/local/bin
にインストールされる。
sudo apt-get update sudo apt-get install -y build-essential mercurial zip unzip autoconf \ curl libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev \ libxt-dev libcups2-dev libfontconfig1-dev libasound2-dev curl -s "https://get.sdkman.io" | bash source "/root/.sdkman/bin/sdkman-init.sh" mkdir /work cd /work hg clone http://hg.openjdk.java.net/loom/loom/ cd loom hg update -r fibers chmod +x configure ./configure --prefix=$HOME/loom make images make install
あと、なぜかは不明だが docker でビルドすると、もれなく docker ごと落ちてしまうっぽい。
私も何度か、Dockerでビルドをためしたのですが、落ちてしまうんですよね 😰
— Yuichi Sakuraba (@skrb) May 19, 2019
上記のスクリプトは $HOME/loom
にインストールされる。その中にに jvm
と bin
というディレクトリーができる。 jvm/openjdk-13-internal/bin/jshell
または bin/jshell
を実行すると、 Jshell が起動できる。
$ $HOME/loom/bin/jshell May 20, 2019 9:22:38 PM java.util.prefs.FileSystemPreferences$1 run INFO: Created user preferences directory. | Welcome to JShell -- Version 13-internal | For an introduction type: /help intro jshell>
お約束の Continuation
jshell> var cont = new Continuation(scope, () -> ...> IntStream.range(0,10). ...> <Runnable>mapToObj(i -> () -> System.out.println("phase: " + i)). ...> flatMap(runnable -> Stream.of(runnable, () -> Continuation.yield(scope))). ...> forEach(Runnable::run)) cont ==> java.lang.Continuation@6d21714c scope: test-scope jshell> while(!cont.isDone()) { ...> System.out.println("running"); ...> cont.run(); ...> } running phase: 0 running phase: 1 running phase: 2 running phase: 3 running phase: 4 running phase: 5 running phase: 6 running phase: 7 running phase: 8 running phase: 9 running