20190730のJavaに関する記事は6件です。

Spring Boot + WireMockでNoHttpResponseException

事象

商用で動いているSpring BootのAppを改修した。
AppにはRestTemplateを使って他の連携先システムのREST APIを呼びにいく箇所があり、該当箇所を含む単体テストはWireMockでモックサーバを立てて実施していた。

改修に応じてテストを追加した所、既存のテストが突然
NoHttpResponseException:[server] failed to respond
などと例外を吐いてコケるようになった。

テストを単体で実行すると通り、通しで実行するとコケるという状態のため、テスト自体のミスでは無い模様。
ということで調査開始。

原因

WireMockへアクセスするAppのHttp Clientに、HttpURLConnectionを使用している場合に発生するバグらしい。

https://github.com/tomakehurst/wiremock/issues/97
SpringのRestTemplateも内部的にはHttpURLConnectionを使っているので該当。

対策

spring-cloud-contract-wiremockを使う。

https://github.com/tomakehurst/wiremock/issues/97
同issueに何種類かの対策が示されているので、お気に召すものを採用すれば良いと思われる。
一応の選定基準は以下の様な感じ。

  • Spring Bootのバージョンを上げる or HttpClientを変える
    商用で動いているAppなので、テストのために構成変更は基本NG→✕

  • HttpClientのconnection reuseを無効化
    設定場所が分からないし、Appの動作に影響出そう→✕

  • spring-cloud-contract-wiremockの利用
    テストのライブラリ変更だけで完結→○

spring-cloud-contract-wiremockは名前の通り内部でwireMockを利用しているので、テストコードの変更も最小限で済みました。
具体的には、サーバ設定の記法を変更して、既存のテスト用resourceのディレクトリを指定してやるだけ。
詳しい使い方は公式参照

Configuration(before)
public class ExampleUnitTest {
    @Rule
    public WireMockClassRule wireMockRule = new WireMockClassRule(8080);
.... 
Configuration(after)
@AutoConfigureWireMock(port = 8080, stubs = "classpath*:/META-INF/**/mappings/**/*.json")
public class ExampleUnitTest {
....

上記の通り、私の場合はstubs =で指定しているテスト用resourceのパスをよしなにしてやるだけで既存のテストコードがそのままパスするようになりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

swagger condegenからの自動生成メモ

swagger condegenからの自動生成メモ

公式の情報が多すぎてちょっとよくわからなくなったので、メモ残します

使った理由

  • ドキュメントを絶対正義とした開発をしたかったから。
  • クライアントも出力出来てテストしやすそうだったから。

generateしてみる

難しいことはなく、↓でできます。

java -jar swagger-codegen-cli.jar generate \
  -i swagger.json \
  -l java \
  -o outfolder \

しかし、package構成やプロジェクト名がなかなか実用的ではなかったりしますね。

image.png

オプションを指定できる

公式に従い、確認します。
spring使いたかったので、springのoptionを調べます

java -jar swagger-codegen-cli-2.4.7.jar config-help -l spring
        sortParamsByRequiredFlag
            Sort method arguments to place required parameters before optional parameters. (Default: true)

        ensureUniqueParams
            Whether to ensure parameter names are unique in an operation (rename parameters that are not). (Default: true)

        allowUnicodeIdentifiers
            boolean, toggles whether unicode identifiers are allowed in names or not, default is false (Default: false)

        modelPackage
            package for generated models

        apiPackage
            package for generated api classes

        invokerPackage
            root package for generated code

        groupId
            groupId in generated pom.xml

        artifactId
            artifactId in generated pom.xml

        artifactVersion
            artifact version in generated pom.xml

        artifactUrl
            artifact URL in generated pom.xml

        artifactDescription
            artifact description in generated pom.xml

        scmConnection
            SCM connection in generated pom.xml

        scmDeveloperConnection
            SCM developer connection in generated pom.xml

        scmUrl
            SCM URL in generated pom.xml

        developerName
            developer name in generated pom.xml

        developerEmail
            developer email in generated pom.xml

        developerOrganization
            developer organization in generated pom.xml

        developerOrganizationUrl
            developer organization URL in generated pom.xml

        licenseName
            The name of the license

        licenseUrl
            The URL of the license

        sourceFolder
            source folder for generated code

        localVariablePrefix
            prefix for generated code members and local variables

        serializableModel
            boolean - toggle "implements Serializable" for generated models (Default: false)

        bigDecimalAsString
            Treat BigDecimal values as Strings to avoid precision loss. (Default: false)

        fullJavaUtil
            whether to use fully qualified name for classes under java.util. This option only works for Java API client (Default: false)

        hideGenerationTimestamp
            hides the timestamp when files were generated

        withXml
            whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML) (Default: false)

        dateLibrary
            Option. Date library to use
                joda - Joda (for legacy app only)
                legacy - Legacy java.util.Date (if you really have a good reason not to use threetenbp
                java8-localdatetime - Java 8 using LocalDateTime (for legacy app only)
                java8 - Java 8 native JSR310 (preferred for jdk 1.8+) - note: this also sets "java8" to true
                threetenbp - Backport of JSR310 (preferred for jdk < 1.8)

        java8
            Option. Use Java8 classes instead of third party equivalents
                true - Use Java 8 classes such as Base64
                false - Various third party libraries as needed

        disableHtmlEscaping
            Disable HTML escaping of JSON strings when using gson (needed to avoid problems with byte[] fields) (Default: false)

        title
            server title name or client service name

        configPackage
            configuration package for generated code

        basePackage
            base package (invokerPackage) for generated code

        interfaceOnly
            Whether to generate only API interface stubs without the server files. (Default: false)

        delegatePattern
            Whether to generate the server files using the delegate pattern (Default: false)

        singleContentTypes
            Whether to select only one produces/consumes content-type by operation. (Default: false)

        java8
            use java8 default interface (Default: false)

        async
            use async Callable controllers (Default: false)

        responseWrapper
            wrap the responses in given type (Future,Callable,CompletableFuture,ListenableFuture,DeferredResult,HystrixCommand,RxObservable,RxSingle or fully qualified type)

        useTags
            use tags for creating interface and controller classnames (Default: false)

        useBeanValidation
            Use BeanValidation API annotations (Default: false)

        implicitHeaders
            Use of @ApiImplicitParams for headers. (Default: false)

        swaggerDocketConfig
            Generate Spring Swagger Docket configuration class. (Default: false)

        useOptional
            Use Optional container for optional parameters (Default: false)

        generateForOpenFeign
            Generate for usage with OpenFeign (instead of feign) (Default: false)

        library
            library template (sub-template) to use (Default: spring-boot)
                spring-boot - Spring-boot Server application using the SpringFox integration.
                spring-mvc - Spring-MVC Server application using the SpringFox integration.
                spring-cloud - Spring-Cloud-Feign client with Spring-Boot auto-configured settings.

指定してみました。

ちゃんと全部Packageを指定しないとdefaultのio.swaggerに出力されるので注意

{
    "groupId": "hoge",
    "artifactId": "hoge",
    "artifactVersion": "1.0.0-SNAPSHOT",
    "basePackage": "hoge",
    "configPackage": "hoge",
    "modelPackage" "hoge",
    "apiPackage" "hoge",
    "java8": true,
    "useBeanValidation": true
}

generate

java -jar swagger-codegen-cli-2.4.7.jar generate \
 -i ./swagger.yml \
 -l spring \
 -o ./ \
 -c ./config.json

mvn install

がっかり
image.png

pom書き換える

追記

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.1</version>
</dependency>

mvn install

成功

image.png

そういえばSpringのバージョンは?

古い

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

参考

https://github.com/swagger-api/swagger-codegen
https://github.com/swagger-api/swagger-codegen/wiki/Server-stub-generator-HOWTO

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

swagger condegenからの自動生成メモ(spring) -1

swagger condegenからの自動生成メモ

公式の情報が多すぎてちょっとよくわからなくなったので、メモ残します

使った理由

  • ドキュメントを絶対正義とした開発をしたかったから。
  • クライアントも出力出来てテストしやすそうだったから。

generateしてみる

難しいことはなく、↓でできます。

java -jar swagger-codegen-cli.jar generate \
  -i swagger.json \
  -l java \
  -o outfolder \

しかし、package構成やプロジェクト名がなかなか実用的ではなかったりしますね。

image.png

オプションを指定できる

公式に従い、確認します。
spring使いたかったので、springのoptionを調べます

java -jar swagger-codegen-cli-2.4.7.jar config-help -l spring
        sortParamsByRequiredFlag
            Sort method arguments to place required parameters before optional parameters. (Default: true)

        ensureUniqueParams
            Whether to ensure parameter names are unique in an operation (rename parameters that are not). (Default: true)

        allowUnicodeIdentifiers
            boolean, toggles whether unicode identifiers are allowed in names or not, default is false (Default: false)

        modelPackage
            package for generated models

        apiPackage
            package for generated api classes

        invokerPackage
            root package for generated code

        groupId
            groupId in generated pom.xml

        artifactId
            artifactId in generated pom.xml

        artifactVersion
            artifact version in generated pom.xml

        artifactUrl
            artifact URL in generated pom.xml

        artifactDescription
            artifact description in generated pom.xml

        scmConnection
            SCM connection in generated pom.xml

        scmDeveloperConnection
            SCM developer connection in generated pom.xml

        scmUrl
            SCM URL in generated pom.xml

        developerName
            developer name in generated pom.xml

        developerEmail
            developer email in generated pom.xml

        developerOrganization
            developer organization in generated pom.xml

        developerOrganizationUrl
            developer organization URL in generated pom.xml

        licenseName
            The name of the license

        licenseUrl
            The URL of the license

        sourceFolder
            source folder for generated code

        localVariablePrefix
            prefix for generated code members and local variables

        serializableModel
            boolean - toggle "implements Serializable" for generated models (Default: false)

        bigDecimalAsString
            Treat BigDecimal values as Strings to avoid precision loss. (Default: false)

        fullJavaUtil
            whether to use fully qualified name for classes under java.util. This option only works for Java API client (Default: false)

        hideGenerationTimestamp
            hides the timestamp when files were generated

        withXml
            whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML) (Default: false)

        dateLibrary
            Option. Date library to use
                joda - Joda (for legacy app only)
                legacy - Legacy java.util.Date (if you really have a good reason not to use threetenbp
                java8-localdatetime - Java 8 using LocalDateTime (for legacy app only)
                java8 - Java 8 native JSR310 (preferred for jdk 1.8+) - note: this also sets "java8" to true
                threetenbp - Backport of JSR310 (preferred for jdk < 1.8)

        java8
            Option. Use Java8 classes instead of third party equivalents
                true - Use Java 8 classes such as Base64
                false - Various third party libraries as needed

        disableHtmlEscaping
            Disable HTML escaping of JSON strings when using gson (needed to avoid problems with byte[] fields) (Default: false)

        title
            server title name or client service name

        configPackage
            configuration package for generated code

        basePackage
            base package (invokerPackage) for generated code

        interfaceOnly
            Whether to generate only API interface stubs without the server files. (Default: false)

        delegatePattern
            Whether to generate the server files using the delegate pattern (Default: false)

        singleContentTypes
            Whether to select only one produces/consumes content-type by operation. (Default: false)

        java8
            use java8 default interface (Default: false)

        async
            use async Callable controllers (Default: false)

        responseWrapper
            wrap the responses in given type (Future,Callable,CompletableFuture,ListenableFuture,DeferredResult,HystrixCommand,RxObservable,RxSingle or fully qualified type)

        useTags
            use tags for creating interface and controller classnames (Default: false)

        useBeanValidation
            Use BeanValidation API annotations (Default: false)

        implicitHeaders
            Use of @ApiImplicitParams for headers. (Default: false)

        swaggerDocketConfig
            Generate Spring Swagger Docket configuration class. (Default: false)

        useOptional
            Use Optional container for optional parameters (Default: false)

        generateForOpenFeign
            Generate for usage with OpenFeign (instead of feign) (Default: false)

        library
            library template (sub-template) to use (Default: spring-boot)
                spring-boot - Spring-boot Server application using the SpringFox integration.
                spring-mvc - Spring-MVC Server application using the SpringFox integration.
                spring-cloud - Spring-Cloud-Feign client with Spring-Boot auto-configured settings.

指定してみました。

ちゃんと全部Packageを指定しないとdefaultのio.swaggerに出力されるので注意

{
    "groupId": "hoge",
    "artifactId": "hoge",
    "artifactVersion": "1.0.0-SNAPSHOT",
    "basePackage": "hoge",
    "configPackage": "hoge",
    "modelPackage" "hoge",
    "apiPackage" "hoge",
    "java8": true,
    "useBeanValidation": true
}

generate

java -jar swagger-codegen-cli-2.4.7.jar generate \
 -i ./swagger.yml \
 -l spring \
 -o ./ \
 -c ./config.json

mvn install

がっかり
image.png

pom書き換える

追記

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.1</version>
</dependency>

mvn install

成功

image.png

そういえばSpringのバージョンは?

古い

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

参考

https://github.com/swagger-api/swagger-codegen
https://github.com/swagger-api/swagger-codegen/wiki/Server-stub-generator-HOWTO

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java学習日記 1日目

初めまして。ミントッパと言います。
現在27歳、大学卒業後5年間製造業やってました。

上がらない給料、下がる一方のボーナスに将来の不安を感じ
エンジニアになるべく転職を決意しました。

独学でRubyを学び、大したスキルは無いが勉強意欲を評価されて無事内定!
8月よりJavaエンジニアとして働くことになった。

エンジニアはアウトプットが大事とのことなので
今日から勉強の記録をしていこうと思う。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaのラムダ式を改めて

はじめに

IT業界に飛び込んで早2年ちょっとが経過。
本格的にコーディングに取り組んだのが正直なところ、1年とちょっとくらいしかない。
かつ、運用保守ということもあり、既存の実装をなるべく汚さないようにエンハンスすることが正な世界で生きてきた。
そして何と言っても、そのパッケージで利用されていたJDKはjava1.7!!
という上記の背景からも、なかなかjava8以降に触れることも少なかったので、今一度学び直したいと思った。
備忘録も兼ねつつ、今後はQiitaへの執筆も本格化していきたいところでもあるので、今回の執筆に至った。

まずはその第一歩として、ラムダ式についての理解がぼんやりしていたので、記事を通して理解を深めたい。

ラムダ式って何? ⇨ インタフェースって何?

ラムダ式をいきなり理解する前に、どうやら関数型インタフェースに関する前提知識が必要そう。
そうなるとそもそも、インタフェースって何?と聞かれるとはっきり答えることができない自分がいる。
恥を恐れずJavaにおけるインタフェースについて、まずはしっかり理解しておこうと思う。

Javaにおけるインタフェースとは?

以下の記事がわかりやすく、参考になるかと思います。
https://www.internetacademy.jp/it/programming/java/difference-between-interface-and-abstract.html

インタフェースとは、メソッドの箱だけを準備しておき、その箱を実際に利用するとき(継承)に、継承先のクラスに実装を強制させる。
例えば、EmployeeというEntityに対するServiceクラスとして、EmployeeServiceを実装する場面を考える。

EmployeeService.java
interface EmployeeService {
     Employee getEmployee(String pk);
}

Serviceクラスの実装でよく見かける(使われるケース)として、Serviceのinterfaceを実装し、メソッドのみを外部に公開する方法。
EmployeeServiceの実装クラスとして、EmployeeServiceImplを別クラスで作成する。

EmployeeServiceImpl.java
public class EmployeeServiceImpl implements EmployeeService {
     Employee getEmployee(String pk) {
          // Daoにアクセスして、pkに一致するEmployeeを取得する。
          return employeeDao.find(pk); 
     }
}

ここで重要なのは、このEmployeeServiceImplEmployeeServiceを継承しているため、
EmployeeServiceにて宣言された、getEmployeeを必ず実装しなくてはいけないということ。
こうすることで、インタフェースを継承した実装クラスは必ずインタフェースで宣言されたメソッドを実装しなくてはコンパイルエラーとなり、実装を強制することができる。

抽象クラスとインタフェースの一番の違いは、多重継承することができるという点。
多重継承について詳しくは記載しないが、要するに複数の実装を強制する仕組みをインタフェースだと利用できるということ。
(複数のインタフェースをひとつのクラスが継承することができるということ。)

ラムダ式って何? ⇨ 関数型インタフェースって何? ⇨ 関数って何?

インタフェースについてはわかった。わかったけど、まだラムダ式を理解しにかかるには足りていない知識がある。
関数型インタフェースってなに?
ん、関数型ってなに?
んん、関数ってなに?

Javaにおける関数とは?

関数とは何かは以下のURLが参考になります。
https://stackoverflow.com/questions/155609/whats-the-difference-between-a-method-and-a-function

要するに関数とは、
とあるパラメータ(引数)を受け取り、引数をもとに何らかの処理を加えた上で結果の値を返す(return)するもの。

関数を実装する際に気をつけるべきポイントがあるため、ついでにここで紹介しておく。
Javaのような言語でプログラミングを経験していると、遅かれ早かれ副作用という単語を聞くことになる。
副作用というのは超簡単にざっくりと言うと・・・
関数の実行結果が常に一定とならない実装だと自分は理解しています。

副作用のない関数を実装するために意識しておくポイントは以下です。
1. 関数は引数の値以外からは影響を受けない。
2. 同じ引数の値であれば、常に同じ値を返す。

具体的な実装例等は別途調べてみてください。(自分よりもうまく説明してくれている記事は5万とあります。)

話は戻って、関数とは結局、入力に対して値を返すものです。

関数って何? ⇨ 関数型インタフェースって何?

関数についてはざっくり理解できた。
じゃあいよいよ関数型インタフェースって何?という話に主題を移してみる。
以下の記事がかなり参考になるので記載しておきます。
http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html#h_outline

こちらの記事でも言及されているように、関数型インタフェースとは、

定義されている抽象メソッドが1つだけあるインターフェース。

ということです。

この記事の中で紹介した、EmployeeServiceは関数型インタフェースと呼ぶことができます。
pkに一致するEmployeeを取得して返すということのみを行なっているServiceクラスです。

EmployeeService.java
@FunctionalInterface
public interface EmployeeService {
    Employee getEmployee(String pk);
}

関数型インタフェースを定義するのポイントとしては、@FunctionalInterfaceのアノテーション。
このアノテーションを付与することで、関数型インタフェースであることを明示的に宣言でき、コンパイル時にも条件を満たしていない場合はエラーとなります。
また、実装を追う場面でもこのアノテーションが付与されていることで、関数型インタフェースであることを他者から見てもわかりやすくなります。
defaultstaticメソッドが定義されていても、それらは関数型インタフェースの条件からは除外されるらしい。

関数型インタフェースって何? ⇨ ラムダ式って何?

JDK1.8から、関数型インタフェース(抽象メソッドを1つのみ保持しているインタフェース)を特別なものとして扱うことになった。
さて、本記事の本題にようやく返ってきました。ここからようやく結局ラムダ式ってなに?を突き詰めようと思います。

以下の記事がすごくわかりやすく、ラムダ式のことを図解してくれているので参考になります。
http://masatoshitada.hatenadiary.jp/entry/2015/02/09/190150

つまるところ、ラムダ式を理解するためには、Functionを例に型推論を理解することが一番だと思う。

ラムダ式って何? ⇨ Functionって何? 型推論って何?

FunctionとはJava8で導入されたパッケージです。
Function<T, R>で型が定義されており、Tは引数となる型、Rは戻り値として返す型となります。
で、このFunctionは関数型インタフェースとして定義されており、applyというメソッドのみを持ちます。

ラムダ式を利用して、Functionを実装することができます。
以下に簡単に実装例を示します。
例)EmployeeNameFunctionを利用して取得する。

Employee.java
@Getter
@Setter
@AllArgsConstructor(staticName = "of")
public class Employee {
    /** Id */
    private int id;

    /** Name */
    private String name;
}
Main.java
pubic class Main {
    public static void main(String args[]){
        Employee emp = Employee.of(1, "Sample太郎")
        Function<Employee, String> getEmployeeName = employee -> employee.getName();
        String empName = getEmployeeName.apply(emp);
        System.out.println(empName); // 「Sample太郎」が出力される。
    }
} 

Name取り出すくらいならGetter使えよなんて声はご愛嬌ください。

上記の例で重要なのはここ。

Function<Employee, String> getEmployeeName = employee -> employee.getName();

Functionの引数となる型(Employee)から、戻り値としてemployee.getName()の結果である、文字列型(String)を返却する処理を、Functionが持っているapplyというメソッドに実装します。
ということをラムダ式を用いてやっている。

型推論employeeTであるEmployeeだとJavaは解釈し、型推論returnする値がStringであることをJavaは解釈します。(賢いですね・・・)

String empName = getEmployeeName.apply(emp);

そして実際に上記部分で、StringのempNameFunctionapplyを適用させる。

というように関数型インタフェースの記載をシンプルにできるメリットがラムダ式にはあります。

ラムダ式って何?

結局自分が理解したラムダ式とは、関数型インタフェースを実装するにあたり、型推論を駆使して実装をシンプルにする便利なやつだということ。
ラムダ式単体での活用シーンは限られており、ラムダ式が真に実力を発揮するのは、Functionstreamと合わさった時なのかなと。
streamを利用する際に特にこのラムダ式を意識することは必ずしも必要ではないが、理解しておいても損はないかな。

おわりに

Optionalの学び直しもやろうと思っているが、どうやらラムダ式(というよりはConsumerとか)が絡んできそう。
記事書くことで理解も捗る + 備忘 になるので、今後も積極的に書いていきたいと思う。

間違いやアドバイス等々ございましたら、コメントよろしくお願いいたします・・・!

次回はOptionalに関する記事を書きたいと思います。
ではでは〜

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Programming News】Qiitaまとめ記事 July 29, 2019 Vol.15

筆者が2019/7/29(月)に気になったQiitaの記事をまとめました。昨日のまとめ記事はこちら

2019/7/21(日)~2019/7/27(土)のWeeklyのまとめのまとめ記事もこちらで公開しております。

Java

Python

Rails

Vue.js

Android

Swift

Kotlin

Flutter

JavaScript

Node.js

React

Laravel

Keras

PowerShel

Spark

R言語

MySQL

Azure

AWS

Docker

TypeScript

Google Apps Script

機械学習

Raspberry

Develop

Intellij IDEA

更新情報

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む