JSON Server でダミーサーバを手軽に構築する

JSON を返すダミー API サーバを構築する際、以下が手軽で便利そうだったので使ってみる。

github.com


npm コマンドでインストール。

npm install -g json-server

APIJSON ファイルで作成する。次の場合、exampleAPI のエンドポイントとなり、value のオブジェクトがレスポンスボディとなる。

{
  "example": {
    "values": [
      { "id": "1", "name": "foo" },
      { "id": "2", "name": "bar" },
      { "id": "3", "name": "baz" },
      { "id": "4", "name": "hoge" },
      { "id": "5", "name": "fuga" }
    ]
  }
}

JSON Server を起動する。--watch オプションを付けると JSON ファイルの変更を監視してくれる。便利。

json-server --watch example.json

http://localhost:3000/example にアクセスすると以下のレスポンスが返る。

{
  "values": [
    {
      "id": "1",
      "name": "foo"
    },
    {
      "id": "2",
      "name": "bar"
    },
    {
      "id": "3",
      "name": "baz"
    },
    {
      "id": "4",
      "name": "hoge"
    },
    {
      "id": "5",
      "name": "fuga"
    }
  ]
}

JSON Server 起動時に js ファイルを指定して、動的にレスポンスを生成することもできる。(未検証)

(2019/10/01 追記)

ルーティングについて。

JSON Server ではエンドポイントの設定に / を含めることができない。例えば、/example/10001 のような記述を db.json に書くことはできない。

そこで、次のような routes.json を用意する。

{
  "/example/10001": "/example1",
  "/example/10002": "/example2"
}

これに合わせて次のような db.json を用意。

{
  "example1": {
    "values": [
      // ...
    ]
  },
  "example2": {
    "values": [
      // ...
    ]
  }
}

JSON Server 起動。

json-server --watch db.json --routes routes.json

http://localhost:3000/example/10001 にアクセスすると内部で /example1 にルーティングされて、db.jsonexample1 の内容が返却される。

参考) Add custom routes - typicode/json-server

jQuery プラグインを使ってキーワードサジェストを実装してみる

Google 検索のようなキーワードサジェストを実装する際、以下の jQuery プラグインが使いやすくてよかったです。というメモ。

www.devbridge.com

ソースコードはこちら

github.com

利用方法

プラグインを読み込む。

<script src="js/jquery.autocomplete.min.js"></script>

キーワードサジェストを適用するテキストボックスを用意。

<input type="text" id="autocomplete">

今回はサンプルということで、Ajax ではなく内部に埋め込んであるデータを読み込む。

$(function() {
  var values = [
    { value: 'foo', id: '1', name: 'FOO' },
    { value: 'bar', id: '2', name: 'BAR' },
    { value: 'baz', id: '3', name: 'BAZ' },
    { value: 'hoge', id: '4', name: 'HOGE' },
    { value: 'fuga', id: '5', name: 'FUGA' }
  ];
  $('#autocomplete').autocomplete({
    lookup: values,
    onSelect: function(suggestion) {
      console.log('id: ' + suggestion.id + ', name: ' + suggestion.name);
    }
  });
});

$('#autocomplete').autocomplete({ ... でテキストボックスに対してキーワードサジェストを適用する。lookup プロパティには、サジェストするデータを格納したオブジェクトを指定する。内部的にはオブジェクトの value プロパティの値がマッチングに使われる模様。

onSelect プロパティには、サジェストされた候補から選択したときにコールバックされる関数を指定する。

表示データを Ajax で取得する場合

serviceUrlAjax のリクエスト URLを指定する。レスポンスは JSON 形式であること。

$('#autocomplete').autocomplete({
  serviceUrl: '<ajax-url>',
  onSelect: function(suggestion) {
    console.log('id: ' + suggestion.id + ', name: ' + suggestion.name);
  }
});

Ajax のレスポンスをごにょごにょする場合は以下でイケる。

$('#autocomplete').autocomplete({
  lookup: function(query, done) {
    $.ajax({
      type: 'GET',
      url: '<ajax-url>',
      data: 'query=' + query,
      dataType: 'json',
      success: function(res) {
        // レスポンスをごにょごにょして done に渡す
        // res = { suggestions: [ { value: 'foo', id: '1', name: 'FOO' }, ... ] };
        done(res);
      },
    });
  },
  onSelect: function(suggestion) {
    console.log('id: ' + suggestion.id + ', name: ' + suggestion.name);
  }
});

(2017/01/18 追記)
Ajax の動作を手軽に試すなら JSON Server が便利。

kntmr.hatenablog.com

2017年の行動指針

早くも2017年の1.9%が過ぎ去ろうとしていますが、年末年始を帰省先でだらだらと過ごした影響で、未だに怠け癖が抜けない今日この頃です。このまま貴重な時間を浪費するのはよろしくないので、きちんと計画というか行動指針みたいなものを決めておこうかと思います。

基本的に毎日勉強することが目標。

平日の通勤時間を利用して英語を勉強する。当面は、zuknow アプリを利用して英単語を覚える。その他、英文法やリスニングをやる。

http://blog.zuknow.net/

仕事は、本質的な作業に集中することを意識する。「神は細部に宿る」と言いますが、いつもどうでもいい細かいところばかりに気を取られる傾向にあるので、ある程度のアウトプットを出したら早く家に帰るようにしよう。

帰宅したら素早く家事を片付けて子供を寝かし付け、22~24時を自分の時間として確保できるようにする。ただし、疲れているときは無理せず寝る。翌早朝に起きて朝活するのもありだが、過去の朝活経験からすると継続することは期待できない...。

当面は、Oracle Certified Java Programmer, Gold SE 8 認定資格に向けて勉強する。あと、JavaScript フレームワークを勉強したい。仕事で Angular + Spring の組み合わせを使う可能性があるので、Angular 2 あたりかな。今さら感あるけども。Angular 以外だと React か Vue.js あたりか。

とりあえずしばらくはこんな感じで。

Apache HttpClient の HttpRequestRetryHandler でリトライをカスタマイズするサンプル

Apache HttpClient の DefaultHttpRequestRetryHandler は ConnectTimeoutException のときはリトライしない - kntmr-blog

これの続き。

雑ですが、HttpRequestRetryHandler でリトライをカスタマイズするサンプルを書いてみました。ついでにリトライの間隔を指定できるようにしました。

gist.github.com

使うときはこんな感じ。

MyRetriableHttpClient client = new MyRetriableHttpClient(url).setTimeout(5000, 5000).setRetry(3, 3000);
try {
    Optional<String> resp = client.execute();
    resp.ifPresent(System.out::println);
} catch (IOException e) {
    // error
}

Apache HttpClient の DefaultHttpRequestRetryHandler は ConnectTimeoutException のときはリトライしない

Apache HttpClient はデフォルトで3回リトライする機能を持っています。しかし、コネクションタイムアウト (ConnectTimeoutException) のときはリトライしません。すべてドキュメントに書いてあることなんですが、そのあたりを調べたときのメモ。

※以下は Apache HttpClient 4.4.1 で調べています。

HttpClientBuilder#setRetryHandler でハンドラを設定せずに HttpClient を生成すると、デフォルトで DefaultHttpRequestRetryHandler が使われます。

以下、HttpClientBuilder#build から抜粋。

if (!automaticRetriesDisabled) { // automaticRetriesDisabled は デフォルトで false
    HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
    if (retryHandlerCopy == null) {
        retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE; // INSTANCE は new DefaultHttpRequestRetryHandler() で初期化されている
    }
    execChain = new RetryExec(execChain, retryHandlerCopy);
}

以下、DefaultHttpRequestRetryHandler のドキュメントから抜粋。

DefaultHttpRequestRetryHandler (Apache HttpClient 4.4.1 API)

Create the request retry handler with a retry count of 3, requestSentRetryEnabled false and using the following list of non-retriable IOException classes: InterruptedIOException, UnknownHostException, ConnectException, SSLException

余談ですが、最初、ここの non-retriablenon-retrieval に読み間違えて、全然見当違いな解釈をしていたことは内緒です。で、デフォルトコンストラクタを呼び出すと、リトライ不可能な IOException として以下が設定されるようです。

  • InterruptedIOException
  • UnknownHostException
  • ConnectException
  • SSLException

以下、DefaultHttpRequestRetryHandler#retryRequest からリトライ処理を抜粋。

if (this.nonRetriableClasses.contains(exception.getClass())) {
    return false;
} else {
    for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
        if (rejectException.isInstance(exception)) {
            return false;
        }
    }
}

この this.nonRetriableClasses に上記4つのクラスが設定されています。ConnectTimeoutExceptionInterruptedIOException のサブクラスなので、retryRequestfalse を返すことになります。

したがって、ハンドラを設定していない HttpClient では、コネクションタイムアウトのときにリトライしません。

(参考) Chapter 1. Fundamentals

  • 1.5.3. Automatic exception recovery
  • 1.5.4. Request retry handler

Windows 7 / 8.1 仮想環境

必要に迫られて構築したときに調べたメモ。

Free Virtual Machines from IE8 to MS Edge - Microsoft Edge Development

IE8 から Microsoft Edge までの Windows 仮想環境をダウンロードできる。
組み合わせは以下の通り。(2016/12/08 時点)

仮想環境の形式は VirtualBox, Vagrant, HyperV, VMWare から選択する。今回は IE11 on Win8.1 / Vagrant を利用。zip をダウンロードして展開する。

> vagrant init <box-name> # box-name は box のファイル名を指定

Vagrantfile に以下を設定する。

config.vm.provider "virtualbox" do |vb|
    vb.gui = true
end
config.vm.guest = :windows
config.vm.communicator = "winrm"
config.vm.network :forwarded_port, guest: 3389, host: 3389

仮想マシン起動。

> vagrant up

起動が完了すると、VirtualBox のコンソールが起動する。とりあえず日本語化する。

プロキシ

日本語化は、Windows Update 経由で Language Pack をダウンロードするようなので、プロキシ環境の場合はプロキシを設定する。

  1. Windows キー > Apps > PC settings
  2. Network > Proxy
  3. Use a proxy server を On

日本語化

  1. Windows キー > Apps > PC settings
  2. Time and language > Region and language
  3. Country or region で Japan を選択
  4. Languages の Add a language で「日本語」を追加
  5. 日本語をクリック > Options
  6. Language options の Language Pack をダウンロード
  7. 日本語をクリック > Set as primary
  8. English を Remove

ついでに Time and language の Date and time で Time zone を変更する。

サインアウト > サインインで、日本語化が適用される。

JJUG CCC 2016 Fall に行ってきた

JJUG CCC 2016 Fall に行ってきました。簡単に所感をまとめます。

[CCC2016Fall]Be a great engineer! #jjug_ccc #ccc_a1 - Speaker Deck

  • 「こんなセッションを聞きに来てる時点でダメ」とのこと
  • 技術の本質を考える
  • 適材適所で使い分ける
  • 技術には必ずニーズが伴う (解決したい課題はなにか)
  • 技術的に優れていてもそれが正解とは限らない

他所のとある現場で、流行りの技術を使おうとして半ば強引に某フレームワークを採用しているんじゃないかと思えるようなケースを見たことがあります。そのシステムでそのフレームワークを使う必要があるのかと疑問ではありましたが、自分の考えにイマイチ自信を持つことができませんでした。
そういう意味で、このセッションの話を聴いて自分の考えは概ね間違ってないなと思えた気がします。いきなり「こんなセッションを聞きに来てる時点でダメ」とか言われてお茶吹きそうになりましたが、いい話が聴けてよかったです。

SpringはどうやってDIしているのか? #jjug_ccc - Speaker Deck

とにかくひとが多くて、改めて Spring の勢いを感じました。Spring のコードリーディングの話はたまに聴くけど、毎回勉強せねばって思う...。

メンバーのスキルアップ、どうしてる? − Java 100本ノックで新加入メンバーを鍛えてみた −

  • 回答 -> PR -> レビュー のサイクル
  • 教える側も本質を正しく理解していないといけない
  • アンチパターンには名前をつけるとよい
  • 「あなたが書いたコードはコピペであってもあなたのもの」
    • 自分がコードを書くところは自分の責任

Oracle のベンダー資格あたりも入門として使えそうな気がするけど、Java 100本ノックはより実践的な内容っぽいし、レビューし易いというのがメリットな気がします。

どうしようJUnit5 - Speaker Deck

  • この日、最も聴きたかったセッション
  • JUnit4 と JUnit5 の互換性はない (別のフレームワーク)
  • 基本的な機能は名前やパッケージが変わった程度
  • assertThat がなくなった (hamcrest を入れれば使える)
  • @Enclosed -> @Nested
    • @BeforeEach を使えばネストクラス間で初期化処理を共通化できそう
  • @DisplayName でテストに名前を付けることができる
    • メソッド名を日本語で書いてた日々に別れを告げる...

既存のテストを JUnit4 から移行する必要はなく、JUnit5 の正式リリース以降、新しくテストを書く場合に採用する感じでよさそう。
あと、テストメソッドの実行順序を制御する機能(@FixMethodOrder)があることを初めて知りました...。というか、実行順序を制御しないといけないケースに遭遇したことがないし、そもそも実行順序に依存するのはユニットテストとして NG だと思ってました。が、JUnit をシナリオテストで使うケースがあるんですね、なるほど。
現時点で自分のやりたいことは JUnit4 + JMockit でひと通りはできていて、JUnit5 ならそれがもう少し簡潔にできるのかなという印象。ただ、ぶっちゃけ Runner とか Rule とか Parameterized とか Theory とか JUnit の機能をまだ全然使いこなせていないのでもっと勉強が必要です...。

JPA と DDD の関係で僕が思っていること - Qiita

その他

CCCは7回目の参加になりますが、昔に比べて参加者が格段に増えて規模も大きくなりました。その分、セッション数も増えてどれを聴こうか迷います。あと、マスクがノベルティとして配布されてたけど、大人数が集まる場ではとてもよいですね。ありがたや。

その他の資料 (把握してる分のみ)

(2016/12/06 追記) ここに資料まとまってた。

github.com