2016.06.07

jetty6をjetty9.3にアップデートした時のメモ


次世代システム研究室のN.Oです。先日Servletエンジンであるjettyのアップデートの検証をしたのですが、その中でいくつか気づきがありましたので共有します。そもそもの経緯としてはJava8対応の検討をしていたところ、利用していたjettyのバージョンがJava8に非対応である事が分かり、検証を行う事になった次第です。

動作環境の調査


元の環境ではJava6とjetty6で動作していました。今回のターゲットはJava8なので、What Version Do I Use?で対応状況を調べます。こちらのページを見ますと、冒頭にて述べた通りjetty6はJava8に対応してません。対応しているのは9.3からとなっております。


jetty9.3のセットアップ

Running Jettyを参考にjetty9.3をセットアップします。細かい手順は本稿では省略します。

アプリケーションをデプロイしてみる

jettyがセットアップできたので、まずはjetty6で動作している既存のアプリケーションのwarとxmlを、何も手を加えずにjetty9.3でデプロイしましたが、エラーが発生しました。


結果的に3点修正する事で無事動作しました。
1. ServerコネクタをAJP→HTTPに変更する
2. パッケージ名を変更する
3. Deprecatedしたメソッドを修正する

それぞれ詳しく説明していきます。

Serverコネクタの変更 AJP→HTTP

元のjettyではServerコネクタとしてAJPを利用していましたが、AJPモジュールがjetty9で無くなった為、利用する事はできません。今回はフロントのリバースプロキシサーバでの変更も容易だった事と、負荷もそれほど無いサイトだったのでHTTPコネクタに変更しました。

パッケージ名の変更

デプロイ時のエラーでjava.lang.ClassNotFoundExceptionが発生しました。
java.lang.ClassNotFoundException: org.mortbay.jetty.webapp.WebAppContext
これはjettyは過去にプロジェクトのホストを移転した歴史があり、パッケージ名が変わったためです。アプリケーションのXMLを以下のように修正しました。
  < <Configure class="org.mortbay.jetty.webapp.WebAppContext">
  ---
  > <Configure class="org.eclipse.jetty.webapp.WebAppContext">

  <           <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
  ---
  >           <New class="org.eclipse.jetty.server.session.HashSessionIdManager">

Deprecatedしたメソッドの修正

パッケージ名を適切に設定した後、今度はjava.lang.NoSuchMethodExceptionが発生しました。
java.lang.NoSuchMethodException: setIdManager

このアプリケーションはセッションを利用していますが、アプリケーションサーバ間でセッションを共有する仕組みがありません。つまりセッションの管理はアプリケーションサーバごとに行い、フロントのリバースプロキシサーバで適切なセッションを持つアプリケーションサーバに割り降る必要があります。そのためセッションの管理にHashSessionIdManagerを利用し、フロントのリバースプロキシがcookieの文字列を参照して適切なアプリケーションサーバに割り振る形となっているのですが、ここで利用しているメソッドが現在は無くなっているようです。このままでは適切なアプリケーションサーバに割り振る事ができず、動作に支障が出てしまいます。

ここで各バージョンのapidocを参照していきますと、setIdManagerはjetty7時代にDeprecatedとなり、代わりにsetSessionIdManagerを使うようになった事が分かりました。またsetIdManagerはjetty8まで存在していましたがjetty9で無くなってることも判明しました。即座にsetSessionIdManagerに書き換えます。

以上の修正で無事アプリケーションをデプロイする事が出来ました。修正前・修正後のアプリケーションのXMLファイルは以下となります。

修正前
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
  <Set name="contextPath">/demo-app</Set>
  <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/demo-app.war</Set>
  <Get name="sessionHandler">
    <Get name="sessionManager">
      <Call name="setIdManager">
        <Arg>
          <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
            <Set name="workerName">demo-app01</Set>
          </New>
        </Arg>
      </Call>
    </Get>
  </Get>
</Configure>

修正後
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/demo-app</Set>
  <Set name="war"><Property name="jetty.webapps" default="."/>/demo-app.war</Set>
  <Get name="sessionHandler">
    <Get name="sessionManager">
      <Call name="setSessionIdManager">
        <Arg>
          <New class="org.eclipse.jetty.server.session.HashSessionIdManager">
            <Set name="workerName">demo-app01</Set>
          </New>
        </Arg>
      </Call>
    </Get>
  </Get>
</Configure>

あとがき

バージョンを複数またぐと、このようにオプションがDeprecatedとなり消えてしまうという事に気がつきました。またこういう時は各バージョンのapidocを見ていけば良いという事も新たな気づきでした。当たり前の事ですが改めてマニュアルを読む事の大切さを感じた次第です。

次世代システム研究室では、アプリケーション開発や設計を行うアーキテクトを募集しています。アプリケーション開発者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。