WTPを使って開発をすると、JBossへデプロイすることができるだけでなく、jboss.xmlやjboss-web.xml,web.xmlやejb-jar.xmlを自動生成することができます。さらにはEJBの実装クラスを作成するだけで、めんどくさいその他のインタフェースファイルなども自動生成することができます。自動生成にはXDocletという、JavaDoc?コメントから各種設定ファイルを生成するツールが使われています。
今回はJBossの環境を主においているので、JBossの設定ファイルを自動生成する用に設定しました。設定といっても簡単で、Eclipse上で、
ウィンドウ > 設定 >> J2EE注釈 >> XDoclet
でXDocletのホームディレクトリなどを入れておくだけです*1。
JBossなどコンテナ依存の設定ファイルは、更に下の
XDoclet >> ejbdoclet XDoclet >> webdoclet
などのチェックを入れておけばよいようです。
コンテナ上のEJBビジネスロジックを使用するServlet*2は以下のようにしました。
/** * Servlet implementation class for Servlet: HogeServlet * * @web.servlet name="HelloServlet" display-name="HelloServlet" * * @web.servlet-mapping url-pattern="/hello" * @web.ejb-ref name = "ejb/HelloEJB" home = "hello.HelloEJBHome" remote = * "hello.HelloEJB" type = "Session" * @jboss.ejb-ref-jndi jndi-name = "HelloEJBHoge" ref-name = "ejb/HelloEJB" */ public class HelloServlet extends HttpServlet { private HelloHome home = null; public void init(ServletConfig config) throws ServletException { Context context; try { context = new InitialContext(); } catch (NamingException e) { throw new ServletException("JNDI InitialContextが取得できません."); } try { Object boundObject = context.lookup("java:comp/env/ejb/HelloEJB"); home = (HelloHome) PortableRemoteObject.narrow(boundObject, HelloHome.class); } catch (NamingException e) { throw new ServletException("Homeインタフェースが取得できません."); } super.init(config); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String ejbMessage; try { Hello remote = home.create(); ejbMessage = remote.sayHello(); System.out.println("ejbMessage = " + ejbMessage); } catch (Exception e) { ejbMessage = e.toString(); } request.setAttribute("ejbMessage", ejbMessage); getServletContext().getRequestDispatcher("/HelloClient.jsp").forward( request, response); } }
このうちクラスコメントの
@web.servlet name="HelloServlet" display-name="HelloServlet" @web.servlet-mapping url-pattern="/hello"
の部分で、
<servlet> <servlet-name>HelloServlet</servlet-name> <- @web.servlet name="HelloServlet" <display-name>HelloServlet</display-name> <- display-name="HelloServlet" <servlet-class>hello.web.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> <- @web.servlet-mapping url-pattern="/hello" </servlet-mapping>
というweb.xmlが出力されます。
@web.ejb-ref name = "ejb/HelloEJB" home = "hello.HelloEJBHome" remote = "hello.HelloEJB" type = "Session"
の部分で
<ejb-ref > <ejb-ref-name>ejb/HelloEJB</ejb-ref-name> <- @web.ejb-ref name = "ejb/HelloEJB" <ejb-ref-type>Session</ejb-ref-type> <- type = "Session" <home>hello.HelloEJBHome</home> <- home = "hello.HelloEJBHome" <remote>hello.HelloEJB</remote> <- remote = "hello.HelloEJB" </ejb-ref>
というweb.xmlが出力されます。
また先の
@jboss.ejb-ref-jndi jndi-name = "HelloEJBHoge" ref-name = "ejb/HelloEJB"
の部分で、
<ejb-ref> <ejb-ref-name>ejb/HelloEJB</ejb-ref-name> <- ref-name = "ejb/HelloEJB" <jndi-name>HelloEJBHoge</jndi-name> <- @jboss.ejb-ref-jndi jndi-name = "HelloEJBHoge" </ejb-ref>
というjboss-web.xmlが出力されます。
EJBのビジネスロジックは以下のようにしました。
/* * Enterprise Bean */ package hello.ejb; import java.rmi.RemoteException; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; /** * * @version $Revision: 1.3 $ * @ejb.bean name="HelloEJB" display-name = "HelloEJB" jndi-name="HelloEJBHoge" * type = "Stateless" view-type = "remote" * @ejb.interface remote-class="hello.ejb.Hello" * @ejb.home remote-class="hello.ejb.HelloHome" */ public class HelloBean implements SessionBean { /** * @return * @throws RemoteException * @ejb.interface-method view-type= "remote" */ public String sayHello() throws RemoteException { System.out.println("hoge"); return "Hello EJB !"; } public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException { } public void ejbRemove() throws EJBException, RemoteException { } public void ejbActivate() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } }
このうちクラスコメントの
@ejb.bean name="HelloEJB" display-name = "HelloEJB" jndi-name="HelloEJBHoge" type = "Stateless" view-type = "remote" @ejb.interface remote-class="hello.ejb.Hello" @ejb.home remote-class="hello.ejb.HelloHome"
の部分で、
<session > <description><![CDATA[]]></description> <display-name>HelloEJB</display-name> <- display-name = "HelloEJB" <ejb-name>HelloEJB</ejb-name> <- @ejb.bean name="HelloEJB" <home>hello.ejb.HelloHome</home> <- @ejb.home remote-class="hello.ejb.HelloHome" <remote>hello.ejb.Hello</remote> <- @ejb.interface remote-class="hello.ejb.Hello" <ejb-class>hello.ejb.HelloEJBSession</ejb-class> <session-type>Stateless</session-type> <- type = "Stateless" <transaction-type>Container</transaction-type> </session>
というejb-jar.xmlが出力されます。
また
<session> <ejb-name>HelloEJB</ejb-name> <- @ejb.bean name="HelloEJB" <jndi-name>HelloEJBHoge</jndi-name> <- jndi-name="HelloEJBHoge" また、実際にコンテナにデプロイされる実際の(?)JNDI名 <method-attributes> </method-attributes> </session>
もあわせて出力されます。
上のXDocletの記述で
のファイルも併せて自動生成されます。
また、この場合のビジネスロジックのインタフェースであるhello.ejb.Helloインタフェースに、
public java.lang.String sayHello( ) throws java.rmi.RemoteException;
が定義されていますが、これは
/** * @return * @throws RemoteException * @ejb.interface-method view-type= "remote" */ public String sayHello() throws RemoteException { System.out.println("hoge"); return "Hello EJB !"; }
の
@ejb.interface-method view-type= "remote"
によって出力されます。
使ってみてわかるのが、EJBのめんどくさいいろいろなインタフェースを書かなくても、XDocletが自動でいろいろ生成してくれることがわかります。このアプローチはEJB3.0でも全面的に採用されていて、JavaDoc?のコメントがAnnotationになるなどいろいろ洗練されて実装されるようです。
XDocletを使った場合、ユーティリティクラスHelloEJBUtilクラスも生成されます。このユーティリティクラスはHomeインタフェースをキャッシュして返すなど便利なメソッドを提供してくれます。具体的には、通常
Object boundObject = context.lookup("java:comp/env/ejb/HelloEJB"); home = (HelloHome) PortableRemoteObject.narrow(boundObject,HelloHome.class);
とやっているところを、
home = HelloEJBUtil.getHome();
とすることができます。またPropertiesクラスを渡して、InitialContext?を初期化することもできます。こんな感じです。
Properties props = new Properties(); props.put(Context.PROVIDER_URL, "localhost:1099"); home = HelloEJBUtil.getHome(props);
Welcomeファイルの場所やcontext-paramなど、ココのファイルに依存しない情報はどこに書くのかよくわからなかったのですが、XDocletにはマージという概念があるようです。詳細はXDocletを使った設定ファイルなどの作成の効率化を参照のこと。
この記事は
現在のアクセス:13654