かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その7 )( webpack + browser-sync をインストールする )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その6 )( URL の決定 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 各画面の HTML を作成する前に、今回は HTML の確認を Tomcat ではなく webpack + browser-sync を使用して行ってみようと思います。
    • まずはインストールして試してみます。
  • 「Spring Boot + npm + Geb で入力フォームを作ってテストする」では webpack は js ファイルの開発にしか使わないので HTML の確認だけなら browser-sync だけでいいのですが、両方インストールして変更したファイル(html ファイルだけでなく js ファイルも)を watch する仕組みを構築します。

参照したサイト・書籍

  1. 最新版で学ぶwebpack 3入門 – JavaScript開発で人気のバンドルツール
    https://ics.media/entry/12140

  2. Building Static Sites with Webpack
    https://blog.binoy.io/building-static-sites-with-webpack-4fc489ceabca

  3. WebPack-Dev-ServerからBrowsersyncに乗り換えた
    https://saku.io/move-from-webpack-dev-server-to-browser-sync/

  4. webpackで複数のディレクトリへ出力する
    http://webdesign-dackel.com/2015/09/10/webpack-multiple-output/

  5. window.onloadとjQueryの$(document).ready等の比較
    https://rcmdnk.com/blog/2015/07/11/computer-javascript-jquery/

目次

  1. webpack をインストールする
  2. browser-sync をインストールする
  3. webpack + browser-sync 起動用の npm-scripts を作成する
  4. 動作確認する

手順

webpack をインストールする

npm install --save-dev webpack コマンドを実行して webpack をインストールします。

f:id:ksby:20170724061949p:plain f:id:ksby:20170724062146p:plain f:id:ksby:20170724062319p:plain f:id:ksby:20170724062428p:plain f:id:ksby:20170724062534p:plain

プロジェクトのルートディレクトリ直下に webpack.config.js というファイルを新規作成し、以下の内容を記述します。

module.exports = {
    entry: {
        "js/app": ["./src/main/assets/js/app.js"]
    },
    output: {
        path: __dirname + "/src/main/resources/static",
        publicPath: "/",
        filename: "[name].js"
    }
};
  • js ファイルは src/main の下に assets/js ディレクトリを作成し、その下に作成します。
  • 今回は動作確認のために app.js を作成します。
  • webpack により処理・生成された js ファイルは src/main/resources/static/js の下に配置します。

src/main の下に assets/js ディレクトリを作成し、src/main/assets/js の下に app.js を作成します。

f:id:ksby:20170724063549p:plain

app.js には以下の内容を記述します。

var $ = require("admin-lte/plugins/jQuery/jquery-2.2.3.min.js");

webpack を起動しやすくするために package.json の scripts に以下の記述を追加します。

  "scripts": {
    ..........,
    "webpack": "webpack"
  },

動作確認します。まずは npm run webpack -- --version コマンドを実行してバージョン番号が表示されることを確認します。

f:id:ksby:20170724064207p:plain

3.3.0 と表示されました。

次に npm run webpack コマンドを実行し、src/main/assets/js/app.js から src/main/resources/static/js/app.js が生成されることを確認します。

f:id:ksby:20170724064532p:plain

コマンドが正常に終了し、src/main/resources/static/js の下に app.js が生成されています。

f:id:ksby:20170724064722p:plain

app.js を開くと以下の内容で始まるファイルでした。

f:id:ksby:20170724064903p:plain

問題なく動作しているようですので、次へ進みます。

browser-sync をインストールする

npm install --save-dev browser-sync コマンドを実行して browser-sync をインストールします。

f:id:ksby:20170724065807p:plain f:id:ksby:20170724065903p:plain f:id:ksby:20170724070002p:plain f:id:ksby:20170724070103p:plain f:id:ksby:20170724070208p:plain f:id:ksby:20170724070311p:plain

package.json の scripts に以下の記述を追加します。

  "scripts": {
    ..........,
    "browser-sync": "browser-sync"
  },

npm run browser-sync -- init コマンドを実行して bs-config.js を生成します。

f:id:ksby:20170724070615p:plain

bs-config.js の以下の点を変更します。

  • "weinre": { "port": 8080 }"weinre": { "port": 9081 } に変更します。
  • "files": false"files": [ "./static/**/*", "./src/main/resources/static/**/*" ] に変更します。
  • "server": false"server": { "baseDir": [ "./static", "./src/main/resources/static" ] }に変更します。
  • "port": 3000"port": 9080 に変更します。
  • "notify": true"notify": false に変更します。
/*
 |--------------------------------------------------------------------------
 | Browser-sync config file
 |--------------------------------------------------------------------------
 |
 | For up-to-date information about the options:
 |   http://www.browsersync.io/docs/options/
 |
 | There are more options than you see here, these are just the ones that are
 | set internally. See the website for more info.
 |
 |
 */
module.exports = {
    "ui": {
        "port": 3001,
        "weinre": {
            "port": 9081
        }
    },
    "files": [
        "./static/**/*",
        "./src/main/resources/static/**/*"
    ],
    "watchEvents": [
        "change"
    ],
    "watchOptions": {
        "ignoreInitial": true
    },
    "server": {
        "baseDir": [
            "./static",
            "./src/main/resources/static"
        ]
    },
    "proxy": false,
    "port": 9080,
    "middleware": false,
    "serveStatic": [],
    "ghostMode": {
        "clicks": true,
        "scroll": true,
        "location": true,
        "forms": {
            "submit": true,
            "inputs": true,
            "toggles": true
        }
    },
    "logLevel": "info",
    "logPrefix": "Browsersync",
    "logConnections": false,
    "logFileChanges": true,
    "logSnippet": true,
    "rewriteRules": [],
    "open": "local",
    "browser": "default",
    "cors": false,
    "xip": false,
    "hostnameSuffix": false,
    "reloadOnRestart": false,
    "notify": false,
    "scrollProportionally": true,
    "scrollThrottle": 0,
    "scrollRestoreTechnique": "window.name",
    "scrollElements": [],
    "scrollElementMapping": [],
    "reloadDelay": 0,
    "reloadDebounce": 0,
    "reloadThrottle": 0,
    "plugins": [],
    "injectChanges": true,
    "startPath": null,
    "minify": true,
    "host": null,
    "localOnly": false,
    "codeSync": true,
    "timestamps": true,
    "clientEvents": [
        "scroll",
        "scroll:element",
        "input:text",
        "input:toggles",
        "form:submit",
        "form:reset",
        "click"
    ],
    "socket": {
        "socketIoOptions": {
            "log": false
        },
        "socketIoClientConfig": {
            "reconnectionAttempts": 50
        },
        "path": "/browser-sync/socket.io",
        "clientPath": "/browser-sync",
        "namespace": "/browser-sync",
        "clients": {
            "heartbeatTimeout": 5000
        }
    },
    "tagNames": {
        "less": "link",
        "scss": "link",
        "css": "link",
        "jpg": "img",
        "jpeg": "img",
        "png": "img",
        "svg": "img",
        "gif": "img",
        "js": "script"
    }
};

package.json の scripts に以下の記述を追加します。

  "scripts": {
    ..........,
    "browser-sync:start": "browser-sync start --config bs-config.js"
  },

プロジェクトのルートディレクトリ直下に static ディレクトリを作成します。今回は Thymeleaf テンプレート前の html ファイルは jar ファイルに入れないようにするために、src/main/resources/static ではなく static の下に作成することにします。

npm run browser-sync:start コマンドを実行してみます。

f:id:ksby:20170724072032p:plain

特にエラーは出ずに起動しているようです。http://localhost:3001 にアクセスすると browser-sync の ui が表示されました。

f:id:ksby:20170724072148p:plain

npm run browser-sync:start コマンドを実行したコマンドプロンプトで Ctrl+C を押して終了すると、ブラウザに以下の画面が表示されました。サーバと同期して動いているようです。

f:id:ksby:20170724072416p:plain

問題なさそうですので、次へ進みます。

webpack + browser-sync 起動用の npm-scripts を作成する

package.json の scripts に以下の記述を追加します。

  "scripts": {
    ..........,
    "webpack": "webpack",
    "webpack:watch": "webpack --watch",
    "browser-sync": "browser-sync",
    "browser-sync:start": "browser-sync start --config bs-config.js",
    "server": "run-p webpack:watch browser-sync:start"
  },
  • "webpack:watch": "webpack --watch" を追加します。
  • "server": "run-p webpack:watch browser-sync:start" を追加します。

npm run server コマンドで webpack と browser-sync が起動して、ファイルが変更されるとブラウザに自動反映されるようにします。

動作確認する

static の下に以下の内容の sample.html を作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
テスト用ページです。<br/>
<span id="sample">xxx</span>
<script src="/js/app.js"></script>
</body>
</html>

src/main/assets/js/app.js を以下の内容に変更します。

var $ = require("admin-lte/plugins/jQuery/jquery-2.2.3.min.js");

$(document).ready(function() {
    $("#sample").text("サンプル");
});

npm run server コマンドを実行します。

f:id:ksby:20170724213650p:plain

ブラウザが起動しますので、http://localhost:9080/sample.html にアクセスしてみます。

f:id:ksby:20170724213858p:plain

sample.html に記述した文字列が表示されており、また app.js に記述した処理も反映されていました。

sample.html を以下の内容に変更してみます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
サンプルですよ?<br/>
<span id="sample">xxx</span>
<script src="/js/app.js"></script>
</body>
</html>

ブラウザを見るとリロードすることなく反映されています。

f:id:ksby:20170724214205p:plain

今度は app.js を以下の内容に修正してみます。

var $ = require("admin-lte/plugins/jQuery/jquery-2.2.3.min.js");

$(document).ready(function() {
    $("#sample").text("app.js を修正してみました");
});

webpack の処理が実行されて src/main/resources/static/js/app.js が作り直されて、

f:id:ksby:20170724214540p:plain

ブラウザの方に手動でリロードすることなく反映されました。

f:id:ksby:20170724214748p:plain

他にも browser-sync はこんなことができるようです。

  • 複数のブラウザ(下の画像では IEChrome)で同じページを見ている時に、ファイルが変更されると全てのブラウザに手動リロードすることなく反映されます。

    f:id:ksby:20170724223414p:plain

  • 複数のブラウザで同じフォームを見ている時に、片方のブラウザ(IE)に入力すると、自動で別のブラウザ(Chrome)にも入力されます。

    f:id:ksby:20170724223724p:plain

  • sample2.html を作成します。その後で sample.html には sample.html → sample2.html へ遷移するリンクを、sample2.html には sample2.html → sample.html へ遷移するリンクを記述してから IEChrome で sample.html を表示した後

    f:id:ksby:20170724224224p:plain

    IE の方のリンクをクリックして sample2.html へ遷移すると、Chrome の方でも sample2.html へ遷移します。

    f:id:ksby:20170724224858p:plain

browser-sync ってすごい面白い! まさか、こんな便利なソフトがあるとは。

他にも browser-sync には proxy の機能もあるようで、Spring Boot の Tomcat と連携して自動リロードもできるのでしょうか。。。? 入力フォームができたら試してみたいと思います。

Ctrl+C を押して webpack と browser-sync を停止します。今回作成した sample.html, sample2.html は commit せずに削除します。

最後に package.json, webpack.config.js, bs-config.js を記載しておきます。

ソースコード

package.json

{
  "name": "boot-npm-geb-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "postinstall": "run-s clean:static-dir copy:all",
    "clean:static-dir": "rimraf src/main/resources/static/*",
    "copy:all": "run-p copy:bootstrap copy:admin-lte copy:font-awesome copy:ionicons",
    "copy:bootstrap": "cpx node_modules/bootstrap/dist/**/* src/main/resources/static/vendor/bootstrap",
    "copy:admin-lte": "cpx node_modules/admin-lte/dist/**/* src/main/resources/static/vendor/admin-lte",
    "copy:font-awesome": "cpx node_modules/font-awesome/{css,fonts}/**/* src/main/resources/static/vendor/font-awesome",
    "copy:ionicons": "cpx node_modules/ionicons/dist/{css,fonts}/**/* src/main/resources/static/vendor/ionicons",
    "webpack": "webpack",
    "webpack:watch": "webpack --watch",
    "browser-sync": "browser-sync",
    "browser-sync:start": "browser-sync start --config bs-config.js",
    "server": "run-p webpack:watch browser-sync:start"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "admin-lte": "^2.3.11",
    "bootstrap": "^3.3.7",
    "font-awesome": "^4.7.0",
    "ionicons": "^3.0.0"
  },
  "devDependencies": {
    "browser-sync": "^2.18.13",
    "cpx": "^1.5.0",
    "npm-run-all": "^4.0.2",
    "rimraf": "^2.6.1",
    "webpack": "^3.3.0"
  }
}

webpack.config.js

module.exports = {
    entry: {
        "js/app": ["./src/main/assets/js/app.js"]
    },
    output: {
        path: __dirname + "/src/main/resources/static",
        publicPath: "/",
        filename: "[name].js"
    }
};

bs-config.js

/*
 |--------------------------------------------------------------------------
 | Browser-sync config file
 |--------------------------------------------------------------------------
 |
 | For up-to-date information about the options:
 |   http://www.browsersync.io/docs/options/
 |
 | There are more options than you see here, these are just the ones that are
 | set internally. See the website for more info.
 |
 |
 */
module.exports = {
    "ui": {
        "port": 3001,
        "weinre": {
            "port": 9081
        }
    },
    "files": [
        "./static/**/*",
        "./src/main/resources/static/**/*"
    ],
    "watchEvents": [
        "change"
    ],
    "watchOptions": {
        "ignoreInitial": true
    },
    "server": {
        "baseDir": [
            "./static",
            "./src/main/resources/static"
        ]
    },
    "proxy": false,
    "port": 9080,
    "middleware": false,
    "serveStatic": [],
    "ghostMode": {
        "clicks": true,
        "scroll": true,
        "location": true,
        "forms": {
            "submit": true,
            "inputs": true,
            "toggles": true
        }
    },
    "logLevel": "info",
    "logPrefix": "Browsersync",
    "logConnections": false,
    "logFileChanges": true,
    "logSnippet": true,
    "rewriteRules": [],
    "open": "local",
    "browser": "default",
    "cors": false,
    "xip": false,
    "hostnameSuffix": false,
    "reloadOnRestart": false,
    "notify": false,
    "scrollProportionally": true,
    "scrollThrottle": 0,
    "scrollRestoreTechnique": "window.name",
    "scrollElements": [],
    "scrollElementMapping": [],
    "reloadDelay": 0,
    "reloadDebounce": 0,
    "reloadThrottle": 0,
    "plugins": [],
    "injectChanges": true,
    "startPath": null,
    "minify": true,
    "host": null,
    "localOnly": false,
    "codeSync": true,
    "timestamps": true,
    "clientEvents": [
        "scroll",
        "scroll:element",
        "input:text",
        "input:toggles",
        "form:submit",
        "form:reset",
        "click"
    ],
    "socket": {
        "socketIoOptions": {
            "log": false
        },
        "socketIoClientConfig": {
            "reconnectionAttempts": 50
        },
        "path": "/browser-sync/socket.io",
        "clientPath": "/browser-sync",
        "namespace": "/browser-sync",
        "clients": {
            "heartbeatTimeout": 5000
        }
    },
    "tagNames": {
        "less": "link",
        "scss": "link",
        "css": "link",
        "jpg": "img",
        "jpeg": "img",
        "png": "img",
        "svg": "img",
        "gif": "img",
        "js": "script"
    }
};

履歴

2015/07/24
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その6 )( URL の決定 )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その5 )( Bootstrap, AdminLTE, Font Awesome, Ionicons のインストール ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 画面の URL を決めます。

参照したサイト・書籍

目次

  1. 画面の URL を決める

手順

画面の URL を決める

各画面の URL は以下のようにします。

画面 アクション URL
入力画面1 初期表示 /inquiry/input/01/
「次へ」ボタンクリック時 /inquiry/input/01/?move=next
入力画面2 初期表示 /inquiry/input/02/
「前の画面へ戻る」ボタンクリック時 /inquiry/input/02/?move=prev
「次へ」ボタンクリック時 /inquiry/input/02/?move=next
入力画面3 初期表示 /inquiry/input/03/
「前の画面へ戻る」ボタンクリック時 /inquiry/input/03/?move=prev
「次へ」ボタンクリック時 /inquiry/input/03/?move=next
確認画面 初期表示 /inquiry/confirm/
入力画面1の項目の「修正する」ボタンクリック時 /inquiry/input/01/
入力画面2の項目の「修正する」ボタンクリック時 /inquiry/input/02/
入力画面3の項目の「修正する」ボタンクリック時 /inquiry/input/03/
「送信する」ボタンクリック時 /inquiry/confirm/send/
完了画面 初期表示 /inquiry/complete/

履歴

2015/07/23
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その5 )( Bootstrap, AdminLTE, Font Awesome, Ionicons のインストール )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その4 )( nodist + Node.js のインストール ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • npm を使用して Bootstrap, AdminLTE, Font Awesome, Ionicons をインストールします。
    • インストール後 src/main/resources/static へ必要なファイルをコピーする npm-scripts も作成します。

参照したサイト・書籍

  1. Purpose of installing bootstrap through npm?
    https://stackoverflow.com/questions/26773767/purpose-of-installing-bootstrap-through-npm

  2. npm でパッケージのバージョン一覧を確認したりバージョンを指定してインストールしたりする方法
    http://phiary.me/npm-package-version-info-install/

  3. npm scriptsを使おう
    http://qiita.com/liply/items/cccc6a7b703c1d3ab04f

  4. npm-scripts で使える便利モジュールたち
    http://qiita.com/mysticatea/items/12bb6579b9155fd74586

  5. cpx と rimraf を試す
    http://akabeko.me/blog/2015/09/cpx-rimraf/

  6. cpx
    https://www.npmjs.com/package/cpx

  7. rimraf
    https://www.npmjs.com/package/rimraf

  8. npm-run-all
    https://www.npmjs.com/package/npm-run-all

  9. npm runコマンドを実行したら警告が出るようになった
    http://qiita.com/isamusuzuki/items/738a2736a746b67bd977

目次

  1. package.json を生成する
  2. Bootstrap をインストールする
  3. AdminLTE をインストールする
  4. Font Awesome をインストールする
  5. Ionicons をインストールする
  6. install 後に node_modules → src/main/resources/static へファイルをコピーする npm-scripts を作成する
  7. AdminLTE の starter.html で確認する
  8. .gitignore を変更する
  9. 最後に

手順

package.json を生成する

  1. npm init -y コマンドを実行して package.json を生成します。

    f:id:ksby:20170722145004p:plain

    今は生成されたままとし、特に変更はしません。

Bootstrap をインストールする

  1. npm info bootstrap versions コマンドを実行してインストール可能な Bootstrap のバージョン一覧を表示します。

    f:id:ksby:20170722150304p:plain

  2. npm install --save bootstrap コマンドを実行して Bootstrap をインストールします。bootstrap@3.3.7 と表示されており、3.3.7 がインストールされました。

    f:id:ksby:20170722150624p:plain

  3. インストール先の node_modules/bootstrap の下を見ると以下のディレクトリ構成になっていました。単に使用したいのであれば dist ディレクトリの下のファイルを使えば良さそうです。

    f:id:ksby:20170722151144p:plain

AdminLTE をインストールする

  1. Google で “npm AdminLTE” で検索すると https://www.npmjs.com/package/admin-lte のページがヒットしました。npm でインストールする時のパッケージ名は admin-lte のようです。

    npm install --save admin-lte コマンドを実行して Bootstrap をインストールします。

    f:id:ksby:20170722152034p:plain

  2. インストール先の node_modules/admin-lte の下を見ると以下のディレクトリ構成になっていました。こちらも単に使用したいのであれば dist ディレクトリの下のファイルを使えば良さそうです。

    f:id:ksby:20170722152414p:plain

    jQuery も node_modules/admin-lte/plugins/jQuery の下に jquery-2.2.3.min.js があります。今回はこのファイルを使用します。

    f:id:ksby:20170722152615p:plain

Font Awesome をインストールする

  1. “npm Font Awesome” で検索すると https://www.npmjs.com/package/font-awesome がヒットしました。

    npm install --save font-awesome コマンドを実行して Font Awesome をインストールします。

    f:id:ksby:20170722174852p:plain

  2. インストール先の node_modules/font-awesome の下を見ると以下のディレクトリ構成になっていました。単に使用したいのであれば css, fonts ディレクトリの下のファイルを使えば良さそうです。

    f:id:ksby:20170722175203p:plain

Ionicons をインストールする

  1. “npm Ionicons” で検索すると https://www.npmjs.com/package/ionicons がヒットしました。

    npm install --save ionicons コマンドを実行して Ionicons をインストールします。

    f:id:ksby:20170722175714p:plain

  2. インストール先の node_modules/font-awesome の下を見ると以下のディレクトリ構成になっていました。単に使用したいのであれば css, fonts ディレクトリの下のファイルを使えば良さそうです(dist に scss 用のファイルとかも入っていて分かりづらいです)。

    f:id:ksby:20170722180247p:plain

install 後に node_modules → src/main/resources/static へファイルをコピーする npm-scripts を作成する

以下のコマンドを実行して npm-scripts を作成する上で便利なパッケージをインストールします。

  • npm install --save-dev cpx
  • npm install --save-dev rimraf
  • npm install --save-dev npm-run-all

package.json の scripts にコピー用の script を定義します。パッケージのファイルは src/main/resources/static/vendor/<パッケージ名>/ の下にコピーします。

  "scripts": {
    ..........
    "postinstall": "run-s clean:static-dir copy:all",
    "clean:static-dir": "rimraf src/main/resources/static/*",
    "copy:all": "run-p copy:bootstrap copy:admin-lte copy:font-awesome copy:ionicons",
    "copy:bootstrap": "cpx node_modules/bootstrap/dist/**/* src/main/resources/static/vendor/bootstrap",
    "copy:admin-lte": "cpx node_modules/admin-lte/dist/**/* src/main/resources/static/vendor/admin-lte",
    "copy:font-awesome": "cpx node_modules/font-awesome/{css,fonts}/**/* src/main/resources/static/vendor/font-awesome",
    "copy:ionicons": "cpx node_modules/ionicons/dist/{css,fonts}/**/* src/main/resources/static/vendor/ionicons"
  },
  • postinstall を追加し、npm install コマンドが実行された後にファイルのコピーを行う処理を記述します。run-s コマンドで clean:static-dir → copy:all の順に script を実行します。
  • clean:static-dir は src/main/resources/static の下のディレクトリ、ファイルを削除します。static ディレクトリ自体は削除しません。
  • copy:all は node_modules の下から必要なファイルを src/main/resources/static の下にコピーします。以下の4つの script を run-p コマンドで並列実行します。
    • copy:bootstrap は node_modules/bootstrap パッケージの下のファイルをコピーします。
    • copy:admin-lte は node_modules/admin-lte パッケージの下のファイルをコピーします。
    • copy:font-awesome は node_modules/font-awesome パッケージの下のファイルをコピーします。
    • copy:ionicons は node_modules/ionicons パッケージの下のファイルをコピーします。

npm install コマンドを実行してみます。

f:id:ksby:20170723004623p:plain f:id:ksby:20170723004808p:plain

The node binary used for scripts is C:\Nodist\bin\node.exe but npm is using C:\Nodist\v-x64\6.11.1\node.exe itself. Use the–scripts-prepend-node-pathoption to include the path for the node binary npm was executed with. というメッセージが大量に出力されました(というより npm install コマンドでパッケージをインストールしている時から出ていて WARN だったので気にしていなかっただけでしたが)。さすがに量が多いので出力されないようにする方法があるか確認します。

Web で調べたところ npm runコマンドを実行したら警告が出るようになった に解決方法が記載されていました。npm config set scripts-prepend-node-path true コマンドを実行します。

再度 npm install コマンドを実行します。

f:id:ksby:20170723005544p:plain f:id:ksby:20170723005653p:plain

まだ npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules\chokidar\node_modules\fsevents): というメッセージが出ます。

Web で調べたところ fsevents は Mac でしか使用できないパッケージのためメッセージが出力されていますが、WARN なので気にしなければよいようです。

src/main/resources/static の下を見ると以下の画像のようにディレクトリが作成されていました。

f:id:ksby:20170723011220p:plain

AdminLTE の starter.html で確認する

node_modules/admin-lte の下に starter.html がありますので、それを src/main/resources/static の下にコピーした後、以下の点を変更します。

  • <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"><link rel="stylesheet" href="/vendor/bootstrap/css/bootstrap.min.css">
  • <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"><link rel="stylesheet" href="/vendor/font-awesome/css/font-awesome.min.css">
  • <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css"><link rel="stylesheet" href="/vendor/ionicons/css/ionicons.min.css">
  • <link rel="stylesheet" href="dist/css/AdminLTE.min.css"><link rel="stylesheet" href="/vendor/admin-lte/css/AdminLTE.min.css">
  • <link rel="stylesheet" href="dist/css/skins/skin-blue.min.css"><link rel="stylesheet" href="/vendor/admin-lte/css/skins/skin-blue.min.css">
  • 以下の2行はコメントアウトします。
    • <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    • <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
  • body タグ内の <img src="dist/img/...<img src="/vendor/admin-lte/img/...

head タグ内は以下のようになります。

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>AdminLTE 2 | Starter</title>
  <!-- Tell the browser to be responsive to screen width -->
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
  <!-- Bootstrap 3.3.6 -->
  <link rel="stylesheet" href="/vendor/bootstrap/css/bootstrap.min.css">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="/vendor/font-awesome/css/font-awesome.min.css">
  <!-- Ionicons -->
  <link rel="stylesheet" href="/vendor/ionicons/css/ionicons.min.css">
  <!-- Theme style -->
  <link rel="stylesheet" href="/vendor/admin-lte/css/AdminLTE.min.css">
  <!-- AdminLTE Skins. We have chosen the skin-blue for this starter
        page. However, you can choose any other skin. Make sure you
        apply the skin class to the body tag so the changes take effect.
  -->
  <link rel="stylesheet" href="/vendor/admin-lte/css/skins/skin-blue.min.css">

  <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  <!--&lt;!&ndash;[if lt IE 9]>-->
  <!--<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>-->
  <!--<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>-->
  <!--<![endif]&ndash;&gt;-->
</head>

bootRun タスクを実行して Tomcat を起動した後、http://localhost:8080/starter.html にアクセスすると画面が表示されました。

f:id:ksby:20170723013450p:plain

Tomcat を停止します。

.gitignore を変更する

  1. commit する前に .gitignore を以下の方針で変更します。

    • node_modules は commit の対象にしません。
    • src/main/resources/static も commit の対象にしません。
    • npm 実行時にエラーが出ると出力される npm-debug.log も commit の対象にしません。

    .gitignore を リンク先の内容 に変更します。

    commit すると変更した .gitignore と、生成した package.json だけでした。npm install コマンドを実行すれば必要なファイルがインストール + コピーされます。

最後に

npm + npm-scripts が便利ですね。最初 Node.js + npm 関連を調べた時は最近の流行りは grunt, gulp ではなく webpack になったというような記事を見ていたので、npm でインストールした Bootstrap の css ファイル等を src/main/resources/static の下にコピーしたい場合にも webpack でやるのかな、と思って試行錯誤していたのですが(ファイルをコピーするための copy-webpack-plugin は見つけました)、単なるコピーは npm-scripts の方が楽でした。

現時点での感想として、

  • npm-scripts と webpack を必要に応じて使い分けるのが良さそう。
  • コピーするだけのような簡単な処理だったりコマンド実行するような場合には npm-scripts で。
  • 自分で js ファイルを実装して、実行用に1つにまとめるような場合には webpack で。
  • SPA で js ファイル以外に css や html のファイルも1つにまとめる場合も webpack で。
  • Gulpで始めるwebpack 3入門 という記事も見かけました。どうも大規模開発になったら webpack に gulp を組み合わせるといいらしいですが、今の自分ではその境地には至れず。。。 npm-scripts + webpack で進めて、必要性を感じたら gulp を使う流れかな? 今は無理に手を出さないことにします。

今回の作業で生成・変更した package.json の最終版を リンク先 に記載しておきます。

ソースコード

.gitignore

# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
**/bin/
**/gen/

# Local configuration file (sdk path, etc)
local.properties

# Eclipse project files
.classpath
.project

# Proguard folder generated by Eclipse
**/proguard/

# Intellij project files
*.iml
*.ipr
*.iws
**/.idea/
**/out/
**/src/main/resources/static

#Gradle
.gradletasknamecache
**/.gradle/
**/build/
**/bin/

#Node.js
**/node_modules/
npm-debug.log
  • **/src/main/resources/static を追加します。
  • #Node.js から下の行を追加します。

package.json

{
  "name": "boot-npm-geb-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "postinstall": "run-s clean:static-dir copy:all",
    "clean:static-dir": "rimraf src/main/resources/static/*",
    "copy:all": "run-p copy:bootstrap copy:admin-lte copy:font-awesome copy:ionicons",
    "copy:bootstrap": "cpx node_modules/bootstrap/dist/**/* src/main/resources/static/vendor/bootstrap",
    "copy:admin-lte": "cpx node_modules/admin-lte/dist/**/* src/main/resources/static/vendor/admin-lte",
    "copy:font-awesome": "cpx node_modules/font-awesome/{css,fonts}/**/* src/main/resources/static/vendor/font-awesome",
    "copy:ionicons": "cpx node_modules/ionicons/dist/{css,fonts}/**/* src/main/resources/static/vendor/ionicons"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "admin-lte": "^2.3.11",
    "bootstrap": "^3.3.7",
    "font-awesome": "^4.7.0",
    "ionicons": "^3.0.0"
  },
  "devDependencies": {
    "cpx": "^1.5.0",
    "npm-run-all": "^4.0.2",
    "rimraf": "^2.6.1"
  }
}

履歴

2015/07/23
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その4 )( nodist + Node.js のインストール )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その3 )( Project の作成2 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。

参照したサイト・書籍

  1. Node.js
    https://nodejs.org/ja/

  2. nodist
    https://github.com/marcelklehr/nodist

  3. nodistでNode.jsをバージョン管理
    http://qiita.com/satoyan419/items/56e0b5f35912b9374305

  4. nodist 〜 Node.jsのバージョンを管理する for Windows
    http://tech.pjin.jp/blog/2016/12/12/how_to_use_nodist/

目次

  1. nodist をインストールする
  2. Node.js をインストールする

手順

nodist をインストールする

  1. https://github.com/marcelklehr/nodist/releases から NodistSetup-v0.8.8.exe をダウンロードします。

  2. NodistSetup-v0.8.8.exe を実行します。

  3. 「Welcome to Nodist Setup」画面が表示されます。「Next >」ボタンをクリックします。

  4. 「License Agreement」画面が表示されます。「I Agree」ボタンをクリックします。

  5. 「Choose Install Location」画面が表示されます。「Destination Folder」を C:\Nodist へ変更した後、「Install」ボタンをクリックします。

  6. インストールが実行されます。完了すると「Completing Nodist Setup」画面が表示されますので、「Finish」ボタンをクリックします。

  7. コマンドプロンプトを起動し、nodist -v コマンドを実行してバージョン番号が表示されることを確認します。

    f:id:ksby:20170722140816p:plain

Node.js をインストールする

  1. nodist dist コマンドを実行してインストール可能な Node.js のバージョン一覧を表示します。

    f:id:ksby:20170722141120p:plain f:id:ksby:20170722141310p:plain

    https://nodejs.org/ja/ を見ると現在の推奨版は 6.11.1 ですので、6.11.1 をインストールします。

    f:id:ksby:20170722141605p:plain

  2. 以下の画像のコマンドを実行して 6.11.1 をインストールした後、Node.js のカレントのバージョンを 6.11.1 へ切り替えます。

    f:id:ksby:20170722142120p:plain

  3. npm はアップデートしても 4.0.5 のままでした。

    f:id:ksby:20170722142440p:plain

履歴

2015/07/22
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その3 )( Project の作成2 )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その2 )( Project の作成 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Project の作成
    • 前回長くなったので2回に分けています。今回は前回からの続きです。

参照したサイト・書籍

  1. DBCP - validationQuery for different Databases
    https://stackoverflow.com/questions/10684244/dbcp-validationquery-for-different-databases

    • H2 Database の validationQuery を調べた時に参照しました。H2 Database 以外の validationQuery も記載されています。ほとんどの DB で select 1 なんですね。

目次

  1. ksbysample-webapp-lending からファイルをコピーする(その2)
  2. 「Spring Configuration Check」のメッセージが表示されないようにする
  3. Tomcat が起動することを確認する

手順

ksbysample-webapp-lending からファイルをコピーする(その2)

  1. ksbysample-webapp-lending から以下のファイルをコピーします。

    ※リンクのあるファイルはリンク先の内容に変更します。

    ■src/main/resources

  2. ファイルコピー後は以下のディレクトリ構成になります。

    f:id:ksby:20170722071222p:plain f:id:ksby:20170722071357p:plain

「Spring Configuration Check」のメッセージが表示されないようにする

  1. IntelliJ IDEA を再起動します。

  2. 画面右下に「Spring Configuration Check」のメッセージが表示されます。

    f:id:ksby:20170722072847p:plain

    下矢印ボタンを押してメッセージの全てを表示した後、「boot-npm-geb-sample_main」リンクをクリックします。

    f:id:ksby:20170722073021p:plain

  3. 「Project Structure」ダイアログが表示されます。「+」ボタンをクリックして下に表示されているファイルを追加します。

    f:id:ksby:20170722073405p:plain

  4. 「New Application Context」ダイアログが表示されます。以下の画像のファイルをチェックした後、「OK」ボタンをクリックします。

    f:id:ksby:20170722073637p:plain

  5. 「Project Structure」ダイアログに戻ると以下の画像のように表示されます。下の画像では下半分を表示していませんが、まだこの段階では警告メッセージは消えていません。

    f:id:ksby:20170722073829p:plain

  6. 再び IntelliJ IDEA を再起動して、画面右下に「Spring Configuration Check」のメッセージが表示されないことを確認します。この後「Project Structure」ダイアログを表示すると警告メッセージは消えていました。

Tomcat が起動することを確認する

  1. Gradle Tool Window から bootRun タスクを実行します。Tomcat が起動して “Started Application in …” のログが出力されることを確認します。

    f:id:ksby:20170722075704p:plain

  2. Tomcat を停止します。

ソースコード

application.properties

doma.dialect=org.seasar.doma.jdbc.dialect.H2Dialect

spring.datasource.tomcat.url=jdbc:h2:mem:bootnpmgebdb
spring.datasource.tomcat.username=sa
spring.datasource.tomcat.password=
spring.datasource.tomcat.driverClassName=org.h2.Driver
spring.datasource.tomcat.initialSize=1
spring.datasource.tomcat.maxActive=1
spring.datasource.tomcat.maxIdle=1
spring.datasource.tomcat.minIdle=1
spring.datasource.tomcat.testOnBorrow=true
spring.datasource.tomcat.validationQuery=select 1
spring.datasource.tomcat.validationQueryTimeout=5
spring.datasource.tomcat.removeAbandoned=true
spring.datasource.tomcat.removeAbandonedTimeout=30
spring.datasource.tomcat.jdbc-interceptors=SlowQueryReport(threshold=5000)
# spring.datasource.jmx-enabled は spring.datasource.tomcat.jmx-enabled と書かないこと。
# spring.datasource.tomcat.jmx-enabled だと機能しない。
spring.datasource.jmx-enabled=true

spring.session.store-type=hash_map

spring.freemarker.cache=true
spring.freemarker.settings.number_format=computer
spring.freemarker.charset=UTF-8
spring.freemarker.enabled=false
spring.freemarker.prefer-file-system-access=false

spring.thymeleaf.mode=HTML

logging.level.root=INFO
logging.level.org.seasar.doma=ERROR

application-develop.properties

spring.mail.host=localhost
spring.mail.port=25

# Spring MVC
logging.level.org.springframework.web=DEBUG
# log4jdbc-log4j2
logging.level.jdbc.sqlonly=DEBUG
logging.level.jdbc.sqltiming=INFO
logging.level.jdbc.audit=INFO
logging.level.jdbc.resultset=ERROR
logging.level.jdbc.resultsettable=ERROR
logging.level.jdbc.connection=DEBUG

application-product.properties

server.tomcat.basedir=C:/webapps/boot-npm-geb-sample
logging.file=${server.tomcat.basedir}/logs/boot-npm-geb-sample.log
slowquery.logging.file=${server.tomcat.basedir}/logs/slow-query.log

spring.autoconfigure.exclude=com.integralblue.log4jdbc.spring.Log4jdbcAutoConfiguration
spring.datasource.tomcat.initialSize=1
spring.datasource.tomcat.maxActive=1
spring.datasource.tomcat.maxIdle=1
spring.datasource.tomcat.minIdle=1

spring.mail.host=localhost
spring.mail.port=25

application-unittest.properties

spring.autoconfigure.exclude=com.integralblue.log4jdbc.spring.Log4jdbcAutoConfiguration

spring.mail.host=localhost
spring.mail.port=25

logging.level.root=OFF

applicationContext-develop.xml

    <aop:config>
        <aop:pointcut id="pointcutService" expression="execution(* ksbysample.webapp.bootnpmgeb..*Service.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcutService"/>
    </aop:config>
  • execution(* ksbysample.webapp.lending..*Service.*(..))execution(* ksbysample.webapp.bootnpmgeb..*Service.*(..)) に変更します。

applicationContext-product.xml

    <aop:config>
        <aop:pointcut id="pointcutService" expression="execution(* ksbysample.webapp.bootnpmgeb..*Service.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcutService"/>
    </aop:config>
  • execution(* ksbysample.webapp.lending..*Service.*(..))execution(* ksbysample.webapp.bootnpmgeb..*Service.*(..)) に変更します。

applicationContext-unittest.xml

    <aop:config>
        <aop:pointcut id="pointcutService" expression="execution(* ksbysample.webapp.bootnpmgeb..*Service.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcutService"/>
    </aop:config>
  • execution(* ksbysample.webapp.lending..*Service.*(..))execution(* ksbysample.webapp.bootnpmgeb..*Service.*(..)) に変更します。

messages_ja_JP.properties

  • 中は空にします。

履歴

2015/07/22
初版発行。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その2 )( Project の作成 )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その1 )( 概要 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Project の作成

参照したサイト・書籍

  1. spring-projects/spring-session - Add @EnableSpringHttpSession
    https://github.com/spring-projects/spring-session/issues/231

目次

  1. GitHub 上で ksbysample-boot-miscellaneous レポジトリを新規作成してクローンする
  2. IntelliJ IDEA の起動し、Project を新規作成する
  3. build.gradle を変更する
  4. Gradle の設定を変更する
  5. Project language level を SDK default に変更する
  6. JUnit によるテスト実行時の spring.profiles.active を設定する
  7. src/main/resources の下に static, templates ディレクトリを作成する
  8. ksbysample-webapp-lending からファイルをコピーする(その1)
  9. 続く。。。

手順

GitHub 上で ksbysample-boot-miscellaneous レポジトリを新規作成してクローンする

  1. GitHub 上で ksbysample-boot-miscellaneous レポジトリを新規作成します。

  2. SourceTree で作成した ksbysample-boot-miscellaneous レポジトリを C:\project-springboot\ksbysample-boot-miscellaneous へクローンします。

    f:id:ksby:20170721055314p:plain

  3. C:\project-springboot\ksbysample-boot-miscellaneous の下に .gitignore を新規作成し、リンク先の内容 に変更します。この .gitignore は Spring Integration のサンプルを作成している ksbysample-boot-integration レポジトリ のものをコピーしたものです。

  4. develop ブランチ、feature/1-issue ブランチを作成します。

IntelliJ IDEA の起動し、Project を新規作成する

  1. IntelliJ IDEA を起動します。他の Project を開いている場合には、メイン画面のメニューから「File」->「Close Project」を選択して Project をクローズします。

  2. 「Welcome to IntelliJ IDEA」画面が表示されます。画面中央の「Create New Project」をクリックします。

  3. 「New Project」画面が表示されます。画面左側のリストから「Gradle」を選択し、画面右側は以下の画像の状態にして「Next」ボタンをクリックします。

    f:id:ksby:20170721062816p:plain

  4. GroupId、ArtifactId、Version を入力する画面が表示されます。以下の点を変更した後、「Next」ボタンをクリックします。

    • 「GroupdId」に “project” を入力します。
    • 「ArtifactId」に “boot-npm-geb-sample” を入力します。

    f:id:ksby:20170721063040p:plain

  5. Gradle の設定をする画面が表示されます。何も変更せず「Next」ボタンをクリックします。

    f:id:ksby:20170721063319p:plain

  6. Project name、Project location を入力する画面が表示されます。以下の点を変更した後、「Finish」ボタンをクリックします。

    • 「Project location」に “C:\project-springboot\ksbysample-boot-miscellaneous\boot-npm-geb-sample” を入力します。

    f:id:ksby:20170721063522p:plain

  7. 「Directory Does Not Exist」ダイアログが表示されますので「OK」ボタンをクリックします。

    f:id:ksby:20170721064011p:plain

  8. IntelliJ IDEA のメイン画面が表示されて Project Tool Window に以下のディレクトリ構造が表示されます。

    ※src/main/java や src/test/java に以下の画像のように色が付いていることを確認します。

    f:id:ksby:20170721064632p:plain

build.gradle を変更する

  1. build.gradle を リンク先の内容 に変更します。

  2. コマンドプロンプトを起動して gradlew wrapper コマンドを実行し、gradle を 3.5 へバージョンアップします。

    f:id:ksby:20170721070921p:plain

  3. Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

Gradle の設定を変更する

  1. メイン画面のメニューから「File」->「Settings…」を選択して「Settings」ダイアログを表示します。

  2. 画面左上の検索フィールドに “Gradle” と入力して画面左側のツリーから「Build, Execution, Deployment」-「Build Tools」-「Gradle」を選択した後、以下の点を変更します。

    • 「Create directories for empty content roots automatically」をチェックします。
    • 画面右側の「Gradle JVM」で「Use Project JDK」を選択します。

    f:id:ksby:20170722000056p:plain

  3. 「OK」ボタンをクリックして「Settings」ダイアログを閉じます。

  4. 再度 Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。src/man/groovy, src/test/groovy ディレクトリが自動作成されます。

    f:id:ksby:20170722084510p:plain

Project language level を SDK default に変更する

  1. メイン画面のメニューから「File」->「Project Structure…」を選択して「Project Structure」ダイアログを表示します。

  2. 画面左側のツリーから「Project Settings」-「Project」を選択し、画面右側で「Project language level」の設定を「SDK default」に変更します。

    f:id:ksby:20170721210919p:plain

  3. 「OK」ボタンをクリックして「Project Structure」ダイアログを閉じます。

JUnit によるテスト実行時の spring.profiles.active を設定する

  1. メイン画面のメニューから「Run」->「Edit Configurations…」を選択します。

  2. 「Run/Debug Configuraitons」ダイアログが表示されます。左側のツリーで「Defaults」-「JUnit」を選択した後、右側の画面の「VM options」の末尾に -Dspring.profiles.active=unittest を追加します。

    f:id:ksby:20170721211628p:plain

  3. 「OK」ボタンをクリックして「Run/Debug Configuraitons」ダイアログを閉じます。

src/main/resources の下に static, templates ディレクトリを作成する

  1. Project Tool Window で src/main/resources の下に static, templates ディレクトリを作成します。

ksbysample-webapp-lending からファイルをコピーする

  1. 以下の画像の階層のパッケージを作成します。

    f:id:ksby:20170722085123p:plain

  2. ksbysample-webapp-lending から以下のファイルをコピーします。

    ※リンクのあるファイルはリンク先の内容に変更します。

    ■src/main/java

続く。。。

長くなったので2回に分けます。

ソースコード

.gitignore

# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
**/bin/
**/gen/

# Local configuration file (sdk path, etc)
local.properties

# Eclipse project files
.classpath
.project

# Proguard folder generated by Eclipse
**/proguard/

# Intellij project files
*.iml
*.ipr
*.iws
**/.idea/
**/out/

#Gradle
.gradletasknamecache
**/.gradle/
**/build/
**/bin/

build.gradle

group 'ksbysample'
version '1.5.4-RELEASE'

buildscript {
    ext {
        springBootVersion = '1.5.4.RELEASE'
    }
    repositories {
        mavenCentral()
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        // for Error Prone ( http://errorprone.info/ )
        classpath("net.ltgt.gradle:gradle-errorprone-plugin:0.0.10")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'groovy'
apply plugin: 'net.ltgt.errorprone'
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'

sourceCompatibility = 1.8
targetCompatibility = 1.8

task wrapper(type: Wrapper) {
    gradleVersion = '3.5'
}

[compileJava, compileTestGroovy, compileTestJava]*.options*.compilerArgs = ['-Xlint:all,-options,-processing,-path']
compileJava.options.compilerArgs += ['-Xep:RemoveUnusedImports:WARN']

// for Doma 2
// JavaクラスとSQLファイルの出力先ディレクトリを同じにする
processResources.destinationDir = compileJava.destinationDir
// コンパイルより前にSQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する
compileJava.dependsOn processResources

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

configurations {
    // for Doma 2
    domaGenRuntime
}

checkstyle {
    configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml")
    toolVersion = '8.0'
    sourceSets = [project.sourceSets.main]
}

findbugs {
    toolVersion = '3.0.1'
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    effort = "max"
    excludeFilter = file("${rootProject.projectDir}/config/findbugs/findbugs-exclude.xml")
}

tasks.withType(FindBugs) {
    // Gradle 3.3以降 + FindBugs Gradle Plugin を組み合わせると、"The following errors occurred during analysis:"
    // の後に "Cannot open codebase filesystem:..." というメッセージが大量に出力されるので、以下の doFirst { ... }
    // のコードを入れることで出力されないようにする
    doFirst {
        def fc = classes
        if (fc == null) {
            return
        }
        fc.exclude '**/*.properties'
        fc.exclude '**/*.xml'
        fc.exclude '**/META-INF/**'
        fc.exclude '**/static/**'
        fc.exclude '**/templates/**'
        classes = files(fc.files)
    }
    reports {
        xml.enabled = false
        html.enabled = true
    }
}

pmd {
    toolVersion = "5.8.1"
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    consoleOutput = true
    ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml")
    ruleSets = []
}

repositories {
    mavenCentral()
}

dependencyManagement {
    imports {
        // BOM は https://repo.spring.io/release/io/spring/platform/platform-bom/Brussels-SR3/
        // の下を見ること
        mavenBom("io.spring.platform:platform-bom:Brussels-SR3") {
            bomProperty 'guava.version', '22.0'
            bomProperty 'thymeleaf.version', '3.0.6.RELEASE'
            bomProperty 'thymeleaf-extras-springsecurity4.version', '3.0.2.RELEASE'
            bomProperty 'thymeleaf-layout-dialect.version', '2.2.2'
            bomProperty 'thymeleaf-extras-data-attribute.version', '2.0.1'
            bomProperty 'thymeleaf-extras-java8time.version', '3.0.0.RELEASE'
        }
    }
}

bootRepackage {
    mainClass = 'ksbysample.webapp.lending.Application'
}

dependencies {
    def spockVersion = "1.1-groovy-2.4"
    def domaVersion = "2.16.1"
    def lombokVersion = "1.16.18"
    def errorproneVersion = "2.0.15"
    def powermockVersion = "1.7.0"

    // dependency-management-plugin によりバージョン番号が自動で設定されるもの
    // Appendix A. Dependency versions ( http://docs.spring.io/platform/docs/current/reference/htmlsingle/#appendix-dependency-versions ) 参照
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf") {
        exclude group: "org.codehaus.groovy", module: "groovy"
    }
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("org.springframework.boot:spring-boot-starter-freemarker")
    compile("org.springframework.boot:spring-boot-starter-mail")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.boot:spring-boot-devtools")
    compile("org.springframework.session:spring-session")
    compile("com.google.guava:guava")
    compile("org.apache.commons:commons-lang3")
    compile("org.codehaus.janino:janino")
    compile("com.h2database:h2")
    testCompile("org.springframework.boot:spring-boot-starter-test")
    testCompile("org.springframework.security:spring-security-test")
    testCompile("org.yaml:snakeyaml")
    testCompile("org.mockito:mockito-core")

    // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの
    compile("com.integralblue:log4jdbc-spring-boot-starter:1.0.1")
    testCompile("org.dbunit:dbunit:2.5.3")
    testCompile("com.icegreen:greenmail:1.5.5")
    testCompile("org.assertj:assertj-core:3.8.0")
    testCompile("org.spockframework:spock-core:${spockVersion}")
    testCompile("org.spockframework:spock-spring:${spockVersion}")
    testCompile("com.google.code.findbugs:jsr305:3.0.2")

    // for lombok
    compileOnly("org.projectlombok:lombok:${lombokVersion}")
    testCompileOnly("org.projectlombok:lombok:${lombokVersion}")

    // for Doma
    compile("org.seasar.doma:doma:${domaVersion}")
    domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")

    // for Error Prone ( http://errorprone.info/ )
    errorprone("com.google.errorprone:error_prone_core:${errorproneVersion}")
    compileOnly("com.google.errorprone:error_prone_annotations:${errorproneVersion}")

    // PowerMock
    testCompile("org.powermock:powermock-module-junit4:${powermockVersion}")
    testCompile("org.powermock:powermock-api-mockito:${powermockVersion}")
}

bootRun {
    jvmArgs = ['-Dspring.profiles.active=develop']
}

test {
    jvmArgs = ['-Dspring.profiles.active=unittest']
}

// for Doma-Gen
task domaGen {
    doLast {
        // まず変更が必要なもの
        def rootPackageName = 'ksbysample.webapp.bootnpmgeb'
        def daoPackagePath = 'src/main/java/ksbysample/webapp/bootnpmgeb/dao'
        def dbUrl = 'jdbc:h2:mem:bootnpmgebdb'
        def dbUser = 'sa'
        def dbPassword = ''
        def tableNamePattern = '.*'
        // おそらく変更不要なもの
        def importOfComponentAndAutowiredDomaConfig = "${rootPackageName}.util.doma.ComponentAndAutowiredDomaConfig"
        def workDirPath = 'work'
        def workDaoDirPath = "${workDirPath}/dao"

        // 作業用ディレクトリを削除する
        clearDir("${workDirPath}")

        // 現在の Dao インターフェースのバックアップを取得する
        copy() {
            from "${daoPackagePath}"
            into "${workDaoDirPath}/org"
        }

        // Dao インターフェース、Entity クラスを生成する
        ant.taskdef(resource: 'domagentask.properties',
                classpath: configurations.domaGenRuntime.asPath)
        ant.gen(url: "${dbUrl}", user: "${dbUser}", password: "${dbPassword}", tableNamePattern: "${tableNamePattern}") {
            entityConfig(packageName: "${rootPackageName}.entity", useListener: false)
            daoConfig(packageName: "${rootPackageName}.dao")
            sqlConfig()
        }

        // 生成された Dao インターフェースを作業用ディレクトリにコピーし、
        // @ComponentAndAutowiredDomaConfig アノテーションを付加する
        copy() {
            from "${daoPackagePath}"
            into "${workDaoDirPath}/replace"
            filter {
                line ->
                    line.replaceAll('import org.seasar.doma.Dao;', "import ${importOfComponentAndAutowiredDomaConfig};\nimport org.seasar.doma.Dao;")
                            .replaceAll('@Dao', '@Dao\n@ComponentAndAutowiredDomaConfig')
            }
        }

        // @ComponentAndAutowiredDomaConfig アノテーションを付加した Dao インターフェースを
        // dao パッケージへ戻す
        copy() {
            from "${workDaoDirPath}/replace"
            into "${daoPackagePath}"
        }

        // 元々 dao パッケージ内にあったファイルを元に戻す
        copy() {
            from "${workDaoDirPath}/org"
            into "${daoPackagePath}"
        }

        // 作業用ディレクトリを削除する
        clearDir("${workDirPath}")
    }
}

/* -----------------------------------------------------------------------------
 * メソッド定義部
 ---------------------------------------------------------------------------- */

void clearDir(String dirPath) {
    delete dirPath
}

Application.java

package ksbysample.webapp.bootnpmgeb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * ???
 */
@ImportResource("classpath:applicationContext-${spring.profiles.active}.xml")
@SpringBootApplication(exclude = {JpaRepositoriesAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@ComponentScan("ksbysample")
@EnableSpringHttpSession
public class Application {

    ..........
  • @EnableRedisHttpSession@EnableSpringHttpSession に変更します。
  • @EnableGlobalMethodSecurity(prePostEnabled = true) を削除します。

ControllerAndEventNameLogger.java

    @Around(value = "execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..)) && @annotation(loggingEventName)"
            , argNames = "pjp, loggingEventName")
    public Object logginControllerAndEventName(ProceedingJoinPoint pjp, LoggingEventName loggingEventName)
            throws Throwable {
        ..........
  • execution(* ksbysample.webapp.lending.web..*.*(..))execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..)) に変更します。

MethodLogger.java

    @SuppressWarnings({"PMD.UnusedPrivateMethod"})
    @Pointcut("execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..))"
            + "&& @within(org.springframework.stereotype.Controller)")
    private void pointcutControllerMethod() {
    }

    @SuppressWarnings({"PMD.UnusedPrivateMethod"})
    @Pointcut("execution(* ksbysample.webapp.bootnpmgeb.service..*.*(..))"
            + "&& @within(org.springframework.stereotype.Service)")
    private void pointcutServiceMethod() {
    }
  • execution(* ksbysample.webapp.lending.web..*.*(..))execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..)) に変更します。
  • execution(* ksbysample.webapp.lending.service..*.*(..))execution(* ksbysample.webapp.bootnpmgeb.service..*.*(..)) に変更します。

RequestAndResponseLogger.java

    private static final String POINTCUT_ALL_CLASS_AND_METHOD_UNDER_APPLICATION_PACKAGE
            = "execution(* ksbysample.webapp.bootnpmgeb..*.*(..))";
  • execution(* ksbysample.webapp.lending..*.*(..))execution(* ksbysample.webapp.bootnpmgeb..*.*(..)) に変更します。

ApplicationConfig.java

package ksbysample.webapp.bootnpmgeb.config;

import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import javax.sql.DataSource;

/**
 * ???
 */
@Configuration
public class ApplicationConfig {

    private final MessageSource messageSource;

    /**
     * @param messageSource {@link MessageSource} bean
     */
    public ApplicationConfig(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    /**
     * Controller クラスで直接 {@link Validator} を呼び出すために Bean として定義している
     * また Hibernate Validator のメッセージを ValidationMessages.properties ではなく
     * messages.properties に記述できるようにするためにも使用している
     *
     * @return new {@link LocalValidatorFactoryBean}
     */
    @Bean
    public Validator mvcValidator() {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        localValidatorFactoryBean.setValidationMessageSource(this.messageSource);
        return localValidatorFactoryBean;
    }

    /**
     * @return Tomcat JDBC Connection Pool の DataSource オブジェクト
     */
    @Bean
    @ConfigurationProperties("spring.datasource.tomcat")
    public DataSource dataSource() {
        return DataSourceBuilder.create()
                .type(org.apache.tomcat.jdbc.pool.DataSource.class)
                .build();
    }

}
  • 以下の Bean のみ残します。
    • mvcValidator Bean
    • dataSource Bean

WebSecurityConfig.java

package ksbysample.webapp.bootnpmgeb.config;

import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * ???
 */
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します
                // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します
                // .antMatchers("/country/**").permitAll()
                //
                // この Web アプリケーションでは Spring Security を CSRF対策で使用したいだけなので、
                // 全ての URL を認証の対象外にする
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated();
    }

}

履歴

2015/07/22
初版発行。

Java SE を 8u131 → 8u141 へ、IntelliJ IDEA を 2017.1.5 → 2017.2 へ、Git for Windows を 2.13.2 → 2.13.3 へバージョンアップ

※ksbysample-webapp-lending プロジェクトを開いた状態でバージョンアップしています。

Java SE を 8u131 → 8u141 へバージョンアップする

  1. OracleJava SE Downloads を見ると 8u141 がダウンロードできるようになっていました。以下のページに説明があります。

    8u141 へバージョンアップします。

  2. jdk-8u141-windows-x64.exe をダウンロードして C:\Java\jdk1.8.0_141 へインストールした後、環境変数 JAVA_HOME のパスを C:\Java\jdk1.8.0_141 へ変更します。

    コマンドプロンプトから java -version を実行し、1.8.0_141 に変更されていることを確認します。

    f:id:ksby:20170720021345p:plain

  3. IntelliJ IDEA を再起動した後、プロジェクトで使用する Java SE を 8u141 へ変更します。

  4. 開いているプロジェクトを閉じて「Welcome to IntelliJ IDEA」ダイアログを表示します。

  5. ダイアログ下部の「Configure」-「Project Defaults」-「Project Structure」を選択します。

    f:id:ksby:20170720021936p:plain

  6. 「Default Project Structure」ダイアログが表示されます。画面左側で「Project Settings」-「Project」を選択後、画面右側の「Project SDK」の「New…」ボタンをクリックし、表示されるメニューから「JDK」を選択します。

    f:id:ksby:20170720022154p:plain

  7. 「Select Home Directory for JDK」ダイアログが表示されます。今回も環境変数 JAVA_HOME のディレクトリが選択された状態で表示されませんでした。C:\Java\jdk1.8.0_141 を選択した後、「OK」ボタンをクリックします。

    f:id:ksby:20170720022715p:plain

  8. 「Default Project Structure」ダイアログに戻るので、今度は「Project SDK」の「Edit」ボタンをクリックします。

    f:id:ksby:20170720023058p:plain

  9. 画面左側で「Platform Settings」-「SDKs」が選択された状態になるので、画面右上の入力フィールドで “1.8” → “1.8.0_141” へ変更します。

    f:id:ksby:20170720023324p:plain

  10. 次に中央のリストから「1.8.0_131」を選択した後、リストの上の「-」ボタンをクリックして削除します。

    f:id:ksby:20170720023536p:plain

  11. 「OK」ボタンをクリックして「Default Project Structure」ダイアログを閉じます。

  12. 「Welcome to IntelliJ IDEA」ダイアログに戻ったら、ksbysample-webapp-lending プロジェクトを開きます。

  13. IntelliJ IDEA のメイン画面が開いたら、メニューから「File」-「Project Structure…」を選択します。

  14. 「Project Structure」ダイアログが表示されます。以下の画像の状態になっているので、

    f:id:ksby:20170720023851p:plain

    「Project SDK」と「Project language level」を選択し直します。

    f:id:ksby:20170720024059p:plain

  15. 「OK」ボタンをクリックして「Project Structure」ダイアログを閉じます。

  16. メイン画面に戻ると画面右下に「Indexing…」の表示が出るので、終了するまで待ちます。

    f:id:ksby:20170720024303p:plain

  17. clean タスク実行 → Rebuild Project 実行 → build タスクを実行して、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。

    f:id:ksby:20170720025235p:plain

  18. Project Tool Window で src/test を選択した後、コンテキストメニューを表示して「Run ‘All Tests’ with Coverage」を選択し、テストが全て成功することを確認します。

    f:id:ksby:20170720025847p:plain

  19. 特に問題は発生しませんでした。8u141 で開発を進めます。

IntelliJ IDEA を 2017.1.5 → 2017.2 へバージョンアップする

IntelliJ IDEA の 2017.2 がリリースされたのでバージョンアップします。

※上の Java SE のバージョンアップからの続きで ksbysample-webapp-lending プロジェクトを開いた状態でバージョンアップしています。

  1. IntelliJ IDEA のメインメニューから「Help」-「Check for Updates…」を選択します。

  2. 「Platform and Plugin Updates」ダイアログが表示されます。左下に「Update and Restart」ボタンが表示されていますので、「Update and Restart」ボタンをクリックします。

    f:id:ksby:20170720061757p:plain

  3. Plugin の update も表示されました。「Error-prone Compiler Integration」はバージョンアップすると動かなくなりますので、これだけチェックを外して「Update and Restart」ボタンをクリックします。

    f:id:ksby:20170720062026p:plain

  4. Patch がダウンロードされて IntelliJ IDEA が再起動します。

  5. Patch 適用後「Complete Installatioin」ダイアログが表示されます。表示された設定はそのままで「OK」ボタンをクリックします。

    f:id:ksby:20170720062651p:plain

  6. IntelliJ IDEA が起動すると画面下部に「Indexing…」のメッセージが表示されますので、終了するまで待機します。

    f:id:ksby:20170720063013p:plain

  7. C:\Users\root の下に .IntelliJIdea2017.1 フォルダが残っているので削除します。

  8. Gradle Tool Window のツリーを見ると「Tasks」の下に「other」しかない状態になっているので、左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

    f:id:ksby:20170720063259p:plain

  9. clean タスク実行 → Rebuild Project 実行 → build タスクを実行して、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。

    f:id:ksby:20170720065626p:plain

  10. Project Tool Window で src/test を選択した後、コンテキストメニューを表示して「Run ‘All Tests’ with Coverage」を選択し、テストが全て成功することを確認します。

    f:id:ksby:20170720071050p:plain

    テスト成功時のアイコンが変わっていますね。

Git for Windows を 2.13.2 → 2.13.3 へバージョンアップする

Git for Windows の 2.13.3 がリリースされていたのでバージョンアップします。

  1. https://git-for-windows.github.io/ の「Download」ボタンをクリックして Git-2.13.3-64-bit.exe をダウンロードします。

  2. Git-2.13.3-64-bit.exe を実行します。

  3. 「Git 2.13.3 Setup」ダイアログが表示されます。[Next >]ボタンをクリックします。

  4. 「Select Components」画面が表示されます。「Git LFS(Large File Support)」だけチェックした状態で [Next >]ボタンをクリックします。

  5. 「Adjusting your PATH environment」画面が表示されます。中央の「Use Git from the Windows Command Prompt」が選択されていることを確認後、[Next >]ボタンをクリックします。

  6. 「Choosing HTTPS transport backend」画面が表示されます。「Use the OpenSSL library」が選択されていることを確認後、[Next >]ボタンをクリックします。

  7. 「Configuring the line ending conversions」画面が表示されます。「Checkout Windows-style, commit Unix-style line endings」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  8. 「Configuring the terminal emulator to use with Git Bash」画面が表示されます。「Use Windows'default console window」が選択されていることを確認した後、[Next >]ボタンをクリックします。

  9. 「Configuring extra options」画面が表示されます。「Enable file system caching」だけがチェックされていることを確認した後、[Install]ボタンをクリックします。

  10. インストールが完了すると「Completing the Git Setup Wizard」のメッセージが表示された画面が表示されます。中央の「View Release Notes」のチェックを外した後、「Finish」ボタンをクリックしてインストーラーを終了します。

  11. コマンドプロンプトを起動して git のバージョンが git version 2.13.3.windows.1 になっていることを確認します。

    f:id:ksby:20170721043210p:plain

  12. git-cmd.exe を起動して日本語の表示・入力が問題ないかを確認します。

    f:id:ksby:20170721043903p:plain

  13. 特に問題はないようですので、2.13.3 で作業を進めたいと思います。