Oracle Containers for J2EE サーブレット開発者ガイド 10g(10.1.3.1.0) B31859-01 |
|
動的Webアプリケーションは、通常、コンテンツを提供するために、データベースにアクセスします。この章では、データベース接続性のJava標準APIであるJDBCをサーブレットで使用する方法について説明します。また、Enterprise JavaBeansの概要も示します。Enterprise JavaBeansは、サーバー・サイド・ビジネス・ロジックを実行したり、アプリケーションのデータ永続性を管理するために、サーブレットからコールすることができます。この章には、次の項が含まれます。
サーブレットは、JDBCドライバを使用してデータベースにアクセス可能です。JDBCの使用方法としては、データベース接続にOC4Jデータソースを使用し、Java Naming and Directory Interface(JNDI)を使用してデータソースをルックアップすることをお薦めします。次の項では、関連する基本手順を説明し、この機能の例を示します。
JDBCの詳細は、『Oracle Database JDBC開発者ガイドおよびリファレンス』を参照してください。
サーブレットの利点の1つに、データベースからデータを取得して動的出力を作成できる点があげられます。サーブレットは、データベースから情報を取得して動的HTMLを生成してそれをクライアントに返すことや、HTTPリクエスト内でサーブレットに渡された情報に基づいてデータベースを更新することが可能です。
JDBCは、データベースにアクセスするための標準Javaメカニズムです。
注意
|
データベース接続には、通常、標準データソースが使用されます。この項では、JNDIによって使用できるデータソースを構成する手順を説明します。
データソースとそのOC4Jでの構成の詳細は、『Oracle Containers for J2EEサービス・ガイド』を参照してください。
データソースを使用するには、データソースを主要OC4Jデータソース構成に追加する必要があります。一般に、この手順は、Oracle Enterprise Manager 10g Application Server Controlを使用して実行します。
Application Server Controlコンソールで、次の手順を実行します。
データソースを構成すると、次のフォームに従って、j2ee/home/config/data-sources.xml
ファイルのエントリが(この例では、Oracle JDBCシン・ドライバを使用するために)新しく追加または更新されます。次の点に注意してください。
<connection-pool>
要素は、JDBC接続プール用の設定を持ち、プールの名前を指定します。(接続プール機能は、接続オブジェクトの既存のプールから接続を取得して、新しい接続オブジェクトを作成するオーバーヘッドを回避することにより、パフォーマンスを向上させます。)
<connection-pool>
の<connection-factory>
サブ要素は、接続のファクトリ(この場合、通常、データソースを表すクラス)として使用するクラスとデータベース・ユーザー名、パスワードおよび接続文字列を指定します。
<managed-data-source>
要素は、データソースの名前(name
)とJNDIの場所(jndi-name
)を指定し、<connection-pool>
要素で指定された接続プールを参照します。
「問合せサーブレットのデータソースの構成」の例を参照してください。
<data-sources ... > <connection-pool name="poolname"> <connection-factory factory-class="package.Classname" user="user" password="password" url="jdbc:oracle:thin:@host:port/service"/> </connection-pool> <managed-data-source connection-pool-name="poolname" jndi-name="jndiname" name="name"/> </data-sources>
データソースおよびJNDIルックアップを使用するには、web.xml
ファイルに適切なリソース参照エントリも存在する必要があります。次に、前の項で示したデータソース構成の例に対応する例を示します。
<resource-ref> <res-auth>Container</res-auth> <res-ref-name>jdbc/OracleDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> </resource-ref>
これにより、データソースとして使用するために、jdbc/OracleDS
リソースがDataSource
タイプであることが確立されます。
この項では、サーブレット・コードでJDBCによってデータベースにアクセスする一般的な手順を示します。 例の全体は、「問合せサーブレットの作成」を参照してください。
java.io
パッケージに加えて、JDBC、データソースおよびJNDIのクラスを含むパッケージが存在します。
import javax.servlet.*; import javax.servlet.http.*; import javax.naming.*; // for JNDI import javax.sql.*; // extended JDBC interfaces (such as data sources) import java.sql.*; // standard JDBC interfaces import java.io.*;
init()
メソッドをtry...catch
ブロック内に実装します。 このルックアップは、「データソースおよびリソース参照の構成」で示した例に対応します。
public void init() throws ServletException { try { InitialContext ic = new InitialContext(); // JNDI initial context ds = (DataSource) ic.lookup("jdbc/OracleDS"); // JNDI lookup conn = ds.getConnection(); // database connection through data source } catch (SQLException se) { throw new ServletException(se); } catch (NamingException ne) { throw new ServletException(ne); } }
do
XXX
()
メソッド(doGet()
など)を実装し、JDBCを使用して必要なSQL操作を実行します。この例では、SQL問合せ文字列が文字列のquery
で構成されているものとします。コードは、JDBC文オブジェクトを作成し、問合せを実行し、データ・レコードを出力するために結果セットを調べて(ここでout
はPrintWriter
オブジェクト)、文および結果セット・オブジェクトをクローズします。SQL操作も、try...catch
ブロック内で実行されます。
try { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { out.println(rs.getString(1) + rs.getInt(2)); } rs.close(); stmt.close(); } catch (SQLException se) { se.printStackTrace(out); }
destroy()
メソッドを(同じくtry...catch
ブロック内に)実装します。
public void destroy() { try { conn.close(); } catch (SQLException se) { se.printStackTrace(); } }
この例には、次の問合せを完成するLIKE
仕様の入力をユーザーに求めるHTML「ようこそ」ページが含まれています。
SELECT ename, empno FROM emp WHERE ename LIKE xxx
「ようこそ」ページは、問合せを実行して結果を出力するサーブレットを起動します。
次の項で、例の実装および構成方法を示します。
次に、この例のデータソース構成を示します。この構成は、OC4Jのdata-sources.xml
ファイルに反映されており、Application Server Controlコンソールを使用して構成できます(「データソースの構成」を参照)。この例は、Oracle JDBCシン・ドライバを使用し、ポート5521
経由で、ホストmyhost
上のデータベースにアクセスします。その際、サービス名myservice
を使用し、ユーザーscott
として接続します。(これは単純化された例です。data-sources.xml
でのパスワードの公開を避ける方法もあります。)またこの例では、接続プール、および接続の取得先のデータソースを表すクラスOracleDataSource
を使用します。jndi-name
エントリのjdbc/OracleDS
は、データソースのJNDIルックアップのためにサーブレットによって使用されます。
<data-sources> <connection-pool name="ConnectionPool1"> <connection-factory factory-class="oracle.jdbc.pool.OracleDataSource" url="jdbc:oracle:thin:@myhost:5521/myservice" user="scott" password="tiger"/> </connection-pool> <managed-data-source connection-pool-name="ConnectionPool1" jndi-name="jdbc/OracleDS" name="OracleDS"/> </data-sources>
次に、「ようこそ」ページのempinfo.html
を示します。このページは、ユーザーに問合せの完成を求め、問合せサーブレットを起動します。この例の場合、サーブレットは、/myquery/getempinfo
というコンテキスト・パスおよびサーブレット・パスで起動されるようにデプロイされます。
<html> <head> <title>Query the Employees Table</title> </head> <body> <form method=GET ACTION="/myquery/getempinfo"> The query is<br> SELECT ename, empno FROM emp WHERE ename LIKE xxx <p> Specify the WHERE clause xxx parameter.<br> Enclose entry in single-quotes; use % for wildcard. Search is case-sensitive.<br> Example: 'S%' (for all names starting with 'S').<br> <input type=text name="queryVal"> <p> <input type=submit> </form> </body> </html>
次に、「JDBCコールの実装」で示した手順を実装する問合せサーブレットのGetEmpInfo
を示します。この例には、出力されるHTML表の書式設定と、取得された行の数のカウンタも含まれています。
import javax.servlet.*; import javax.servlet.http.*; import javax.naming.*; // for JNDI import javax.sql.*; // extended JDBC interfaces (such as data sources) import java.sql.*; // standard JDBC interfaces import java.io.*; public class GetEmpInfo extends HttpServlet { DataSource ds = null; Connection conn = null; public void init() throws ServletException { try { InitialContext ic = new InitialContext(); // JNDI initial context ds = (DataSource) ic.lookup("jdbc/OracleDS"); // JNDI lookup conn = ds.getConnection(); // database connection through data source } catch (SQLException se) { throw new ServletException(se); } catch (NamingException ne) { throw new ServletException(ne); } } public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /* Get the LIKE specification for the WHERE clause from the user, through the */ /* HTTP request, then construct the SQL query. */ String queryVal = req.getParameter("queryVal"); String query = "select ename, empno from emp " + "where ename like " + queryVal; resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.println("<html>"); out.println("<head><title>GetEmpInfo Servlet</title></head>"); out.println("<body>"); /* Create a JDBC statement object and execute the query. */ try { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); /* HTML table formatting for the output. */ out.println("<table border=1 width=50%>"); out.println("<tr><th width=75%>Last Name</th><th width=25%>Employee " + "ID</th></tr>"); /* Loop through the results. Using ResultSet getString() and */ /* getInt() methods to retrieve the individual data items. */ int count=0; while (rs.next()) { count++; out.println("<tr><td>" + rs.getString(1) + "</td><td>" +rs.getInt(2) + "</td></tr>"); } out.println("</table>"); out.println("<h3>" + count + " rows retrieved</h3>"); rs.close(); stmt.close(); } catch (SQLException se) { se.printStackTrace(out); } out.println("</body></html>"); } public void destroy() { try { conn.close(); } catch (SQLException se) { se.printStackTrace(); } } }
サーブレットの構成に加えて、web.xml
ファイルには、データソースのリソース参照エントリが含まれている必要があります。また、初期ファイルとしてempinfo.html
を宣言するための構成も含まれています。次に、この例のファイルを示します。
<?xml version="1.0" ?> <!DOCTYPE web-app (doctype...)> <web-app> <servlet> <servlet-name>empinfoquery</servlet-name> <servlet-class>GetEmpInfo</servlet-class> </servlet> <servlet-mapping> <servlet-name>empinfoquery</servlet-name> <url-pattern>getempinfo</url-pattern> </servlet-mapping> <resource-ref> <res-auth>Container</res-auth> <res-ref-name>jdbc/OracleDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> </resource-ref> <welcome-file-list> <welcome-file>empinfo.html</welcome-file> </welcome-file-list> </web-app>
この例のWARファイル(empinfo.war
)は、次のコンテンツと構造を持ちます。
empinfo.html META-INF/Manifest.mf WEB-INF/web.xml WEB-INF/classes/GetEmpInfo.class WEB-INF/classes/GetEmpInfo.java
また、EARファイルは、次のとおりです。
empinfo.war META-INF/Manifest.mf META-INF/application.xml
(Manifest.mf
ファイルは、JARユーティリティにより自動的に作成されます。)
この例では、application.xml
がコンテンツ・パスの/myquery
をempinfo.war
にマップするものとします。この場合、デプロイ後に、次のように、「ようこそ」ページのempinfo.html
を起動することができます(web.xml
でempinfo.html
が「ようこそ」ページとして宣言されている必要があります)。
http://host:port/myquery
テスト実行では、Sで始まるすべての名前を検索するために'S%'
を指定します。
テスト実行に使用されたデータベースの場合は、これにより、2つのエントリが返されました。
サーブレットは、Oracle TopLinkを使用してJ2EE永続性をアプリケーションに提供します。 Oracle Technology Networkの次のWebサイトで、TopLinkサーブレットの例を参照できます。
http://www.oracle.com/technology/products/ias/toplink/examples/index.html
サーブレットでは、Enterprise JavaBeansをコールして、データベースにアクセスすることや、追加のビジネス・ロジックを実行することができます。次の項で、EJBの概要と、サーブレットからのEJBの使用を説明します。
EJBの機能の詳細と、Oracle Application Server環境でのサーブレットとEJBに関する例は、『Oracle Containers for J2EE Enterprise JavaBeans開発者ガイド』を参照してください。
EJBには、サーバー・サイド・ビジネス・ロジックに使用するセッションBeanやデータ永続性を管理するためのエンティティBeanなど、ビジネス・アプリケーションにおいて多くの用途があります。EJBテクノロジは、トランザクションによるセキュアなサーバー・サイド処理で使用するための、JSPまたはサーブレット・テクノロジよりも堅牢なインフラストラクチャを提供します。
一般的なアプリケーション設計では、サーブレットは、HTTPリクエストを処理するフロントエンド・コントローラとして使用され、EJBは、データベースへのアクセスと更新を行うためにコールされ、最後に、別のサーブレットまたはJSPページが、リクエスタのデータを表示するために使用されます。
EJBには、セッションBean、エンティティBeanおよびメッセージドリブンBeanという3つのカテゴリがあります。特に、コンテナ管理の永続性エンティティBeanは、永続データの管理に適しています。これは、データベースにアクセスする際にJDBC APIを直接使用する必要がなくなるためです。かわりに、EJBコンテナで透過的にデータベース操作を処理できます。
セッションBeanは、ビジネス・ロジックのモデリングに役立ちます。また、ステートレスまたはステートフルのいずれかになります。ステートフルなBeanは、一般に、トランザクション状態がメソッド・コールまたはサーブレット・リクエスト間で維持される必要がある場合に使用されます。ステートレスなBeanには、アプリケーション状態とは関係のない個別のビジネス・ロジック・メソッドが含まれます。
OC4Jは、セッションBean、エンティティBeanおよびメッセージドリブンBeanを完全にサポートしています。エンティティBean実装は、Bean管理の永続性(BMP)、コンテナ管理の永続性(CMP)、ローカル・インタフェース、コンテナ管理の関連性、およびEJB問合せ言語による問合せ実行機能を提供します。
エンティティBean実装内では、基本永続性マネージャが単純マッピングと複合マッピングの両方をサポートし、1対1、1対多、多対1および多対多オブジェクト・リレーショナル・マッピングがサポートされます。また、エンティティBeanのフィールドが対応するデータベース表に自動的にマップされます。
アプリケーションのメンテナンスとデプロイを容易にするために、Oracle Application Serverは、動的EJBスタブ生成などの多数の拡張機能を提供します。CORBA相互運用性は、EJBを構築し、CORBAサービスとしてCORBAクライアントからEJBにアクセスする機能を提供します。
サーブレットからのEJBのコールには、3つの使用例があります。
サーブレットとEJB間の通信では、ローカルおよびリモートEJBコールにJNDIが使用されます。リモート・ルックアップが実行される場合、JNDIは、OracleによるRMI実装(ORMI)または標準で相互操作可能なInternet Inter-ORB Protocol(IIOP)のいずれかを使用します。3.0よりも古いバージョンのEJBでは、ホーム・インタフェースのみがJNDIルックアップを必要としました。その後は、アプリケーションが使用するEJBを作成するために使用されています。J2EEコンポーネントは、デフォルトのno-args
コンストラクタを使用して、同じアプリケーション内のオブジェクトをルックアップできます。リモート・ルックアップには、RMIInitialContextFactory
またはIIOPInitialContextFactory
クラスを使用できます。 OC4JのJNDIの詳細は、『Oracle Containers for J2EEサービス・ガイド』を参照してください。
リモート・ルックアップを行うには、JNDI環境を設定する必要があります。これには、URL、ユーザー名およびパスワードが含まれます。この設定は、通常はサーブレット・コードで行われますが、同一アプリケーション内のルックアップでは、rmi.xml
ファイル内で設定される場合もあります。
同一アプリケーション内の、異なるホストでのリモート・ルックアップの場合、各ホストで、アプリケーションのOC4J EJB remote
フラグを正しく設定する必要もあります。 「リモート・フラグによる同一アプリケーション内のリモート・ルックアップ」を参照してください。
EJBが使用されているすべてのアプリケーションと同様、ejb-jar.xml
ファイルに、EJBごとにエントリが含まれている必要があります。
EJB仕様の初期バージョンでは、EJBには、必ず、javax.ejb.EJBObject
インタフェースを拡張するリモート・インタフェースとjavax.ejb.EJBHome
インタフェースを拡張するホーム・インタフェースが備わっています。このモデルでは、すべてのEJBはリモート・オブジェクトとして定義されているため、サーブレットまたは別のコール元モジュールがEJBと同じ場所へ配置されている場合は、EJBコールに不要なオーバーヘッドが追加されます。
より新しいバージョンのEJB仕様は、同じ場所に配置されているEJBコールのローカル・インタフェースをサポートしています。この場合、EJBには、リモート・インタフェースではなく、javax.ejb.EJBLocalObject
インタフェースを拡張するローカル・インタフェースが備わっています。そして、ホーム・インタフェースではなく、javax.ejb.EJBLocalHome
インタフェースを拡張するローカル・ホーム・インタフェースが指定されます。
EJBリモート・インタフェースが関連するルックアップはRMIを使用するため、セキュリティなどの理由でオーバーヘッドが追加されます。ローカル・インタフェースを使用すると、RMIやその他のオーバーヘッドが回避されます。
OC4Jでは、リモートEJBルックアップを同一アプリケーションの異なる層で実行する場合(同一アプリケーションが両方の層でデプロイされている)、OC4J EJBのremote
フラグを各層で正しく設定する必要があります。サーバーでフラグがtrue
に設定されている場合、Beanは、ローカル・サーバーで使用されているEJBサービスではなく、リモート・サーバーでルックアップされます。
remote
フラグは、orion-application.xml
ファイルにある<orion-application>
要素のサブ要素<ejb-module>
内の属性にマップします。デフォルトの設定は、remote="false"
です。ファイルを更新して、次のように、このフラグをtrue
に設定してください。
<orion-application ... > ... <ejb-module remote="true" ... /> ... </orion-application>
(Oracle Enterprise Manager 10g Application Server Controlでこのフラグを設定することはできません。)
false
のリモート・フラグ値でアプリケーションのEARファイルを両サーバーにデプロイしてから、サーブレット層であるサーバー1でリモート・フラグ値をtrue
に設定できます。図8-1にこれを示します。
サーバー2でEJBを検索するようにOC4Jを設定するには、サーバー2をリモート・ホストとして正しく構成する必要があります。次のように、サーバー1のrmi.xml
ファイルの該当する<rmi-server>
要素の<server>
サブ要素で、host
、port
、username
およびpassword
設定を指定してください。
<rmi-server ... > ... <server host="remote_host" port="remote_port" username="user_name" password="password" /> ... </rmi-server>
リモート・ホストおよびremote
フラグの使用方法の詳細は、『Oracle Containers for J2EE Enterprise JavaBeans開発者ガイド』を参照してください。
|
![]() Copyright © 2006 Oracle Corporation. All Rights Reserved. |
|