日々常々

ふつうのプログラマがあたりまえにしたいこと。

ハンズオンイベントに潜む悪魔(黒猫)

11/15に「Javaでwebアプリケーション入門」というイベントのお手伝いをいたしました。 #javajok で関西Java女子部さんのイベントです。

私は参加者と一緒にライブコーディングをするという大役を仰せつかり、緊張のあまり前日は24時間以上爆睡いたしまして。 おかげでGitHubの草を生やそう運動が54日で止まりました。無念。

会場は @bufferings さんに楽天株式会社大阪支社のカフェテリアを提供いただきました。最高ですね。広いし綺麗だし。

同会場にて11月21日(土)に Rakuten Technology Conference 2015 のサテライトが行われます。大阪にいながら世界のセッションを聞けますよ!(英語的な意味で)

当日のコトが起こるまで

家を出てすぐに黒猫に横切られました。嫌な予感がぷんぷんしました。

まず、環境構築でドハマりしました。 ハンズオンイベントでの問題となる筆頭は環境構築です。 ただ、Javaの場合はJDKIDEの準備さえしていてもらえれば、GradleWrapperが他は良いようにしてくれます。 してくれる。そう思っていた時期もありました。参加者が一斉にGradleWrapperを使えば……ダウンロード、すっごいですね。 全然終わりませんでした。

セッション順番を組み替えたり、Gradleを使わずにjarを添付する形にしたり、運用対処でなんとか凌いでハンズオン開始。 準備はできているので大丈夫だと思っていました。各ステップを細かくコミットしたブランチも作って「何かあってもこれを見てもらえばいける」くらいの気分。この準備は前日やる予定だったのですが、残念ながら私の土曜日は夢に飲み込まれたので、仕方なく会場についてから必死にやってました。でも間に合った、いけるつもりでした。

しかし、現実はそうは甘くありません。 本番はAPIサーバーをherokuに立てました。素振りはlocalhostでやりました。検証環境と本番環境が異なると問題が検出できないものです。 ですが素振りの他に、ほぼ同じように作成したサンプルは動作していたので、大丈夫だと思っていました。油断していたのです。

ただでさえ初心者を対象にしたハンズオン。 いくらサポート陣を揃えていても、予定通り進まないのはある程度仕方ありません。 この辺りは織り込み済みで、最悪最後まで行かなくても仕方ないかなーとも思っていました。

起こったコト

ハンズオンの最後の最後。ブラウザで入力したメッセージをつぶやく、よくあるフォーム入力を受け付けるところです。 そこに、以下のようなコードがありました。

Response res = new RestTemplete().postForObject(
        "http://xxxx.heroku.com/yyy",
        param,
        Response.class);

この子がエラーにならずに正常終了しているのに、APIサーバーにはPOSTできませんでした。ちなみにGETの方は普通に動いていたので、タチが悪い。

原因は xxxx.heroku.com/yyy が xxxx.herokuapp.com/yyy にリダイレクトされる動作になっている点。getForXxx はリダイレクトを平然と処理して、リダイレクト先の結果を返してきます。一方 postForXxx はリダイレクトは処理せず(POSTなのでリダイレクトしたらダメだよね)、そのまま301 Moved Permanentlyを空のbodyで受け取って終了しちゃっていました。 この結果になっていることが検出できずに処理は正常終了。最終的には「エラーにならないのに動かない」という不思議な事態となりました。 プロジェクターでスクリーンに画面を映しながら、頭抱えることに……。

結果的には終わる前に解決できて動いたので、それはそれで良いのですが。

言い訳タイム

herokuとかRestTempleteとか普段使ってないのがね……。

postForEntityで受けて、ResponseEntitystatusCodeを見れば判断つくのですが、postForObjectだと直接オブジェクトが生成されちゃうので、見るタイミングがありません。一応RestTemplateに拡張したErrorHandlerを差し込んで「201 Created 以外ならエラー」とかもできますが、どちらにせよ「初心者向けハンズオン」にあまり複雑なことは持ち込みたくはないので、知っていても入れなかったでしょう。(Springのハンズオンでは無いのです)

素振りの時点でherokuを使っておけば、herokuとherokuappの違いに気付けたかもしれません。アドレスを打つときに手打ちせずにコピペしていれば間違えませんでした。URIを手打ちせず、サンプルと同じく設定ファイルから @Value で取っておけば問題は起きなかったです。どれも実際は起こらなかった可能性ですが、助かる可能性もあるにはありました。

しかし、気付くタイミングや間違えないタイミングは全てスルーして問題は起きるものです。油断大敵……そこまでは結構うまくいってた(つもりな)だけに、残念感が酷かったです。

総括

とても楽しかった。今度から黒猫に横切られたら帰って寝る。