技評のJBoss入門

「技評のJBoss入門」の編集履歴(バックアップ)一覧はこちら

技評のJBoss入門」(2006/03/20 (月) 01:47:23) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

* 技評の 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 による開発 [#ba374075] *** 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 との連携 http://jboss.sourceforge.net/jbosside/updates 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 の問題を解決すれば直るのだろうが、今日は時間切れ。 なれと経験の問題だろうが、何をやるにもわかりにくいし面倒くさい。
* 技評の 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 との連携 http://jboss.sourceforge.net/jbosside/updates 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 もご覧ください。