Spring Framework 5.2 からは WebClient の retrieve でちゃんと http status を取れる

Spring Framework 5.2 がリリースされた。

Support for Kotlin Coroutines.


Refinements to WebClient API to make the retrieve() method useful for most common cases, specifically adding the ability to retrieve status and headers and addition to the body. The exchange() method is only for genuinely advanced cases, and when using it, applications can now rely on ClientResponse#createException to simplify selective handling of exceptions.

これまで、Webclient を利用した場合、.retreive().bodyToMono(String.class) などとして response body のみを取得するメソッドしかなく、異常に使いづらかった。 HTTP Status Code が 2xx 以外の場合には例外が上がる設計になっているのはいいのだが、現実的にはどの HTTP Status Code かは例外ではなく通常の処理としてハンドリングしたいというケースも多いのである。

Spring Framework 5.2 以後では以下のように記述可能になった。

        WebClient client = WebClient.create();
        Mono<ResponseEntity<String>> responseEntityMono = client.get()

        ResponseEntity<String> responseEntity = responseEntityMono.block();
        assert responseEntity != null;"url={} status={} headers={} body={}",


Python 2 で GMT で出てるやつを適当に JST にする

from datetime import datetime, timedelta

def to_jst(src):
    return str(datetime.strptime(src, '%d %b %Y %H:%M:%S %Z') + timedelta(hours=9)) + " JST"

print(to_jst('26 Sep 2019 03:56:25 GMT'))


sparksql で emoji/pictogram を含む行を検出する

select text from table where dt='20190911' and text rlike '[\\uD800-\\uDFFF]'


filebeat で jvm unified log を収集する話

jetbrains toolbox for linux を chromebook で動かす

fuse が動かないので ./jetbrains-toolbox-1.15.5796/jetbrains-toolbox --appimage-extract で解凍。 APPDIR=$PWD/squashfs-root ./squashfs-root/AppRun で実行可能。

と、思ったが、sudo apt fuse すれば普通に実行できた。

Unable to publish SessionDestroyedEvent for session foobar

scala で guava のバージョンを確認する

とりあえずこんな感じで。try-with-resources でやりたかったが、あんま短くかけなそうだった。

import java.util.Properties

val resourceName = "META-INF/maven/";
val properties = new Properties();
val inputStream = Resources.getResource(resourceName).openStream();

witcher 3 途中でやめた


pageres から capture-website にしようと思ったが puppeteer にした

長年、pageres を利用して web page から画像を生成していた。 pageres の後継として capture-website があることを知った。

The biggest difference is that Pageres supports capturing multiple screenshots in a single call and it automatically generates the filenames and writes the files. Also, when projects are popular and mature, like Pageres, it becomes harder to make drastic changes. There are many things I would change in Pageres today, but I don't want to risk making lots of breaking changes for such a large userbase before I know whether it will work out or not. So this package is a rethink of how I would have made Pageres had I started it today. I plan to bring some things back to Pageres over time.

しかし、いろいろ試した結果、puppeteer を直接使っても大した差がないことがわかったので、使うのをやめて直接使うことにした。

Excel で特定の行または列を固定する方法


zipkin の RateLimitingSampler が便利(特に低トラフィックの場合)

zipkin で tracing log を取得する場合、一定の割合でログをサンプリングしてストレージに保存していた(たとえば 0.1% だけストアするなど)


しかし、zipkin brave の 5.6.0 以後では RateLimitingSampler という実装が導入されている。これにより、1秒間にどれだけ送るかという上限設定ができるようになり、トラフィック量に応じて sampling rate を変更する手間が省けるようになっている。

Spring Cloud Sleuth の場合

Spring cloud sleuth でもこの機能にすでに対応されていて、spring.sleuth.sampler.rate というプロパティを設定すると良い。

line-bot-sdk-nodejs を typescript で使う

	npm install --save express
	npm install --save typescript
        npm install --save @line/bot-sdk
	npm install --save @types/express
	npm install --save @types/node

	npm install --save-dev ts-node
	npm install --save-dev ts-node-dev

	npx tsc --init

	mkdir src
	touch src/index.ts

	npx ts-node src/index.ts


npx ts-node-dev --respawn src/index.ts


コードはこんな感じ(typescript 慣れてないから怪しい)。

import line = require('@line/bot-sdk');
import express = require('express');

const config: line.Config =  {
  channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN!,
  channelSecret: process.env.LINE_CHANNEL_SECRET!,

// create LINE SDK client
const client = new line.Client(<line.ClientConfig>config);

// create Express app
// about Express itself:
const app = express();

// register a webhook handler with middleware
// about the middleware, please refer to doc'/callback', line.middleware(<line.MiddlewareConfig>config), (req, res) => {
    .then((result) => res.json(result))
    .catch((err) => {

// event handler
function handleEvent(event: line.WebhookEvent) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    // ignore non-text-message event
    return Promise.resolve(null);

  console.log(`Received message: ${event.message.text}`);

  // create a echoing text message
  const echo: line.TextMessage = { type: 'text', text: event.message.text };

  // use reply API
  return client.replyMessage(event.replyToken, echo);

// listen on port
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`listening on ${port}`);

[js] List::Util::all みたいなのを js で

 List::Util::all みたいなものをJSで書くときってどう書くのがいいんだろ
lodash とかにありそうだけど
syohex [8:55 PM]
 Array.prototype.everyとは違うのでしたっけ ?
karupanerura [8:56 PM]

ivy が最近は良いらしい

最近はhelmやめてivyつかってますよ! とのこと。僕も変えてみた。

YAPC::Tokyo 2019 で keynote してきた

keynote の準備に忙しかったりしてあまりトーク聞けなかったけど楽しかったです。

bash で **/* とかしたい

shopt -s globstar で OK

YAPC::Tokyo 2019 で keynote します


spring の 4.3.15, 5.0.5 以後で mockmvc の json path のマッチングで matcher 使わなくてもよくなってる

mockmvc で jsonpath のマッチングを利用する場合、以下のようにする必要があった。

.andExpect(jsonPath("$.id", is(5963)))

これはこれでいいのだが、他の API と一貫性がなく、補完も効きづらく、hamcrest API ではなく assertj をメインで使ってる身としては辛かった。

また long の扱いが渋くて、辛かった。。

SPR-16587 MockMvcResultMatchers.jsonPath(String).value() should have a matching method to declare the expected type で、問題が解決されて以下のような書き方ができるようになっている。


MockMvc でテストを書いているときに部分一致をしたいケースは殆どないと思われるので、このスタイルで書くのが良いと私は思います。

Spring 4.3.15, 5.0.5 以後で使えるので、このスタイルで書いたほうが良い。


【追記】 null であることを保証したいときは hamcrest matcher でやらないと駄目。

spring boot で ExceptionLoggingFilter が ERROR level でログ出まくってうざいってとき

spring-cloud-sleuth を依存にいれたら ERROR レベルでのログの出方がおかしくなった。

このクラスが例外をキャッチしてエラーログに書いて rethrow するという謎の挙動をしている。。


この spring.sleuth.web.exception-throwing-filter-enabled プロパティを false に設定することですべてが解決する。

It's fixed by this PR.

spring boot で静的リソースの書き換えを即時反映させたいよってとき

bootRun {
    sourceResources sourceSets.main

この設定をすると、静的リソースが source directory から読まれるようになり開発が快適になる、とのこと。

webflux で x-forwarded-for とかをケアする


import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.reactive.config.WebFluxConfigurer
import org.springframework.web.server.adapter.ForwardedHeaderTransformer

class WebConfiguration : WebFluxConfigurer {
    fun forwardedHeaderTransformer(): ForwardedHeaderTransformer {
        return ForwardedHeaderTransformer()

あるプロジェクトを Gradle kotlin DSL に移行した

お仕事プロジェクトの一つを gradle kotlin dsl に移行させてみた。 理由としては以下。




Java9 だとspotbugs で OBL_UNSATISFIED_OBLIGATION 警告がでるとき

try-with-resources してるのに leak しているという警告が出るので謎ダナーと思ったら spotbugs のバグみたい。

spring boot 2.1+(spring framework 5.1+) applies `samesite=Lax` attribute to session cookie by default

After boot 2.1, DefaultCookieSerializer applies samesite=lax attribute by default. As a result, the security risk was decreased.

But in the OAuth2 authentication process, OAuth2 provider can pass the data by POST method. It can't work with samesite=lax attribute(A browser won't send cookie).

You can configure the default behavior by following bean definition.

    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        return cookieSerializer;

lombok 1.16.22+ と gradle 4.9+ の食い合わせが悪いイシュー

spring boot 2 で micrometer 使ってるときに、latency の percentile 値を prometheus に送る方法

        - 0.5
        - 0.75
        - 0.95
        - 0.99


gRPC-WEB がもたらす我々の生活への変化

gRPC-WEB が GA となった。これが我々の生活にどのような変化をもたらすのかについて考える。

従来の gRPC の課題

gRPC は google が公開している RPC 方式であり、java, golang などの言語で利用可能になっている。 gRPC は protocol buffers over HTTP/2 を基本としているため、通信が multiplexing されるし、schema 定義がきっちりされるのでクライアント側とのコミュニケーションがしやすい。

一方、protocol buffers はbinary であるためにbinaryの取扱が苦手な Browser JavaScript からのアクセスが難しいという問題があった。


grpc-gateway という実装があって、これを利用すれば Browser JavaScript からのアクセスも可能ではある。しかし、専用の gateway server を golang で生成して運用することになって煩雑である。

また、client library を protobuf 定義ファイルから生成することができないので、そういった意味では、gRPC の魅力を 100% 引き出すことができていないといえるかもしれない。 もちろん、Swagger の定義を生成することができるので、そこから codegen することはできる。

外部に向けて JSON API を提供する必要がある場合には grpc-gateway は引き続き有力な選択肢となるが、SPA web application のためのエンドポイントの場合には、grpc-web の方が今後は良い選択となると私は考える

また、grpc-gateway はコミュニティ実装であるから、公式ではない。


gRPC-WEB のプロトコルは で解説されている。

多くのブラウザで動作するように、base64で encode する方法などが protocol で設定されている。

gRPC-WEB の実装

現在のところ nginx module と envoy というプロキシサーバーによる実装、grpcwebproxy という go 実装が提供されている。

nginx module

nginx module も提供されている。


grpcweb は go のライブラリ実装。既存の golang で書かれた gRPC サーバー実装の中に組み込んで、 gRPC-web で export する機能を追加することができる。 便利。


golang で実装されている grpc-web の実装。go で single binary で導入できるので、一番導入が簡単そう。


Envoy は C++ で書かれた proxy server です。拡張が容易になっていて、C++ で簡単に拡張できるようになっています。

Envoy の grpc-web の実装は envoy の repository の中にあります。C++ ですがコメントがたくさんあるのでわかりやすいですね。

Envoy の中に実装されているのは、Proxy layer でカバーできていればすべてのサーバー実装で使えるので、まずは proxy layer で実装したということのようだ。

Envoy は C++ で書かれているのでビルドがそこそこ面倒なので docker での運用が現実的と思われる。プリビルドバイナリも提供されているが、ubuntu と alpine のみなので centos 勢としては悲しい。

今後の grpc-web の roadmap

このドキュメントで今後の ROADMAP が述べられている。 いくつか気になったところを紹介する。


Binary の protobuf を base64 などにエンコーディングする方式は CPU overhead/memory overhead が大きい。よって、gmail などで採用されている、text protocol だが高速に処理できるフォーマットを使うようにすれば良いのではないか、とのこと。

Local Proxies

各言語用のサーバーライブラリの側に、gRPC-WEB サポートを追加しようというプラン。 今は go だけあるっぽい。Java support が待ち遠しい。

TypeScript support

これはほしい。Protobuf から生成されたクライアントに型情報が付けば、IDE 上での作業が快適になることは間違いない。

Web UI Support

gRPC-WEB を実際に試せる web console を作りたい、とのこと。


whatwg streams api が各ブラウザに実装されて普及すれば、native の gRPC protocol を利用可能になるのではなるとのこと。

sbt の %% と % の違い

groupID %% artifactID % revisiongroupID % artifactID % revision の違い。

If you use groupID %% artifactID % revision instead of groupID % artifactID % revision (the difference is the double %% after the groupID), SBT will add your project’s Scala version to the artifact name.

spring 5.1 で webflux に samesite 対応が入る spring 5.1 から cookie の SameSite のさぽーとが入るっぽい's-New-in-Spring-Framework-5.x#whats-new-in-version-50

つまり、boot 2.1 以後は spring 5.1 なので、webflux 使ってれば samesite 属性使える。

Spring IO platform が deprecated だった。。 今後は spring-boot-dependencies を使おう!

久々に みたら、"End of Life" の文字が。。

The Platform will reach the end of its supported life on 9 April 2019. Maintenence releases of both the Brussels and Cairo lines will continue to be published up until that time.


Users of the Platform are encourage to start using Spring Boot's dependency management directory, either by using spring-boot-starter-parent as their Maven project's parent, or by importing the spring-boot-dependencies bom.

というわけで、spring-boot-dependencies bom を利用したら良いっぽい。

によれば、今後は以下のようにすれば良い。Boot のバージョンを上げれば依存ライブラリも互換性のあるいい感じのバージョンに上がっていって便利! って感じっぽい。

apply plugin: 'io.spring.dependency-management'

dependencyManagement {
	imports {
		mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES