前回までの手順
herokuのjavaのサンプルプロジェクト
herokuのGetting Started with Java on Herokuの手順で作成された「java-getting-started(helloworld)」プロジェクトでは、デフォルトでpostgresqlが利用できるようになっている。
これを既存のmysql(実際にはmariadb)に接続する。
手順
手順1:Run the app locally
まず、以下のherokuの手順にしたがって、組み込みのJavaサーバーのJettyが起動することを確認する。
https://devcenter.heroku.com/articles/getting-started-with-java#run-the-app-locally
foreman start web
の前に、mvn clean install
を実行しないとアプリケーションが起動しないので注意する。
foreman
は、herokubeltに同封されているProcfileにしたがって複数プロセスを起動することができるツールらしい。
http://qiita.com/7kaji/items/6a59977d2ad85604e7fd
サーバーが起動したら、http://localhost:5000/
へアクセスして、Hello from Java!
が表示されればOK。
そしたら、foremanは、Ctrl+cで閉じます。
手順2:IntelliJで開く
IDEを使って開発したいため、IntelliJでherokuのサンプルプロジェクトを開きます。
「Open」を選択して、「Open File or Project」ウィンドウを開きます。
herokuのサンプルプロジェクト「java-getting-started」を選択。
IntelliJが適当にプロジェクトの設定を追加してくれます。
手順3:IntelliJ上でMainクラスを起動
IntelliJからMainクラスを実行します。Mainクラスを右クリックから「Run Main.main()」を選択
Exception in thread "main" java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:542)
at java.lang.Integer.valueOf(Integer.java:766)
at Main.main(Main.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Main.javaの65行目を見ます。
public static void main(String[] args) throws Exception {
Server server = new Server(Integer.valueOf(System.getenv("PORT")));
System.getenv("PORT")
で値が取れていないようなので、IntelliJのメニューから「Run」-「Edit Configurations」から環境変数を設定します。
「Environment variables」が環境変数の指定になります。コードがSystem.getenv()
なので、「VM Option」(起動引数)の-D
オプションではダメでした。
とりあえず、PORT
に5000を設定。(これはforemanのコマンド1つ目のデフォルトポート番号らしいです)
「OK」を押して、 ウィンドウを閉じて、再度、MainクラスをRunする。
2015-04-25 19:04:59.303:INFO::main: Logging initialized @177ms
2015-04-25 19:04:59.412:INFO:oejs.Server:main: jetty-9.2.10.v20150310
2015-04-25 19:04:59.458:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@3ada9e37{/,null,AVAILABLE}
2015-04-25 19:04:59.479:INFO:oejs.ServerConnector:main: Started ServerConnector@490d6c15{HTTP/1.1}{0.0.0.0:5000}
2015-04-25 19:04:59.480:INFO:oejs.Server:main: Started @357ms
こんな感じで起動するので、http://localhost:5000/
にアクセスする。
おなじみのhello
メッセージが表示されるはずです。
また、以下のようにjava.net.BindException: Address already in use
のようなエラーがでる場合は、他のプロセスで5000
番ポートを利用しているので、探しだしてkillするか、IntelliJの環境変数のPORT
の番号をずらしましょう。
2015-04-25 19:06:30.342:INFO:oejs.Server:main: jetty-9.2.10.v20150310
2015-04-25 19:06:30.381:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@3ada9e37{/,null,AVAILABLE}
2015-04-25 19:06:30.393:WARN:oejuc.AbstractLifeCycle:main: FAILED ServerConnector@5f5a92bb{HTTP/1.1}{0.0.0.0:5000}: java.net.BindException: Address already in use
java.net.BindException: Address already in use
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:436)
at sun.nio.ch.Net.bind(Net.java:428)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:321)
at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80)
at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:236)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.server.Server.doStart(Server.java:366)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at Main.main(Main.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
手順4:mysqlに接続してみる
デフォルトのpostgresqlを利用するのではなく、現行稼働しているmysql(実際はmariadb)に接続してみます。
サンプルプログラムを流用して、自前で用意したmysqlへ接続します。
pomファイルにmariadbのコネクタのライブラリを設定
すみません、mysqlの方は読み替えてください。
mariadbの最新のコネクタライブラリを探す。
googleで検索すると以下のページが引っかかるので参考にします。
http://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client/1.1.8
以下の設定をpom.xmlに追記します。postgresqlの設定は消しても大丈夫です。
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.1.8</version>
</dependency>
mariadbへの接続設定を環境変数に設定
herokuのサンプルでは、heroku config
の設定情報からpostgresqlのホスト、ユーザー、パスワードを取得してデータベースコネクションを取得しています。
heroku configの例
~/D/g/java-getting-started ❯❯❯ heroku config
=== dry-bayou-2092 Config Vars
DATABASE_URL: postgres://xxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyy@ec2-99-999-999-99.compute-1.amazonaws.com:5432/zzzzzzzzzzzzzz
HEROKU_POSTGRESQL_MAUVE_URL: @ref:aaaaaaaa-bbbbbbb-9999:url
JAVA_OPTS: -XX:+UseCompressedOops
- xxxxxxxxxxxxxx ユーザーID
- yyyyyyyyyyyyyyyyyyyyyyyyyy パスワード
- ec2-99-999-999-99.compute-1.amazonaws.com ホスト
- 5432 ポート番号
- zzzzzzzzzzzzzz データベース
postgresqlの設定を参考にして、環境変数に以下を設定します。
mariadb://userid:pasword@localhost:3306/database
「Run」-「Edit Configurations」の「Environment Variables」に環境変数「DB_URL」を追加
userid、pasword、database等は自分の環境に合わせて変更してください
mariadbへ接続するようにJavaコードを変更
サンプルコードのgetConnection
メソッドのDATABASE_URL
をDB_URL
に、postgresql
をmariadb
に変更します。
private Connection getConnection() throws URISyntaxException, SQLException {
URI dbUri = new URI(System.getenv("DB_URL"));
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
int port = dbUri.getPort();
String dbUrl = "jdbc:mariadb://" + dbUri.getHost() + ":" + port + dbUri.getPath();
return DriverManager.getConnection(dbUrl, username, password);
}
手順5:DB接続を確認
Mainクラスを再度実行して、今度は、http://localhost:5000/db
にアクセスします。
Servletでmariadbへの接続がうまくいけば、ticks
テーブルが作成され、INSERT INTO ticks VALUES (now())
で現在時刻がテーブルに登録されます。
その結果がWebページに表示されれば成功です。
herokuにデプロイする前に
herokuの環境変数にmaridadbの接続設定を追加します。
heroku config:set DB_URL=mariadb://userid:pasword@localhost:3306/database