tokuhirom's blog

spring boot 2 にしたら `springBoot { executable = true }` が通らない

bootJar {
    launchScript()
}

にしましょう。

Created: 2017-11-21 02:55:57 +0000
Updated: 2017-11-21 02:55:57 +0000

spring boot 2 にしたら InvalidConfigurationPropertyNameException が発生するとき

spring boot 2 だと @ConfigurationProperties("fooBar") みたいなのを指定することができなくなる。 @ConfigurationProperties("foo-bar") なら通るので、変更必要。

Created: 2017-11-21 02:48:47 +0000
Updated: 2017-11-21 02:48:47 +0000

spring boot2 にしたら `bootRun { systemProperty 'spring.profiles.active', 'local' } }` が動かないよって場合

spring-boot 2 では以下の書き方は許容されなくなった。

bootRun {
  systemProperty 'spring.profiles.active', 'local'
}

以下のように変更する。

bootRun {
    execSpec {
        systemProperty 'com.example.foo', 'bar'
    }
}

https://twitter.com/ankinson/status/918498381768658944 ref. https://docs.spring.io/spring-boot/docs/2.0.0.M5/gradle-plugin/reference/html/#running-your-application

Created: 2017-11-21 02:22:37 +0000
Updated: 2017-11-21 02:22:37 +0000

/dev/urandom を fork して読み込んでもいいんかって話

tokuhirom /dev/urandom って開いたまま fork して読み込んだらまずいんですっけ?
親 process で /dev/urandom 開いたまま、fork してそれぞれの子プロセスで読んだら同じの取れる?
kazuho 同じの取れないですね
一般論なファイルについてもそう
つまり、open file descriptionは同一なので、readしたらその中にあるfile offsetは進むので (edited)
Created: 2017-11-13 03:32:48 +0000
Updated: 2017-11-13 03:32:48 +0000

spring-boot-actuator 使いたいけど spring-webmvc はいらないよってケース

management.port のほうは開きたいけど server.port のほうは開きたくないってときは

server.port: -1

とかやっときゃいいとのこと。

Created: 2017-11-08 05:39:24 +0000
Updated: 2017-11-08 05:39:24 +0000

spring-boot で tomcat の設定するときのやり方

server:
  use-forwarded-headers: true
  tomcat:
    accesslog:
      directory: /PATH/TO/logs/tomcat/
      pattern: common
      enabled: true
      rotate: true
      # It's required when using remote-ip-header.
      request-attributes-enabled: true
    remote-ip-header: x-forwarded-for
    protocol-header: x-forwarded-proto

なんかこんな感じ? request-attributes-enabled を設定するの忘れると RemoteIpValve で設定した値が AccessLogValve で拾われないので死ぬ。

Created: 2017-11-02 08:11:47 +0000
Updated: 2017-11-02 08:11:47 +0000

spring-boot で ConfigurationProperties に ZonedDateTime を書く場合のやり方

application.yml に日付データを入れて ZonedDateTime にマッピングしたい、みたいな場合。

http://blog.rakugakibox.net/entry/2015/12/04/springboot-with-java8time ↑こちらのブログに掲載されているように以下のようなクラスをおけばよい。

@Configuration
public class ConversionServiceConfiguration {
    @Bean
    public ConversionService conversionService() {
        FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        factory.setFormatterRegistrars(Collections.singleton(registrar));
        factory.afterPropertiesSet();
        return factory.getObject();
    }
}

便利~


追記: http://www.logicbig.com/tutorials/spring-framework/spring-boot/custom-configuration-properties-binding/ のようなやり方もあるとのこと。 https://twitter.com/wreulicke/status/925613009728290817

Created: 2017-11-01 04:19:13 +0000
Updated: 2017-11-01 04:19:13 +0000

apscheduler で add_job するときは misfire_grace_time の指定が必須

python で job の定期実行を実装するには apscheduler が便利だが、misfiregracetime の指定をしないと job が実行されないことがあるので注意が必要。 指定していないと以下のようなエラーに悩まされることになる。

Run time of job "send_menu (trigger: cron[day_of_week='mon-fri', hour='11'], next run at: 2016-05-31 11:00:00 CEST)" was missed by 0:00:01.51075

これは、予定された実行時間よりも scheduler の起動が遅れてしまったから実行しないようにしましたよ、というメッセージである。 デフォルトでは 1 秒以上実行が遅延した場合、ジョブは実行されない。 https://github.com/museumsvictoria/nodel/issues/13

しかし実際、1.5秒遅れても実行はしてほしいわけなので以下のように misfiregracetime を指定し、delay の許容時間を指定する方が良い。

scheduler.add_job(func, trigger='cron', hour='10,11,12', misfire_grace_time=60*60)
Created: 2017-10-28 08:39:17 +0000
Updated: 2017-10-28 08:39:17 +0000

spring.profiles.include は array で指定可能

https://github.com/spring-projects/spring-boot/issues/6995

spring.profiles.include は従来、string型でしか指定できなかったので以下のようなクソみたいな設定をするしかなかった。

---
spring.profiles: default
spring.profiles.active: local

---
spring.profiles.include: "\
  logging-devel,\
  mybatis-common,\
  freemarker-devel,\
  freemarker-common
"

---
spring.profiles: release
spring.profiles.include: "\
  mybatis-common,\
  freemarker-release,\
  freemarker-common
"

しかし、これは使いづらすぎるので以下のように書けるようにしてくれ、という要望を上げていた。


---
spring.profiles: default
spring.profiles.active: local

---
spring.profiles.include:
  - logging-devel
  - mybatis-common
  - freemarker-develo
  - freemarker-common

---
spring.profiles: release
spring.profiles.include:
  - mybatis-common
  - freemarker-release
  - freemarker-common

これが 2017 年の前半でリリースされてる spring-boot 1.5.0 では取り込まれているので、積極的に使うと良い。

Created: 2017-10-24 09:04:08 +0000
Updated: 2017-10-24 09:04:08 +0000

僕が情報収集に使っているブログ

僕が最近主に見ているブログについて以下に述べさせていただきます。 以下にあげたやつ以外に1000ぐらい購読してるけどそのへんのはあんま実用的というよりは趣味に近い感じです。

idea blog

https://blog.jetbrains.com/idea/

IDEA の最新機能とかがわかって便利。

Java Annotated Monthly ってのが毎月このブログにのるので、コレだけ読んでおけばJava界隈のトピックに乗り遅れることはない。

Reddit の /r/java

https://www.reddit.com/r/java/

なんだかんだ情報集めるのに便利なのは reddit。

spring blog

https://spring.io/blog

spring 関連のアプデ情報が集まるぞ!

github blog

https://github.com/blog

github のアプデ情報がわかるし、github で盛り上がってるレポの状態とかもわかる~

netflix tech blog

https://medium.com/netflix-techblog

netflix は尖った java 運用してるんで参考になる。

Debian security

https://www.debian.org/security/

なんとなく security 関連の update を追うのに便利

vue.js

https://medium.com/the-vue-point

vue.js 情報

AUTOMATON

http://jp.automaton.am/

洋ゲーの情報とか

Created: 2017-10-19 02:54:51 +0000
Updated: 2017-10-19 02:54:51 +0000

Spring cloud config client が Could not locate PropertySource: 400 Bad Request になるときの対処方法

spring cloud config を試しているときにハマったののメモ。

spring cloud config のチュートリアルは server を 8888 番ポートで listen させろと書いてある。 コレに従って進めていくと、Could not locate PropertySource: 400 Bad Request というエラーになって困った。

ngrep を実施して様子を見ていると以下のようなログが取れた。

##########
T 127.0.0.1:50448 -> 127.0.0.1:8888 [AP]
GET /a-bootiful-client/default HTTP/1.1.
Host: 127.0.0.1:8888.
User-Agent: curl/7.54.0.
Accept: */*.
.

##
T 127.0.0.1:8888 -> 127.0.0.1:50448 [AP]
HTTP/1.1 400 Bad Request.
Content-type: text/plain.
Connection: Keep-Alive.
Content-length: 58.
.
400 Bad Request
'json' or 'msgpack' parameter is required

curl http://localhost:8888 でリクエストした場合には以下のようになっていた。

#####
T ::1:50441 -> ::1:8888 [AP]
GET /a-bootiful-client/default HTTP/1.1.
Host: localhost:8888.
User-Agent: curl/7.54.0.
Accept: */*.
.

##
T ::1:8888 -> ::1:50441 [AP]
HTTP/1.1 200 .
X-Application-Context: application:8888.
Content-Type: application/json;charset=UTF-8.
Transfer-Encoding: chunked.
Date: Wed, 11 Oct 2017 06:07:25 GMT.
.
97.
{"name":"a-bootiful-client","profiles":["default"],"label":null,"version":"94427c7a809dbb3550d6db2902eccd4f93eec63d","state":null,"propertySources":[]}.

同じ http://localhost:8888/ を読んでいるが、返しているサーバーが違うようだ。

'json' or 'msgpack' parameter is required というメッセージで検索してみると、fluentd の in_http に含まれるエラーメッセージだということがわかる。

昔、手元のマシンで td-agent を起動してそのままになっていた結果、in_http が 8888 番ポートを見続けていたようだ。

curl http://127.0.0.1:8888 するとたしかに in_http に行ってることが確認できた。

同じ http://localhost:8888 へのリクエストでも、違う process にリクエストがいくことがあるので注意が必要だということがわかった。

対応は sudo pkill -f td-agent です!

Created: 2017-10-11 06:19:59 +0000
Updated: 2017-10-11 06:19:59 +0000

DBIx::Sunny と DBIx::Class の組み合わせでコメント自動挿入機能が微妙なことになっていたのを直した

https://github.com/kazeburo/DBIx-Sunny/issues/8

DBIx::Sunny は自動的にクエリ呼び出し元の位置をコメントに入れる機能がある。

しかし、DBIx::Class は Try::Tiny, Context::Preserve の内側でクエリ生成を行うため、Try::Tiny が呼び出し元として記録されてしまう。 つまり、以下のようなクエリが発行されてしまう。

SELECT /* /Users/tokuhirom/.plenv/versions/5.26.0-RC1/lib/perl5/site_perl/5.26.0/Try/Tiny.pm line 99 */ me.id, me.e FROM foo me

これは不便なので pr を出した。

https://github.com/kazeburo/DBIx-Sunny/pull/10

マージされ、リリースされ、システムに適用され、僕の周りにはキレイな slow query log が生まれることになった(根本的には slow query log はそもそも生まれないほうがいいという説もある)

Created: 2017-09-29 03:16:33 +0000
Updated: 2017-09-29 03:16:33 +0000

[python] IDEA で `if __name__=='__main__':` って簡単に入力したい

main って入力して補完すれば、java でいう psvm みたいなことができるとのこと。

Created: 2017-08-23 04:27:32 +0000
Updated: 2017-08-23 04:27:32 +0000

kotlin で -parameters 相当のことをしたい

http://qiita.com/kazuki43zoo/items/d000c87db98a68c6edba ここにかいてあるとおりにやれば良い。 デフォルトでやってくれ!頼む!! という気分になる

Created: 2017-07-05 20:08:49 +0000
Updated: 2017-07-05 20:08:49 +0000

[kotlin] ktor で config を読みたい

前提として、ktor のサンプルコードは、

    embeddedServer(Jetty, 8080, module = Application::module)
            .start()        

のように書かれているものが多いのですが、embeddedServer() を呼んだだけでは設定ファイルは読まれません。

fun main(args: Array<String>) {
    val applicationEnvironment = commandLineEnvironment(args)
    JettyApplicationHost(applicationEnvironment).start()
}

のように commandLineEnvironment を利用するのがよさそうです。

こうすることで、コマンドライン引数もよしなに扱ってくれるようになり、たとえば -port=8080 のように port 番号をコマンドライン引数で指定できるようになります。

で、application.conf を src/main/resources/application.conf に起きます。ktor サーバーの port 番号や、起動時のエントリポイントなどの指定もここでおこなえますし、アプリケーション独自の設定もここに書くことができます。

ktor {
  deployment {
    port = 8080
  }
  application {
    modules = [ com.example.HelloKt.module ]
  }
}



myapp {
  foobar {
    baz = 5963
  }
}

あとは以下のようにすれば設定を読み込み可能です。簡単ですね。

    val baz = environment.config.property("myapp.foobar.baz").getString()
    environment.log.info("baz: $baz")

完全な例はこちらです。 https://github.com/tokuhirom/ktor-samples/tree/master

Created: 2017-05-30 23:12:05 +0000
Updated: 2017-05-30 23:12:05 +0000

[kotlin] ktor で basic auth したい

ktor-auth コンポーネントで簡単に設定できます。

    compile "org.jetbrains.ktor:ktor-auth:$ktor_version"

で、あとは以下のように認証を設定する。設定した principal をコントローラ内でも取得可能。

        route("/") {
                authentication {
                    basicAuthentication("your-app-realm") { credentials ->
                        val username = credentials.name
                        val password = credentials.password
                        if (checkAuth(username, password)) {
                            UserIdPrincipal(username, password)
                        } else {
                            null
                        }
                    }
                }

            get("/hello") {
                val name = call.principal<UserIdPrincipal>()!!.name
                call.respondText("Hello $name")
            }
        }

簡単ですね。

Created: 2017-05-26 23:45:20 +0000
Updated: 2017-05-26 23:45:20 +0000

kotlin で instance_eval 的なことをしたい

kotlin では ruby 的な block つきメソッド呼び出しができるので、以下のようにすると instance_eval 的な、rubyish な DSL もめっちゃ簡単に実現できる〜〜

class Foo {
    fun bar(cb: Foo.() -> Unit) {
        apply(cb)
    }

    fun berk() {
        println("berk")
    }
}

fun main(args: Array<String>) {
    Foo().bar() {
        berk()
    }
}
Created: 2017-05-24 13:17:09 +0000
Updated: 2017-05-24 13:17:09 +0000

osx の notification を kotlin で呼びたい

osascript で呼ぶのがいいかな。apple script の escape 方法はよくわからないので JavaScript で書くことにして、 JSON で serialize して渡すのが良さそう。

fun sendNotification(message: String, title: String=message, subtitle: String=message, soundName: String = "Frog") {
    // https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayNotifications.html
    val params = jsonObject(
            "withTitle" to title,
            "subtitle" to subtitle,
            "soundName" to soundName
    )

    Runtime.getRuntime().exec(arrayOf(
            "osascript",
            "-l",
            "JavaScript",
            "-e",
            """var app = Application.currentApplication();
                app.includeStandardAdditions = true
                app.displayNotification(${message.toJson()}, $params)"""
    ))
}

JSON serialize は kotoson が便利。

compile 'com.github.salomonbrys.kotson:kotson:2.5.0'

で、こういうのちょっと頑張って書いてみたけど、LINE Notify 使うのが便利っぽいって話になった。。

Created: 2017-05-22 04:18:26 +0000
Updated: 2017-05-22 04:18:26 +0000

kotlin native で外部のライブラリとリンクする

kotlin native は外部のライブラリとリンクするのも簡単にできます。

以下、例として openssl にアクセスしてみます。

openssl.def として以下のように記載します。

headers = openssl/crypto.h openssl/opensslv.h

openssl.def を利用するコードとして以下のように記載(型の推移がわかりやすいように冗長にかいてます)。

import openssl.*
import kotlinx.cinterop.*

fun main(args: Array<String>) {
    val ver: CPointer<ByteVar>? = SSLeay_version(SSLEAY_VERSION)
    val verStr: String = ver!!.toKString()
    println(verStr)
}

あとは、以下のように Makefile でビルドしたら出来上がり。

all: sample.kexe

CCFLAGS=-I/usr/local/opt/openssl/include

clean:
        rm -rf openssl.kt.bc-build/ openssl.kt.bc/ openssl.kt.bc.klib sample.kexe "sample}.kt.bc"

openssl.kt.bc: openssl.def
        cinterop -copt "${CCFLAGS}" -def openssl.def -o openssl.kt.bc

sample.kexe: sample.kt openssl.kt.bc
        kotlinc-native -linkerArgs "-L/usr/local/opt/openssl/lib -lcrypto" -library openssl.kt.bc sample.kt -o sample

.PHONY: all clean

Makefile じゃなくて gradle でビルドするようにしたほうが良いが、めんどくさくて使い慣れた Makefile で今回はビルドしてみた。

実行結果は以下のようになる。

tokuhirom@mba ~/dev/kotlin-native-samples/openssl-version $ ./sample.kexe
OpenSSL 1.0.2k  26 Jan 2017

まとめ

kotlin native 意外と動く。しかしコンパイルは遅い。

Created: 2017-05-19 00:57:03 +0000
Updated: 2017-05-19 00:57:03 +0000

kotlin で native code を生成 kotlin native を楽しみたい

android で kotlin が話題なので、kotlin native を試してみました。 kotlin native を利用すると、kotlin のコードをネイティブコードにコンパイルできます。

https://github.com/JetBrains/kotlin-native

git clone git@github.com:JetBrains/kotlin-native.git

しておいて

./gradlew dependencies:update
./gradlew dist

す。Hello.kt を作成する。

fun main(args : Array<String>) {
    println("Hello, world")
}

以下のように、コンパイルする。

./dist/bin/kotlinc Hello.kt -o hello
[tokuhirom@dev2 kotlin-native]$ time ./program.kexe
Hello, world

real    0m0.002s
user    0m0.001s
sys     0m0.000s

CGI で実行できそうなぐらい速い。便利!!!

C library へのアクセス

C library には *.def ファイルを作ってアクセスすれば良い。 https://github.com/JetBrains/kotlin-native/blob/master/samples/tetris/sdl.def

header ファイルをスキャンしてるのかな?

ためしに stdio.def というファイルを作成する。

headers = stdio.h
excludeDependentModules.osx = true

実際にこのファイルからビルドしてみる。

[tokuhirom@dev2 kotlin-native]$ ./dist/bin/cinterop -def stdio.def -o stdio.kt.bc
JetFile: stdio.kt

このライブラリを利用した Hello2.kt は以下のようになる。

import stdio.puts

fun main(args : Array<String>) {
    puts("Hello, world")
}

さて、stdio.kt を利用したスクリプトをビルドしてみる。

[tokuhirom@dev2 kotlin-native]$ ./dist/bin/konanc Hello2.kt -library stdio.kt.bc -o Hello2.kexe
JetFile: Hello2.kt
[tokuhirom@dev2 kotlin-native]$ ./Hello2.kexe
Hello, world

動いた!!

結論

kotlin native わりと動く。

Created: 2017-05-18 07:20:25 +0000
Updated: 2017-05-18 07:20:25 +0000

Furl の timeout と SSL

Furl は、XS モジュールへの依存を排除するために IO::Socket::SSL のロードを実行時に行っております。 結果として SSL を利用したアクセスのうち、初回のアクセス時は若干の遅延が生じます。 use IO::Socket::SSL には 0.05sec〜0.1sec 程度かかります。

通常は問題がありませんが、timeout を0.1secなどに設定していると、モジュールのロードだけで timeout sec を消費してしまう可能性があります。

HTTPS で通信する場合には use IO::Socket::SSL しておくことを推奨します。

なお、この動作は仕様です。

Created: 2017-05-17 00:26:49 +0000
Updated: 2017-05-17 00:26:49 +0000
Next page