Pivotal Web Services にデプロイしたプロジェクトで利用していたデータベースをH2からMySQLに変更してみたいと思います。
まずは、停止していたプロジェクトを起動するところからですかね、それでははじめていきたいと思います。
Pivotal Web Servicesでプロジェクト起動
Pivotalにログインして、Pivotal Web Servicesを選択。
「development」の「Apps」でプロジェクト名をクリックします。
ダッシュボードから起動しても良いのですが、
Cloud Foundry Command Line Interface (cf CLI)をインストールしてるので、コマンドプロンプトで起動してみます。
cf start [PWSにあるプロジェクト名]
「Events」に『Started app』って追加されていればOK。
PWSでMySQLの利用
※ローカル環境に本番環境と同じ環境のバックアップがあることを確認してください。
いまのところ、本番環境のバックアップの方法が分からないので、ローカル環境に本番環境と同じ環境のものを用意しておく感じで。
PWSで利用できるバックエンド・サービスの一覧を確認。
cf marketplace
※プラン名の右に*が付いているものは有料のようです。
今回は、「cleardb」の「spark」を利用。
cf create-service [サービス名] [プラン名] [サービス・インスタンス名]
⇧ コマンドでサービス・インスタンスを作成します。今回はMySQLサービス・インスタンスを作成。
cf bind-service [アプリケーション名] [サービス・インスタンス名]
⇧ プロジェクト(アプリケーション)でMySQLサービス・インスタンスを利用する準備
「cf restage [アプリケーション名]」しろ~、とあるので実行。
cf restage hajiboot-ts0818
はい、失敗。
エラーの原因は、DBのマイグレーションツールFlywayで起きたっぽいです。(ローカル環境のSpring Boot のプロジェクトでpom.xmlで「Flyway」を追加しています。)
2017-10-28T22:55:31.32+0900 [APP/PROC/WEB/0] OUT org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Unable to obtain Jdbc connection from DataSource 2017-10-28T22:55:31.32+0900 [APP/PROC/WEB/0] OUT Caused by: org.flywaydb.core.api.FlywayException: Unable to obtain Jdbc connection from DataSource 2017-10-28T22:56:28.25+0900 [APP/PROC/WEB/0] OUT 2017-10-28 13:56:28.253 WARN 14 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Unable to obtain Jdbc connection from DataSource 2017-10-28T22:56:28.28+0900 [APP/PROC/WEB/0] OUT org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Unable to obtain Jdbc connection from DataSource
.Introduction to Cloud Foundry #JJUG - SSSSLIDE
⇧ 「はじめてのSpring Boot 改訂版(著:槙 俊明)」の著者の人のスライドを見て、てっきり「application-cloud.properties」ファイルが自動でできるんかと思ったら、自分で作らないといけないみたいで、尚且つ、ローカル環境で作って再デプロイしないといけないようです。
sshログインで本番環境で作るってのはNG?っぽいのかな~、ちょっと分からんです。
それにしても、本番環境をローカル環境で上書きしていくやり方しかできないとすると、ローカル環境ありきになってしまうのですが、仮にローカル環境を削除してしまっていた場合に本番環境からbackup取れないのは怖いですね。
本番環境のbackupの取得方法が見つからないので、そのへんが気になるのですが...。
Spring Bootのプロファイルとは?
「Spring」では「プロファイル」という概念があり、環境ごとに「プロパティ」「Bean定義」などのグループを定義して実行時に切り替えができるようです。開発環境、本番環境といったグループ分けができるようです。
「プロファイル」を使う方法としては、
- propertiesファイル、またはyamlファイルにシステムプロパティ『spring.profiles.active』でグループを設定
- グループ分のpropertiesまたはyamlファイルを作る
- 環境変数「SPRING_PROFILES_ACTIVE」を利用する
の3パターンぐらいあるようです。
1. 『spring.profiles.active』でグループを設定
・Spring Bootで設定のプロファイル分けをする - Qiita
2. グループ分のpropertiesまたはyamlファイルを作る
・Spring Boot の application.properties (yml) でプロパティが重複したときの挙動 - Qiita
3. 環境変数「SPRING_PROFILES_ACTIVE」を利用する
・Spring Boot起動時に環境毎にapplication.propertiesを切り替える色々 - Qiita
⇧ 諸先輩方のサイトが詳しいので参考に。
「Cloud Foundry」にSpring Boot のアプリケーションをデプロイした場合、デフォルトで「application-cloud.properties」ファイルを適用してくれるようなので、ローカル環境のSpring Bootのプロジェクトで「application-cloud.properties」ファイルを作成して再度、本番環境にデプロイしていきます。
「application-cloud.properties」ファイル作成と再デプロイ
本番環境がダメになってしまったので、 ローカル環境を再デプロイしていきますが、再デプロイの前に、「application-cloud.properties」ファイルを作成して設定を記述。
いま、「application.properties」ファイルしかないので、
追加します。フォルダ内の空白部分で右クリックし、「新規作成(X)」>「テキスト ドキュメント」を選択し、
ファイル名を拡張子も含めて変更していきます。
「application-cloud.properties」とします。
拡張子を変更すると出る警告には「はい(Y)」を選択。
新しくpropertiesファイルができましたので、テキストエディタなどで開いて編集していきます。
テキストエディタは何でも良いとは思いますが、サクラエディタとかが良さそうですかね。
ファイルを開きましたら、
spring.jpa.hibernate.ddl-auto=upload spring.datasource.initialize=false
を記述して保存。
ちなみに、今回のプロジェクトは、「はじめてのSpring Boot 改訂版(著:槙 俊明)」という書籍のP.91~の『hajiboot-thymeleaf』プロジェクトを作成して使っています。
おそらく、拡張子が「.sql」のファイルを
spring.datasource.initialize=false
で無効化していなかったのがで、DBマイグレーションツールのFlywayでエラーが起こってしまっていたってことですかね?
propetiesファイルが準備できたので、新たにプロジェクトのjarを作成するため、「mvnw」ファイルのあるディレクトリを確認します。
コマンドプロンプトなどを開いて、ディレクトリを移動し、プロジェクトのjarファイルを作成。
cd C:¥workspace¥hajiboot-thymeleaf mvnw.cmd clean package -DskipTests=true
なぜか、今回は「-DskipTests=true」を付けてもエラーにならず...う~ん、分からん。
「C:¥workspace¥hajiboot-thymeleaf¥target¥hajiboot-thymeleaf-0.0.1-SNAPSHOT.jar」が更新されています。(前回、jarを作っているので更新されたようです。)
デプロイをしていきますが、「サービス・インスタンス」は、バインド先のアプリケーションのステージング前にバインドされている必要があるらしく、「--no-start」オプションをつけてデプロイする必要があるみたいです。
cf push hajiboot-ts0818 -p target/hajiboot-thymeleaf-0.0.1-SNAPSHOT.jar -b java_buildpack --no-start
続いて、デプロイしたアプリケーションを「MySQLサービス・インスタンス」にバインドします。
cf bind-service hajiboot-ts0818 ts0818db
バインドが成功すると、環境変数「VCAP_SERVICES」に「MySQLサービス・インスタンス」の接続情報が追加されるようです。
「cf env [アプリケーション名]」で確認できるようです。
cf env hajiboot-ts0818
「VCAP_SERVICES」というJSONの「credentials」というキーの値として「MySQL」の接続情報が 取得できるようです。
アプリケーションの起動
「cf start [アプリケーション名]」でアプリケーションを起動
cf start hajiboot-ts0818
はい、エラー。
2017-10-29T11:45:56.71+0900 [APP/PROC/WEB/0] OUT 2017-10-29 02:45:56.710 WARN 15 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Schema `ad_eaced1ce5185007` contains a failed migration to version 3 !
マイグレーションに失敗って...う~ん、Flywayが問題っすか。
mvnw.cmd compile flyway:info
⇧ flywayの状況を確認できるかと思いきや...これまたエラー。
どうやら、Flywayで「DBマイグレーション」する方法には、
の3つほどあり、Spring Bootで利用してるのは、「3. Java API」らしいです。pom.xmlに
<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency>
って追記しているから、mavenのプラグインかと思っていたのですが、さにあらず!
って...これ、Java APIでマイグレーションの状況はどうやって確認すれば?
いろいろ試行錯誤した結果、pom.xmlの「flyway」の部分をコメントアウトして無効化して新たにjarファイルを作成、デプロイ、MySQLサービス・インスタンスにバインド、アプリケーションを起動で動きました。
<!-- <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency> -->
根本的な解決にはなってないですが、動きました!
ブラウザでアクセスしてみます。「http://アプリケーション名..cfapps.io」でアクセスできます。
顧客を追加してみます。
「Dora Emon」さんが追加されました。
ただ、実際にMySQLのテーブルとかを確認できていないのですが、
・Cloudn PaaS v2(CloudFoundry)の Service(PostgreSQL & MySQL)に接続 - Qiita
・日本Cloud Foundryグループ ブログ: phpMyAdminをCloud Foundryで動かして、お手軽DBメンテナンス!
・日本Cloud Foundryグループ ブログ: SQL Buddy を Cloud Foundry で動かす
のサイトを参考に、何かしらのコマンドやツールをインストールしていくしかなさそうです。
あんまりメモリを消費しない方法を見極めて、インストールを試みていきたいですね。なんせ、無料枠は2GBまでですから~、残念!
利用してないときは忘れずアプリを停止しときましょう。
それにしても、無料で使わせてもらっているので文句は言えないですが、Pivotal Web ServicesのCloud Foundry使い勝手があんまり良くない気が...。
今回もハマりにハマりましたが、Flyway込みのデプロイはできずでしたが、MySQLは使えたっぽいということで。