技評のJBoss入門


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

技評の JBoss 入門

JBoss site のマニュアルから入るのがよいのかもしれないが、
ざっと全体を眺めるため、日本語の入門本で動作を確認してみる。

ベースが 3.0.7/3.2.0 なので 4.0.3 SP1 で動くか少し心配。
細かいエラーを覚えてないが、4.0.3 でなかなか消えないエラーが SP1 にしたことで
あっさり消えたので、今回も SP1 を使用した。

1章

JBoss モジュールの紹介や、EJB の基礎

EJB の種類

いまさらですが...
  • Session Bean
    • javax.ejb.SessionBean
  • Entity Bean
    • javax.ejb.EntityBean
  • Message Driven Bean

必須インターフェイス

  • Component Interface
  • Home Interface
  • Bean class
  • Deployment Descriptor ejb-jar.xml


EJB-JAR file structure

 xxejb.jar
 +- Sample.class # component interface
 +- SampleHome.class # home interface
 +- SampleBean.class # EJB Bean
 +- META-INF
    +- ejb-jar.xml

ejb-jar のサンプルは #step1 内にある

EJB Interface: Remote and Local

Component Interface Home Interface
Remote Interface javax.ejb.EJBObject javax.ejb.EJBHome
Local Interface javax.ejb.EJBLocalObject javax.ejb.EJBLocalHome


JBoss deployment descriptor


  • jboss.xml
    • JNDI name 等 ejb-jar.xml にかけない設定情報を記述する. WEB-INF におく

  • jboss-web.xml
    • JNDI name 等 web.xml に記述できない設定情報を記述

  • jbosscmp-jdbx.cml
    • CMP Entity EJB module 用。データソース名、フィールドと SQL タイプの
マッピングなど

2章 プログラミングの基礎


step1


最初のサンプル。簡単な CMP Entity Bean を jar + META-INF/ejb-jar.xml
形式でデプロイする。クライアントサイドはスタンドアローンプログラム。

Counter
Component interface, extends EJBObject, getValue(), setValue()
などを定義するインターフェイス

CounterHome
Home interface, extends EJBHome, create(), findByPrimaryKey(),
findAll() 等を定義するインターフェイス

CounterBean
Entity Bean, public abstract class CounterBean implements EntityBean,
永続化フィールドに関する setter, getter を abstract で定義.ejbCreate
をはじめ、ejbActivate(), ejbPassivate(), ejbLoad(), ejbStore, ejbRemove()
等が定義される。

CounterClient
JNDI で Home インターフェイスを取得し、プライマリキーで
エンティティビーンをみつけて、なければ作成。findAll() ですべてのエンティティ
を見つけて表示する。



step1-ejb.jar
jar file, web.xml は入っていない。純粋に EJB のみを含む。

META-INF/
META-INF/MANIFEST.MF
sample/
sample/ejb/
META-INF/ejb-jar.xml
META-INF/jboss.xml
META-INF/jbosscmp-jdbc.xml
sample/ejb/Counter.class
sample/ejb/CounterBean.class
sample/ejb/CounterHome.class

deploy 時のメッセージ

17:36:35,948 INFO  [ProxyFactory] Bound EJB Home 'Counter' to jndi 'ejb/step1/co
unter'
17:36:36,620 INFO  [EJBDeployer] Deployed: file:/C:/usr/local/jboss/server/defau
lt/deploy/step1-ejb.jar


ejb-jar.xml
Entity Bean の定義

<?xml version="1.0"?>

<!DOCTYPE ejb-jar PUBLIC
 "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
 "http://java.sun.com/j2ee/dtds/ejb-jar_2_0.dtd">

<ejb-jar>
 <enterprise-beans>
   <entity>
     <ejb-name>Counter</ejb-name>
     <home>sample.ejb.CounterHome</home>
     <remote>sample.ejb.Counter</remote>
     <ejb-class>sample.ejb.CounterBean</ejb-class>
     <persistence-type>Container</persistence-type>
     <prim-key-class>java.lang.String</prim-key-class>
     <reentrant>False</reentrant>
     <abstract-schema-name>Counter</abstract-schema-name>
     <cmp-field><field-name>name</field-name></cmp-field>
     <cmp-field><field-name>value</field-name></cmp-field>
     <primkey-field>name</primkey-field>
   </entity>
 </enterprise-beans>
</ejb-jar>

jboss.xml
EJB と JNDI の対応付け

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE jboss PUBLIC
     "-//JBoss//DTD JBOSS//EN"
     "http://www.jboss.org/j2ee/dtd/jboss.dtd">

<jboss>
 <enterprise-beans>
   <entity>
     <ejb-name>Counter</ejb-name>
     <jndi-name>ejb/step1/counter</jndi-name>
   </entity>
 </enterprise-beans>
</jboss>

jbosscmp-jdbc.xml
CMP bean を DB にどのようにおくかを指定

<?xml version="1.0"?>

<!DOCTYPE jbosscmp-jdbc PUBLIC
  "-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN"
  "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd">

<jbosscmp-jdbc>
 <defaults>
   <create-table>true</create-table>
   <remove-table>true</remove-table>
 </defaults>
 <enterprise-beans>
   <entity>
     <ejb-name>Counter</ejb-name>
     <table-name>step1</table-name>
   </entity>
 </enterprise-beans>
</jbosscmp-jdbc>

jndi.properties
以下の内容の物でコンパイルの過程でクラスのディレクトリ
にコピーされているが jar には含まれていない。動いてしまうのはこれらが
デフォルトと一致しているためか... いや、違う、これはクライアントプログラム
のための物だ。

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

実行してみるとエラーになった。

E:\ghjbossbook\samples\chap2\step1>step1
[test]
javax.naming.CommunicationException [Root exception is java.io.InvalidClassException: org.jboss.invocation.InvokerInterceptor; unable to create instance]
       at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:707)
       at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:572)
       at javax.naming.InitialContext.lookup(Unknown Source)
       at sample.client.CounterClient.getHome(CounterClient.java:48)
       at sample.client.CounterClient.main(CounterClient.java:19)
Caused by: java.io.InvalidClassException: org.jboss.invocation.InvokerInterceptor; unable to create instance
       at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
       at java.io.ObjectInputStream.readObject0(Unknown Source)
       at java.io.ObjectInputStream.readObject(Unknown Source)
       at org.jboss.proxy.Interceptor.readExternal(Interceptor.java:66)
       at java.io.ObjectInputStream.readExternalData(Unknown Source)
       at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
       at java.io.ObjectInputStream.readObject0(Unknown Source)
       at java.io.ObjectInputStream.readObject(Unknown Source)
       at org.jboss.proxy.Interceptor.readExternal(Interceptor.java:66)
       at java.io.ObjectInputStream.readExternalData(Unknown Source)
       at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
       at java.io.ObjectInputStream.readObject0(Unknown Source)
       at java.io.ObjectInputStream.readObject(Unknown Source)
       at org.jboss.proxy.Interceptor.readExternal(Interceptor.java:66)
       at java.io.ObjectInputStream.readExternalData(Unknown Source)
       at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
       at java.io.ObjectInputStream.readObject0(Unknown Source)
       at java.io.ObjectInputStream.readObject(Unknown Source)
       at org.jboss.proxy.ClientContainer.readExternal(ClientContainer.java:142)
       at java.io.ObjectInputStream.readExternalData(Unknown Source)
       at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
       at java.io.ObjectInputStream.readObject0(Unknown Source)
       at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
       at java.io.ObjectInputStream.readSerialData(Unknown Source)
       at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
       at java.io.ObjectInputStream.readObject0(Unknown Source)
       at java.io.ObjectInputStream.readObject(Unknown Source)
       at java.rmi.MarshalledObject.get(Unknown Source)
       at org.jnp.interfaces.MarshalledValuePair.get(MarshalledValuePair.java:57)
       at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:637)
       ... 4 more

ふと思い出したが、client の jar ファイルの構成が変わっていたためにトラブルが
あったような気がした。確かに実行ファイルにしても実行用の ant task にしても
クラスパスに通す jar ファイルはハードコーディングしてある。
次の様なタスクを加えて実行すると正しく動作した。

 <target name="runclient">
   <java classname="sample.client.CounterClient" fork="yes" dir="${build.classes}">
     <classpath>
       <fileset dir="${jboss.home}/client">
         <include name="**/*.jar"/>
       </fileset>
       <pathelement location="${build.classes}"/>
     </classpath>
   </java>
 </target>

runclient:
    [java] log4j:WARN No appenders could be found for logger (org.jboss.security.SecurityAssociation).
    [java] log4j:WARN Please initialize the log4j system properly.
    [java] name=counter,value=2

直ったけれど、率直な感想としてもっとわかりやすいエラーにしてほしい。
ネストした例外をすべて出せるかどうかわからないが、jar ファイルが足りず
エラーになるということは ClassNotFoundException が大本ではないの?
とするとそのクラス名から jar ファイルが足りないという線は直ぐにでて
きそうな物だが...

Step 2

Web コンテナから実行する方法の解説

war file
次の様な構成をとる

xxxweb.war  # .war で終わればよい
+- WEB-INF
|  +- web.xml
+- classes/ # class files
+- lib/     # jar files
+- <HTML, JSP, image file 等>

web.xml
ServletContext init param, session config, servlet/jsp name


ビルド前の構成

│  build.xml
│
├─build
│  ├─classes
│  │  │  jndi.properties
│  │  │
│  │  ├─META-INF
│  │  │      ejb-jar.xml
│  │  │      jboss.xml
│  │  │      jbosscmp-jdbc.xml
│  │  │
│  │  └─sample
│  │      ├─ejb
│  │      │      Counter.class
│  │      │      CounterBean.class
│  │      │      CounterHome.class
│  │      │
│  │      ├─util
│  │      │      CounterUtil.class
│  │      │
│  │      └─web
│  │              CounterServlet.class
│  │
│  └─lib
│          sample-ejb-client.jar
│          step2-ejb.jar
│          step2.war
│
├─lib
│      javax.servlet.jar
│
├─resources
│      jndi.properties
│
└─src
   └─sample
       ├─ejb
       │  │  Counter.java
       │  │  CounterBean.java
       │  │  CounterHome.java
       │  │
       │  └─META-INF
       │          ejb-jar.xml
       │          jboss.xml
       │          jbosscmp-jdbc.xml
       │
       ├─util
       │      CounterUtil.java
       │
       └─web
           │  CounterServlet.java
           │  index.jsp
           │  ShowCounter.jsp
           │
           └─WEB-INF
                   web.xml

ant で build すると step1 相当の ejb.jar ファイルと war ファイルが
deploy ディレクトリにコピーされる。

実行してみると (/step2 にアクセス) 初期画面は表示される物の
カウンタを表示させようとするとエラーになる。

description The server encountered an internal error () that prevented it from fulfilling this request.

exception 

javax.servlet.ServletException
sample.web.CounterServlet.doGet(CounterServlet.java:45)
javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)


root cause 

java.lang.ClassCastException
com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229)
javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137)
sample.util.CounterUtil.getHome(CounterUtil.java:17)
sample.web.CounterServlet.getNextCounter(CounterServlet.java:22)
sample.web.CounterServlet.doGet(CounterServlet.java:37)
javax.servlet.http.HttpServlet.service(HttpServlet.java:697)


step1 を undeploy してみるが、効果なし。

client ライブラリを war ファイルに強引に追加すると deploy 時に仕様違反の
エラーが発生。

これという解決策が見つからない。デプロイの仕方が悪いのではという意見もあった。
EJB を jar で クライアント部分を WAR で別々にデプロイするとまずいのだろうか?

古い版で試してみる。3.0.7 は 5.0 では実行できない。1.4 で実行は出来たが、
ビルドが失敗してしまう。3.2.0 を 1.4 で起動してみる。コンパイル、デプロイは
問題ない。

実行してみると 3.2.0 では確かに動く。 4.0.3 では異なる単位でデプロイされた
EJB は参照できないということか? 

処理の流れ
index.jsp
  <a href="CounterServlet">...</a>
    CounterServlet.doGet()
      getNextCounter()
        // Home interface を取得して EJB を取得
        get home interface
        home.findByPrimaryKey(name) and return counter.getNextValue()
      // request の attribute に ejb の値をセットし、jsp にフォワード
      request.setAttribute(COUNTER_NAME, new Long(counter))
      getServletContext().getRequestDispatcher("/ShowCounter.jsp")
        ShowCounter.jsp
          // スクリプトレットで値を取り出す。
          <%=request.getAttribute("counter")%>

step 3

EAR ファイルでのデプロイ

xxapp.ear:
+- *.jar    # EJB-JAR file
+- *.war    # WAR file
+- META-INF
   +- application.xml

application.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE application PUBLIC
"-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
"http://java.sun.com/dtd/application_1_3.dtd">

<application>
 <display-name>Counter application</display-name>

 <module>
   <ejb>sample-ejb.jar</ejb>
 </module>

 <module>
   <web>
     <web-uri>sample.war</web-uri>
     <context-root>/step3</context-root>
   </web>
 </module>

</application>

4.0.3SP1 ではやはり動かない...

4.0.3 の readme.html にある compatibility に関する記述を試してみる。

conf/jboss-service.xml
        <mbean code="org.jboss.naming.NamingService"
        name="jboss:service=Naming">
        <!-- The call by value mode. true if all lookups are unmarshalled
        using
        the caller's TCL, false if in VM lookups return the value by reference.
        -->
        <attribute name="CallByValue">''true''</attribute> // SET TO TRUE
        <!-- The listening port for the bootstrap JNP service. Set this to
        -1
        to run the NamingService without the JNP invoker listening port.
        -->
        ...
        </mbean>


deploy/ear-deployer.xml
     <server>
     <!-- EAR deployer, remove if you are not using ear deployments -->
     <mbean code="org.jboss.deployment.EARDeployer"
     name="jboss.j2ee:service=EARDeployer">
     <!-- A flag indicating if ear deployments should have their own scoped
     class loader to isolate their classes from other deployments.
     -->
     <attribute name="Isolated">true</attribute>    // SET TO TRUE
     <!-- A flag indicating if the ear components should have in VM call
     optimization disabled.
     -->
     <attribute name="CallByValue">true</attribute> // SET TO TRUE
     </mbean>
     </server>

では、STEP 2 はどうか?
こちらも動くようになった。

4.0 ベースのサンプルというか、書き方を探す必要あり。

step 4

ENC (環境ネーミングコンテクスト) モジュール毎に JNDI 空間を割り当てる方法
"java:comp/env"

詳細は面倒なのでまたの機会に

3章 Open Source による開発


Ant

特になし。

XDoclet

ひとつの Bean クラスのソースから、各種インターフェイスの java source, ejb-jar.xml, jboss.xml, jbosscmp-jdbc.xml 等を生成。

/**
 * カウンターを表すエンティティBeanです。
 *
 * @ejb.bean
 *   name="Counter"
 *   type="CMP"
 *   jndi-name="ejb/step5/counter"
 *   local-jndi-name="ejb/step5/counterLocal"
 *   primkey-field="name"
 *
 * @ejb.finder
 *   signature="Collection findAll()"
 *   description="すべてのカウンターを返す"
 *
 * @ejb.persistence table-name="step5"
 * @ejb.persistence create-table="${jboss.create.table}"
 * @ejb.persistence remove-table="${jboss.remove.table}"
 */
public abstract class CounterBean implements EntityBean {
  ..
  * @ejb.interface-method
  * @ejb.persistent-field
  */
  public abstract String getName();
 /**
  * 名前
  *
  * @param name 名前
  */
 public abstract void setName(String name);

 /**
  * カウンタ値
  *
  * @return カウンタ値
  * @ejb.interface-method
  * @ejb.persistent-field
  * @jboss.column-name name="cvalue"
  * use different column name for value property
  */
 public abstract long getValue();

 /**
  * カウンタ値
  *
  * @param value カウンタ値
  * @ejb.interface-method
  */
 public abstract void setValue(long value);
   :
  * @param name 名前
  * @param value カウンタ値
  * @return 名前
  * @ejb.create-method
  */
 public String ejbCreate(String name, long value) throws CreateException {
   if (name == null) {
     throw new CreateException("name is null");
   }
   setName(name);
   setValue(value);
   return null;
 }

ejbdoclet target の定義

 <!-- ==================== XDoclet ========================= -->

 <target name="ejbdoclet" depends="init">
   <delete dir="${build.gen}"/>
   <mkdir dir="${build.gen}"/>

   <!-- ejbdocletサブタスクの宣言 -->
   <taskdef
     name="ejbdoclet"
     classname="xdoclet.modules.ejb.EjbDocletTask"
     classpathref="ejbdoclet.classpath"/>

   <!-- ejbdocletの起動-->
   <ejbdoclet
     destdir="${build.gen}"
     excludedtags="@version,@author,@todo"
     ejbspec="${ejb.version}"
     mergedir="${project.root}/xdoclet"
     force="${xdoclet.force}"
     >
     <!-- Beanクラスファイルの指定 -->
     <fileset dir="${src.dir}">
       <include name="**/sample/ejb/*.java"/>
     </fileset>

     <!-- リモートインタフェースの生成 -->
     <remoteinterface/>
     <homeinterface/>

     <!-- ローカルインタフェースの生成 -->
     <localinterface/>
     <localhomeinterface/>

     <!-- セッションBeanクラスの生成 -->
     <session/>

     <!-- データオブジェクトクラスの生成 -->
     <dataobject pattern="{0}DTO"/>

     <!-- エンティティCMPクラスの生成 -->
     <entitycmp/>
     <!--        <entitypk/>-->
     <!--        <entityfacade/>-->
     <!--        <remotefacade/>-->
     <!--        <entitybmp/>-->
     <!--        <dao/>-->

     <!-- ユーティリティクラスの生成 -->
     <utilobject cacheHomes="true"/>

     <!-- デプロイメント記述子の生成 -->
     <deploymentdescriptor
       xmlencoding="${xml.encoding}"
       destdir="${build.dir}/META-INF"/>

     <!-- JBossデプロイメント記述子の生成 -->
     <jboss version="${jboss.version}"
       xmlencoding="${xml.encoding}"
       destdir="${build.dir}/META-INF"
       validateXml="false"/>
   </ejbdoclet>
 </target>

XDoclet は何かとっつきにくく、得体が知れないところがあり、積極的には
使ってこなかった。とはいえ、web.xml 等を見慣れてきたとはいえ、そらで
かけるわけではない。ここは慣れておいたほうがよさそう。

NetBean, Eclipse との連携



DTD に基づいた自動補完機能は活用していきたい。いくつか書きたい DTD もあるし。

section 4


build

build 出来るはずだが...

BUILD FAILED
E:\ghjbossbook\samples\chap4\build.xml:120: E:\ghjbossbook\samples\chap4
\${env.XDOCLET_HOME}\lib not found.

http://xdoclet.sourceforge.net/xdoclet/index.html
からダウンロードできるかとも思ったが、すでに展開してあったのでそこを指定。

conf/login-config.xml の変更

login、認証の種類、その付属情報の設定。このケースでは使用する DB の指定、
セレクト方法などを追加する。

load-data に -Dhsqldb.port=1701

port が 3.0.7 から変わったのかも


4.0.3 でもポートは 1701 の様だが、接続が出来ない。


BUILD FAILED
E:\ghjbossbook\samples\chap4\build.xml:358: java.sql.SQLException: socket  creati on error

E:\ghjbossbook\samples\chap4>java -cp c:\usr\local\jboss\server\default\lib\hsqldb.jar org.hsqldb.util.DatabaseManager

jdbc:hsqldb:hsql://localhost:1701 に接続しようとすると SQLException が
発生する。

DefaultDS で conf 以下を検索。 standardjbosscmp-jdbc.xml に気になる記述を
見つける


  <defaults>
     <datasource>java:/DefaultDS</datasource>
     <!-- optional since 4.0 <datasource-mapping>Hypersonic SQL</datasource-mapping> -->

     <create-table>true</create-table>
     <remove-table>false</remove-table>
     <read-only>false</read-only>
     <read-time-out>300000</read-time-out>

3.2.0 では

  <defaults>
     <datasource>java:/DefaultDS</datasource>
     <datasource-mapping>Hypersonic SQL</datasource-mapping>
     
     <create-table>true</create-table>
     <remove-table>false</remove-table>
     <read-only>false</read-only>

4.0.3 の datasource-mapping を有効にすることで直りそうだが、では、DefaultDS
はどうなっているのか? JBoss のマニュアルをよく読まないと...


コメントをはずしても依然として接続できない。

たしか、docs/examples/jca の下の *-ds.xml を元にデータソースの定義を
deploy かどこかに作る必要があったはず。

hsqldb-ds.xml は deploy にあったが次の行がコメントになっていた。
コメントをはずす。

<connection-url>jdbc:hsqldb:hsql://localhost:1701</connection-url>

しかし、それでもだめ。
起動時にクライアントサイドのコードが起動され SQLException に至る物が
多数表示されるようになった。

hsqldb-jdbc3-service.xml を deploy にコピーしてみてもだめ

standardjbosscmp-jdbc.xml から datasource-mapping をはずす。
hsqldb-ds.xml から connection-url をはずす。

これで元に戻ったはず。
もう一度、関連する xml ファイルを見直してみる。hsqldb-ds.xml 後半に次の
ようなブロックがある。

  <!-- This mbean should be used only when using tcp connections. Uncomment
  when the tcp based connection-url is used. 
  <mbean code="org.jboss.jdbc.HypersonicDatabase" 
    name="jboss:service=Hypersonic">
    <attribute name="Port">1701</attribute>
    <attribute name="Silent">true</attribute>
    <attribute name="Database">default</attribute>
    <attribute name="Trace">false</attribute>
    <attribute name="No_system_exit">true</attribute>
  </mbean>
  -->

standardjbosscmp-jdbc.xml で datasource-mapping を有効に、
hsqldb-ds.xml で connection-url を有効にし、上記ブロックも有効にする。

再起動すると今回は HSQLDB connect のスタックとレースは出ない。
DatabaseManager からもコネクトできる。

ここで、再度 ant load-data を実行。今度は成功!

book-lib を再デプロイ

console に EJB-QL のエラーがでた

01:11:15,027 WARN  [ServiceController] Problem starting service jboss.j2ee:jndiName=ejb/library/pass,service=EJB
org.jboss.deployment.DeploymentException: Error compiling EJB-QL statement ''; - nested throwable: (org.jboss.ejb.plugins.cmp.ejbql.ParseException: FROM not found)
       at org.jboss.ejb.plugins.cmp.jdbc.JDBCEJBQLQuery.<init>(JDBCEJBQLQuery.java:52)
       at org.jboss.ejb.plugins.cmp.jdbc.JDBCCommandFactory.createEJBQLQuery(JDBCCommandFactory.java:60)
       at org.jboss.ejb.plugins.cmp.jdbc.JDBCQueryManager.start(JDBCQueryManager.java:272)
       at org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.startStoreManager(JDBCStoreManager.java:490)
       at org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.start(JDBCStoreManager.java:381)
       ...

ログインを試みると成功。

しかし、図書サービスは発注を除きすべてエラーになる。

exception 

javax.servlet.ServletException
library.book.web.LibraryServlet.getDestinationPage(LibraryServlet.java:64)
library.book.web.LibraryServlet.doGet(LibraryServlet.java:39)
javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)


root cause 

library.book.web.LibrarySystemException
library.book.web.LibraryBusinessDelegate.listBooks(LibraryBusinessDelegate.java:137)
library.book.web.ListBooksAction.perform(Configuration.java:113)
library.book.web.LibraryServlet.performAction(LibraryServlet.java:73)
library.book.web.LibraryServlet.getDestinationPage(LibraryServlet.java:60)
library.book.web.LibraryServlet.doGet(LibraryServlet.java:39)

 public Collection listBooks() throws LibrarySystemException {
   try {
     return getBookSearch().listBooks(); <--- ???
   } catch (Exception e) {
     throw new LibrarySystemException(e);
   }
 }

server.log からさかのぼると、たどることの出来るもっとも深い例外は

java.rmi.ServerException: EJBException:; nested exception is: 
javax.ejb.EJBException: null; CausedByException is:
Could not instantiate bean; CausedByException is:
createBeanClassInstanceCommand == null; CausedByException is:
Could not instantiate bean; CausedByException is:
createBeanClassInstanceCommand == null
at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:352)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:196)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:624)
at org.jboss.ejb.Container.invoke(Container.java:873)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:141)
at org.jboss.mx.server.Invocation.dispatch(Invocation.java:80)
at org.jboss.mx.server.Invocation.invoke(Invocation.java:72)
at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:245)
at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:644)
at org.jboss.invocation.local.LocalInvoker$MBeanServerAction.invoke(LocalInvoker.java:155)
at org.jboss.invocation.local.LocalInvoker.invoke(LocalInvoker.java:104)
at org.jboss.invocation.InvokerInterceptor.invokeMarshalled(InvokerInterceptor.java:201)
at org.jboss.invocation.MarshallingInvokerInterceptor.invoke(MarshallingInvokerInterceptor.java:35)
at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46)
at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:55)
at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:97)
at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:86)
at $Proxy87.listBooks(Unknown Source)
at library.book.web.LibraryBusinessDelegate.listBooks(LibraryBusinessDelegate.java:135)
at library.book.web.ListBooksAction.perform(Configuration.java:113)

おそらく、EJB-QL の問題を解決すれば直るのだろうが、今日は時間切れ。

なれと経験の問題だろうが、何をやるにもわかりにくいし面倒くさい。
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。