#chiroito ’s blog

Java を中心とした趣味の技術について

JMS 2.0 ハンズオン @JavaOne San Francisco 2015

2015年10月25日(日)~29日(木)にサンフランシスコで開催された JavaOne San Francisco 2015 でJMS 2.0 を体験するハンズオンセッションを行いました。ハンズオンのタイトルは Down and Dirty with JMS 2 [HOL2575] です。ハンズオン資料はこちら(JMS 2 Hands on Lab)にあります。

(転載:https://events.rainfocus.com/oow15/catalog/oracle.jsp?event=javaone&search=HOL2575&search.event=javaoneEvent)

ハンズオンのプロジェクトをダウンロードすると problem と solution の 2 つのプロジェクトが含まれています。problem はこれからみなさんがハンズオンを進めていくプロジェクトで、 solution はその解答例が実装されているプロジェクトです。
このハンズオンは、JUnit を使用して書かれた 8 つのテストがあり、そのテストを全て成功するようにしていきます。
テストを実行すると、まずはじめに war アプリケーションが作成されて GlassFish にデプロイされます。その後、1 つずつテストが実行されていきます。
テスト以外に2つのクラスがありますが、既存のクラスを変更する必要はありません。ただし、8 つめのテストで 1 つだけクラスを作成します。

このハンズオンを進めていくと、下記の様にいくつかの問題が発生することがあります。システムを運用する場合にはキチンとした対応が必要ですが、今回はハンズオンなので荒めの応急処置で対応します。
  • キューから想定しない値が得られてテストが失敗する
  • アプリケーションがデプロイできない
  • GlassFish が起動できない

キューから想定しない値が得られてテストが失敗する

今回のハンズオンでは、各テスト内でキューに1つメッセージを入れて、1つ取り出すという処理を行います。そのため、キューに入れるところだけ実装して、取る処理を実装しないでテストを実行すると、キューにメッセージを入れる回数よりもキューからメッセージを取る回数が少ない状態になります。こうなると次にキューから取り出すときに、前に入れたメッセージが取れてしまい、Assertが想定するメッセージを取得できなくなりテストが失敗します。

テストが失敗したエラーメッセージ
testSendStringMessage(org.glassfish.jms2lab.Jms2Test)  Time elapsed: 1.022 sec  <<< FAILURE!
org.junit.ComparisonFailure: expected: but was:
at org.junit.Assert.assertEquals(Assert.java:115)
at org.junit.Assert.assertEquals(Assert.java:144)
at org.glassfish.jms2lab.Jms2Test.testSendStringMessage(Jms2Test.java:116)
キューを空にすることで、この問題を解決します。まずは、キューの一覧を確認し、存在するキューを確認しましょう。次に存在するキューを空にします。
やりかたは色々ありますが、今回は GlassFish の管理ツールである asadmin を使用してキューを空にします。asadmin は GlassFish のインストール先の bin ディレクトリ内にあります。
キューの一覧を確認するには asadmin の list-jmsdest サブコマンドを使用します。このサブコマンドを実行するといくつかのキューが出力されますが、ハンズオンで使用するキューは MyQueue 、MyQueue2、RequestQueue の 3 つです。

キュー一覧の確認方法
C:\GlassFish\bin>asadmin.bat list-jmsdest
mq.sys.dmq
MyQueue
RequestQueue
MyQueue2
Command list-jmsdest executed successfully.
次に、確認できたキューを空にします。キューを空にするには flush-jmsdest サブコマンドを使用します。このサブコマンドが成功すると Command flush-jmsdest executed successfully. と出力されます。
C:\GlassFish\bin>asadmin.bat flush-jmsdest --desttype queue MyQueue
Command flush-jmsdest executed successfully.

C:\GlassFish\bin>asadmin.bat flush-jmsdest --desttype queue MyQueue2
Command flush-jmsdest executed successfully.

C:\GlassFish\bin>asadmin.bat flush-jmsdest --desttype queue RequestQueue
Command flush-jmsdest executed successfully.

アプリケーションがデプロイできない

アプリケーションをデプロイしようとしているときに、既にデプロイされている同じ名前のアプリケーションが実行中のため削除できない場合などにこの問題が発生します。本来は既存のアプリケーションを停止させて削除できるようにするべきですが、今回はハンズオンなので新たにデプロイするアプリケーションの名前を変えることでアプリケーションをデプロイできるようにします。

エラーメッセージとしては下記の様なメッセージが出ます。
重大:   Application with name jms2lab is already registered. Either specify that redeployment must be forced, or redeploy the application. Or if this is a new deployment, pick a different name
情報:   File C:\Users\chihiroito\AppData\Local\Temp\MIME2810202128384054274.tmp was not deleted
 もしくは
重大: exit_code: FAILURE, message: Error occurred during deployment: Application with name jms2lab is already registered. Either specify that redeployment must be forced, or redeploy the application. Or if this is a new deployment, pick a different name. Please see server.log for more details. [status: CLIENT_ERROR reason: Bad Request]
アプリケーションをデプロイしているメソッドで war ファイル名を変更します。この例では jms2lab.war を jms2lab_1.war へ変更しています。
    @Deployment
public static WebArchive createDeployment() {
return ShrinkWrap
.create(WebArchive.class, "jms2lab_1.war")
.addClass(MessageReceiver.class)
.addClass(MyMessageListener.class)
.addAsWebInfResource("web.xml", "web.xml");
}

GFが起動できない

私の環境では再現できなかったので原因は不明ですが、ハンズオンセッション中には NetBeans 上から GlassFish を起動/停止を繰り返していると、新たに起動する際にエラーが発生して起動できなくなることがありました。
この問題は、NetBeans から見ると、GlassFish はきちんと停止したように見えるのですが、何らかの理由で停止できなかったようです。GlassFish のプロセスが NetBeans からコントロールできない状態で動き続け、ソケットをバインドし続けました。そのため、新たに起動した GlassFish がソケットをバインドできないためにエラーが出力されます。今回はハンズオンなので、既存の GlassFish を強制的に停止します。

出力されるエラー
java.net.BindException: Address already in use: JVM_Bind
Windows の場合はタスクマネージャから既に動いている GlassFish のプロセスを停止します。Linux の場合は、kill コマンドでプロセスを停止します。