mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle 5.5 で JUnit Jupiter が gradle init 時にテストフレームワークとして選べるようになっていた

表題の通りです

f:id:mike_neck:20190619163018p:plain

次のコマンドをターミナルで叩きます。

gradle init \
  --type java-library \
  --test-framework junit-jupiter \
  --dsl groovy \
  --package com.example \
  --project-name example-library

次のような build.gradle ファイルが生成されます

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java Library project to get you started.
 * For more details take a look at the Java Libraries chapter in the Gradle
 * User Manual available at https://docs.gradle.org/5.5/userguide/java_library_plugin.html
 */

plugins {
    // Apply the java-library plugin to add support for Java Library
    id 'java-library'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:27.1-jre'

    // Use JUnit Jupiter API for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'

    // Use JUnit Jupiter Engine for testing.
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
}

test {
    // Use junit platform for unit tests
    useJUnitPlatform()
}

Groovy が書けない人のための Gradle 入門

若干ネタ気味ですが、 Groovy を覚えるのが面倒だけど、 Kotlin を覚えるのも面倒という方のためにお勧めしたいのが、 Java で書くという方法です。

f:id:mike_neck:20190619163018p:plain

というわけで、次のような build.gradle を書きます。

Project project = getProject();

project.getPluginManager().apply("java-library");

project.setGroup("org.example");
project.setVersion("1");

project.setSourceCompatibility(JavaVersion.VERSION_11);
project.setTargetCompatibility(JavaVersion.VERSION_11);

project.getRepositories().mavenCentral();

project.getDependencies().add("implementation", "org.slf4j:slf4j-api:1.7.25");
project.getDependencies().add("testImplementation", "org.junit.jupiter:junit-jupiter:5.4.2");

project.getTasks().<Test>named("test", Test.class, new Action<Test>() { @Override public void execute(Test test) { test.useJUnitPlatform(); }  });

では、ビルドを走らせてみましょう

f:id:mike_neck:20190629120614p:plain

見事ビルドできたようです。


Groovy は Java なので、 Groovy がわからないと焦る前に、 Java で書いてしまえばよいです

ただ、一つだけ注意点があって、Gradle が使っている Groovy のバージョンが 2.5.x のため、 Java8 の lambda のような記述を解釈できないので、 Actionインスタンスに対しては匿名クラスで対応せざるを得ないことです。

Functional Spring Hands On に行ってきた

表題の通り、 Functional Spring Hands On に行ってきた。

pivotal-japan.connpass.com

ハンズオンの資料はこれ

github.com

基本的に手を動かさないと理解が遅いので、わりとハンズオンは好きです(用意する方は大変)

内容は、 Spring(WebFlux) アプリケーションを @SpringBootApplication なしで記述するというもの。さらに R2DBC もついてた。

R2DBC はまだ開発が進んでいる最中で、以前のエントリーは完全に無意味になってた…

続きを読む

Mono<Void> は常に empty

当然といえば当然ですが、意外と気づかない。

例えば、特定の条件を満たさないとリクエストを処理しないような 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));
  };
}