Hanami + Vue.jsでTODOアプリを作った
REST APIで動くSPAを作ってみたかったので、TODOアプリ*1を作った。
まずはバックエンドとフロントエンドの分離を目指したかった。構成はこんな感じ:
- バックエンド:Hanami
- フロントエンド:Vue.js with webpack
資料
- Vue.jsではじめるMVVM入門 - DeNA Design
- Hanamiでwebpackを使う方法 - Qiita
- Vue.js初心者向け:Vue.jsとaxiosでJsonを取得してコンポーネントに反映するメモ - Qiita
やったこと
- バックエンド:Hanami
- 1.REST APIの作成(これは以前このブログでやりましたね)
- フロントエンド:Vue.js with webpack
- 2.Hanamiのassetsの仕組みを使わずに、assets-webpack-pluginで、javascriptをビルドして配信
- 3.あとはVue.jsではじめるMVVM入門の記事のとおりにVueのコードを書いて、HanamiとAjaxでつなげます
- 4.Ajaxにはaxiosというライブラリを使用しました、使いやすかったです
以下、もう少し詳しく
バックエンド:Hanami
1.REST APIの作成
以下の記事を参照
nantonaku-shiawase.hatenablog.com
フロントエンド:Vue.js with webpack
2.assets-webpack-pluginで、javascriptをビルドして配信
ほとんどHanamiでwebpackを使う方法 - Qiitaに書かれていることを実行したのみです。ざっくりとした流れ。
- Hanamiのassetsの仕組みを無効化
- yarnで依存するjavascriptのパッケージをインストール → package.jsonに依存関係が記録される
- webpackを実行してjavascriptを単一ファイルで読み込めるようにする
- それをassets-webpack-pluginで読み込む
これにより、Hanamiのアーキテクチャを利用しつつwebpackの恩恵を享受できるようです。yarnとwebpackはすばらです!何が素晴らしいかって、完全なパッケージ管理システムができていることです。
3.Vue.jsではじめるMVVM入門の記事のとおりにVueのコードを書いて
ここは順当にVue.jsのドキュメントを読んで実装しました。
- Vue.jsを使うと、WEBアプリのイベントをGUIアプリのイベントのように細かく扱えます
- 細かいHTML要素はプログラマーに対してうまく隠蔽されているので、やりやすいです。感銘を受けました。
- 下記は「hidden要素がVue.jsで使えないのか?」という質問ですが、解答は「使う必要はない」なのです
- 例えば、今までのアプリならWEBアプリからDBの1要素を削除する場合、HTMLにその1要素のキー値をhiddenなどで用意する必要がありましたが、Vue.jsを使えばそのようなものを用意する必要がなくなります。なぜならVue.jsが自分の中でid要素をオブジェクトとして持っているからです。
*1:本棚アプリのような練習用アプリです https://github.com/hangingman/vue_hanami_test
Apache POIで指定した範囲を空白にする
設定されているExcel式を全消ししたかったので…
Apache POIで指定した範囲を空白にする
動作環境
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <poi.version>3.17</poi.version> </properties> <dependencies> <!-- Apache POI とその依存関係 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.6</version> </dependency> ...
コード片
それなりに時間がかかってしまう。もっといい方法(from Javaから)あればコメントで知らせてください。
参考サイト
/** * 指定された範囲のセルを空白(BLANK)にする * @param sheet 作業対象シート * @param rangeString A1形式の範囲を文字列で */ private void setEmptyValuesWithRange(Sheet sheet, String rangeString) { // 処理時間を計測する StopWatch stopWatch = new StopWatch(); stopWatch.start(); System.out.print(String.format("-> %s を空にする…", rangeString)); CellRangeAddress range = CellRangeAddress.valueOf(rangeString); CellWalk cw = new CellWalk(sheet, range); cw.traverse(new CellHandler() { @Override public void onCell(Cell c, CellWalkContext ctx) { c.setCellType(CellType.BLANK); } }); stopWatch.stop(); System.out.println("OK! " + stopWatch.getTime()); }
それよりGoogle Spreadsheetがよさそうですよ
課題
Apache POIはMSが作っているわけではないし技術的(というより仕様的に)に限界がある。最近直面した問題:
- 複雑なExcel式計算をPOIに渡すと空白で返ってくる
- 前のバージョン、Apache POI 3.16だとそういうことがあった
- POIはライブラリの中でExcel式をエミュレートしてるそうですよ
- ユーザの嘆きの声 → excel - Complex cell formula evaluation does not work using apache-poi - Stack Overflow
- Excel式はユーザがWindows上でExcelを使ってファイルを開くまで実行されない、よって式の値が空白になることがある
- それを防ぐために FormulaEvaluator (POI API Documentation) を使って式を計算するんですが、これが重い
- Apache POIの式計算に関するドキュメント Formula Evaluation
根本的にExcelというクライアントツールがファイルの読み書きを握ってるので、あんまり自由度がない(商用だから当たり前だけど)。
Jettyが週1、2で停止する場合はtmpwatchを疑うべきかも
現象
- 週1or2でJettyが内部エラー起こしてリクエストに404エラーを返す
- エラー発生は決まって週末の同じ時間
解析
参考
- warファイルからお手軽起動したGitBucketの画像やCSSがなくなる | 眠るシーラカンスと水底のプログラマー
- gitbucketというOSSソフトがあるのだが、これも同じような現象が起きてたらしい
概要
- Jettyは無指定だと/tmp以下に公開しているwarファイルのコピーをキャッシュとして展開する
- tmpwatchはAmazon LinuxやCentosに標準でインストールされていて、/tmpにあるファイルを定期的に削除する*1
・/usr/sbin/tmpwatch 240 /tmp /tmp/下で240時間アクセスが無いファイルを削除する ・/usr/sbin/tmpwatch 720 /var/tmp /var/tmp/下で720時間アクセスが無いファイルを削除する ・/var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?} /var/cache/man/、/var/cache/catman/下で720時間アクセスがないファイルを削除する
- /tmpに展開されたキャッシュファイルが削除されると、Jettyは異常な状態になった
解決策
You have few choices.
(取れる選択肢はあんまりない。)1) Specify your own java.io.tmpdir java system property location for jetty to use.
$ java -Djava.io.tmpdir=/path/to/my/new/temp/ -jar start.jar(① Jettyが使用するjava.io.tmpdirのシステム設定の場所を指定する
$ java -Djava.io.tmpdir=/path/to/my/new/temp/ -jar start.jar)
2) Create a "work" directory under the ${jetty.home} path (whereever that is).
That will cause Jetty to use that work directory instead of whatever the java.io.tmpdir property is set to.(② "work"という名前のディレクトリを ${jetty.home} の下に作る。
これによりJettyはjava.io.tmpdirにどんなものが設定されていてもworkディレクトリを使用するようになる。)
*1:tmpwatchというサービスを知らなかった…