仕事でインフラ周りの作業をやって、出くわしたさまざまな問題を備忘録に残しておきたくて。
今回はVelocity を使ったモジュールでエラーが発生して、開発環境がWin環境、本番環境がLinux環境だったから発生した問題の作業したことをまとめてみました。
「Apache Velocity」とは
「Apache Velocity」とは、Javaベースのテンプレートエンジンです。(以下、Velocity。)
テンプレートエンジンとはプログラムで変更する部分と、 雛形となるドキュメントのテンプレートを別々に扱う仕組みです。
Velocity を使ったモジュール
Velocity を使ったモジュール、今回は「JavaMail」ですね。
本番環境でメール送信の処理に入ると、例外発生してしまい、メール送信ができませんでした。
エラーが起きたサーバー環境は以下の通り。
CentOS 7
Tomcat 8
サーバーの処理の環境は以下の通り。
Java 1.8
Spring MVC 4.3.4
maven 2.9
JavaMail API 1.4.3
velocity 1.7
エラー内容はこんな感じ。
org.apache.velocity.exception.VelocityException: Error initializing log: Failed to initialize an instance of org.apache.velocity.runtime.log.Log4JLogChute with the current runtime configuration.
at org.apache.velocity.runtime.RuntimeInstance.initializeLog(RuntimeInstance.java:875)…(中略)…
Caused by: org.apache.velocity.exception.VelocityException: Failed to initialize an instance of org.apache.velocity.runtime.log.Log4JLogChute with the current runtime configuration.
at org.apache.velocity.runtime.log.LogManager.createLogChute(LogManager.java:220)
at org.apache.velocity.runtime.log.LogManager.updateLog(LogManager.java:269)
at org.apache.velocity.runtime.RuntimeInstance.initializeLog(RuntimeInstance.java:871)
… 61 more
Caused by: java.lang.RuntimeException: Error configuring Log4JLogChute :
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.velocity.util.ExceptionUtils.createWithCause(ExceptionUtils.java:67)
at org.apache.velocity.util.ExceptionUtils.createRuntimeException(ExceptionUtils.java:45)
at org.apache.velocity.runtime.log.Log4JLogChute.initAppender(Log4JLogChute.java:133)
at org.apache.velocity.runtime.log.Log4JLogChute.init(Log4JLogChute.java:85)
at org.apache.velocity.runtime.log.LogManager.createLogChute(LogManager.java:157)
… 63 more
Caused by: java.io.FileNotFoundException: velocity.log (Permission denied)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at java.io.FileOutputStream.(FileOutputStream.java:213)
at java.io.FileOutputStream.(FileOutputStream.java:133)
at org.apache.log4j.FileAppender.setFile(FileAppender.java:290)
at org.apache.log4j.RollingFileAppender.setFile(RollingFileAppender.java:194)
at org.apache.log4j.FileAppender.(FileAppender.java:109)
at org.apache.log4j.RollingFileAppender.(RollingFileAppender.java:72)
at org.apache.velocity.runtime.log.Log4JLogChute.initAppender(Log4JLogChute.java:118)
… 65 more
「velocity.log」というログファイルがないよーって怒られています。
でも、そもそも、開発中に「velocity.log」使っていた覚えがない。ローカル環境(Win)では出力されていなかった。
原因を探していると、以下の記事に辿りつきました。どうやらLinux環境だけに発生する現象らしい。
解決案
書き込み許可があるvelocity.logファイルを作成する
とりあえず対処したい場合、velocity.logファイルを作成し、tomcat起動ユーザーで書き込みができるようにしていれば、例外が発生しなくなります。
デフォルト設定の場合、カレントディレクトリに作成されます。
カレントディレクトリってどこよ?
カレントディレクトリはTomcatのサービスコマンドを叩いた場所です。
もしくは、どこかに以下の出力して、現在のカレントディレクトリはどこか確認するといいですね。
System.getProperty("user.dir")
ログ出力を無効にする
もっとちゃんと対処したい場合、ログ出力を無効にするのがベターですね。
init()呼び出す際、ログ出力する設定を追加します。
なので、Javaのソースを修正する必要が出てきます。
init()メソッドを呼び出す前に以下を記述する。
Velocity.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogSystem");
もしくは、
velocity.properties ファイルを用意。
[WEB-INF/velocity.properties] runtime.log.logsystem.class = org.apache.velocity.runtime.log.NullLogSystem
init()メソッドにプロパティファイルの引数を持たせる。
init()→init( Properties p )
まとめ
結構悩んだ事象だったので、他の人の手助けになれば、幸いです。