Ajax4JSFを利用したデータ検証はじめにAJAX(Asynchronous JavaScript and XML)テクノロジは、Webアプリケーションのユーザーインターフェースの使い勝手と柔軟性を高め、使用する帯域幅を最小限に抑えることのできる技術です。AJAXはJavaScriptとドキュメントオブジェクトモデル(DOM)とXMLHttpRequestに基づいており、Webページをサーバに送信することなくブラウザとサーバとの間で動的にXMLを転送できるWebテクニックとして使われています。 AJAXの「A」にあたる「非同期(Asynchronous)」という用語には、サーバ上でXMLHttpRequestを処理してブラウザクライアントに応答を返すまでの間も、Webページの処理が継続して行われるという意味が含まれています。AJAXは、オートコンプリート機能(1つのフィールドに入力が行われたときに、対応する既存の情報をフォームに自動的に読み込む機能)、動的フォーム検証、Webページ全体の再読み込みを必要としないページセクションやページ領域の定期的な更新など、さまざまな機能に応用されています。 JSF(JavaServer Faces)テクノロジは、J2EE(Java 2 Platform Enterprise Edition)アプリケーションのフロントエンドであるユーザーインターフェース(UI)を開発するための一連のコンポーネントを提供します。Ajax4JSFというオープンソースフレームワークを使用すると、JavaScriptを必要とせずにJSFアプリケーションにAJAX機能を追加できます。 Ajax4JSFのコンポーネントライブラリを使用すると、JSFページ全体でAJAX機能を利用できるようになります。Ajax4JSFは、アクションと値の変更リスナに加えて、JSFフレームワークのサーバ側検証および変換機能をサポートします。また、イメージやカスケーディングスタイルシート(CSS)などの静的および動的リソースの管理と、Faceletsフレームワークもサポートします。Ajax4JSFを使用するには、次のツールをインストールしておく必要があります。
ページ上のイベントによってAJAX要求が起動すると、ページの指定領域がAJAX応答で更新されます。 それでは、Ajax4JSFフレームワークについて詳しく見ていきましょう。「web.xml」ファイルにはJSF要求とAJAX要求を区別するAjaxフィルタが登録されています。JSF要求の場合は、JSFページ全体がJSFコンポーネントツリーと同期します。これに対してAJAX要求の場合は、AJAX応答で更新されるのは ブラウザからサーバにAJAX要求を送信するには、AJAXアクションコンポーネント(AjaxCommandButton、AjaxCommandLink、およびAjaxSupport)を使用します。 Ajaxコンテナは、AJAX要求時にデコードされ、AJAX応答で更新されるJSFページ上の領域です。JavaScriptエンジンはクライアント側で実行され、AJAX要求に応じてJSFページのさまざまな領域を更新します。 Ajax4JSFには、JSFでAJAX機能を実装するためのコンポーネントライブラリが用意されています。表1に、よく使用されるコンポーネントを示します。 Ajax4JSFコンポーネント ![]() 動的検証の設定JSF UIコンポーネントとAjax4JSFフレームワークを利用して、ユーザーがデータを入力するときに動的検証を行うアプリケーションを作成します。このサンプルアプリケーションでは、フォームはカタログエントリを作成するインターフェースとして動作し、カタログエントリはデータベーステーブルに格納されます。各カタログエントリにはCatalog IDと呼ばれる一意なフィールドがあり、各レコードには、雑誌名、発行元、エディション、記事タイトル、および著者に対応するフィールドがあります。 AJAX Webテクニックを使用すると、ID値が有効かどうかを動的に検証できます。AJAXを使用せずにこの類の検証を実行するには、フォーム全体をサーバに送信して、特定のIDが存在するかどうかを確認しなければなりません。特定のIDが既にデータベースにある場合、そのIDを新しいIDとして使用することはできないため、フォームを別のID値で再送信する必要があります。 AJAXを使用すると、Catalog IDフィールドへの値の入力時に、ID値を動的に検証できます。今回のサンプルアプリケーションでは、カタログレコードをOracleデータベースに格納します。従って、このサンプルを自分で試す場合は、Oracle Database 10gをサンプルスキーマ付きでインストールし、ORCLという名前のデータベースインスタンスを作成しておいてください。次のSQLスクリプトを使ってデータベーステーブルを作成できます。 CREATE TABLE OE.Catalog(CatalogID VARCHAR(25) PRIMARY KEY, Journal VARCHAR(25), Publisher VARCHAR(25), Edition VARCHAR(25), Title Varchar(255), Author Varchar(25)); INSERT INTO OE.Catalog VALUES('catalog1', 'Oracle Magazine', 'Oracle Publishing', 'July-August 2006', 'Evolving Grid Management', 'David Baum'); INSERT INTO OE.Catalog VALUES('catalog2', 'Oracle Magazine', 'Oracle Publishing', 'July-August 2005', 'Tuning Undo Tablespace', 'Kimberly Floss'); JDeveloper 10.1.3.2をインストールすることもお勧めします。このバージョンはJSF 1.1をサポートしています。Ajax4JSFのバイナリディストリビューションZIPファイル(ajax4jsf-1.0.6-binary.zip)をダウンロードし、展開します。 それでは、実際にJSFアプリケーションを作成し、Ajax4JSFフレームワークを使ってこのアプリケーションにAJAX機能を追加しましょう。このJSFアプリケーションは、カタログレコードの簡単な入力フォームから成ります。前に説明したように、フォームには一意のCatalog IDフィールドが必要であり、このフィールドに入力した値はサーバ上で動的に検証され、ID値の検証ステータスを示すメッセージが表示されます。まず、Applications Navigatorに追加される新しいアプリケーションとプロジェクトを作成します。
次に、JSFページを作成する必要があります。
この手順を完了すると、「input.jsp」ファイルがAjaxJSFプロジェクトに追加されます。 次に、カタログエントリが問題なく作成された場合に表示する「catalog.jsp」という名前のJSF JSPページを追加します。また、エントリの作成時にエラーが生じた場合に表示する「error.jsp」という名前のJSF JSPページも作成します。どちらのページも、Create JSF JSPウィザードで既定のオプションを選択する必要があります。 [Component Binding]フレームの[Do Not Automatically Expose UI Components in a Managed Bean]オプションを選択します。「lib/Ajax4jsf.jar」ファイルと「lib/oscache-2.3.2.jar」ファイルを、Ajax4JSFバイナリディストリビューションからプロジェクトに追加する必要もあります。図1は、Ajax4JSFプロジェクトのプロジェクトライブラリを示しています。 JARファイル(「ajax4jsf.jar」および「oscache-2.3.2.jar」)を、Ajax4JSFバイナリディストリビューションの「lib」ディレクトリからAjaxJSFアプリケーションの「WEB-INF/lib」ディレクトリにコピーします。図2は、AjaxJSFアプリケーションのディレクトリ構造を示しています。 入力の準備次に、JSFコンポーネントを使って入力フォームを作成します。まず、JSF HTMLコンポーネントライブラリからPanel Gridコンポーネントを「input.jsp」ページに追加します。Create PanelGridウィザードの[Next]をクリックします。[Create empty panel grid]を選択し、[PanelGrid Options]フレームで列数として2を指定し、[Finish]をクリックします。パネルグリッドに追加されるコンポーネントが、2列に配置されます。 コンポーネントパレットの[Output Label]および[Input Text]コンポーネントをパネルグリッドに追加します。同様に、さらに5つの[Output Label]および[Input Text]コンポーネントを追加し、フォームの送信に使用される[Command Button]コンポーネントを追加します。また、ID値が有効かどうかを示す検証メッセージを表示するための[Output Text]コンポーネントも追加します(図3を参照)。[Property Inspector]エリアで、出力ラベルコンポーネントとコマンドボタンコンポーネントの値も指定します。 図3 フォームの作成: JDeveloper IDEのコンポーネントパレットを使って、5つのOutput LabelとInput Textコンポーネント、Command Buttonコンポーネント、およびOutput Textコンポーネントをパネルグリッドに追加する ここで、OracleデータベースとのJDBC接続を作成する必要があります。この接続を作成するには、[Connections]エリアの[Database]ノードを右クリックし、[New Database Connection]を選択します。Create Database Connectionウィザードが表示されたら、[Next]をクリックします。接続名を指定し、[Type]フレームで接続タイプとして[Oracle JDBC]を選択し、[Next]をクリックします。 この例では、[Authentication]フレームでユーザー名とパスワードに「OE」を指定し、[Next]をクリックします。次に、[Connection]フレームで既定の接続設定を選択し、[Next]をクリックします。[Test]フレームの[Test Connection]をクリックし、[Finish]をクリックします。[Connections]エリアに接続が追加されます。 Oracleデータソースの「web.xml」ファイルに 場合によっては、JSFの「faces-config.xml」設定ファイルを変更します。カタログエントリが作成される場合の「catalog.jsp」ページへのナビゲート、および「error.jsp」ページへのナビゲートに関するナビゲーションルールを追加します。 <?xml version="1.0" encoding="windows-1252"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config xmlns="http://java.sun.com/JSF/Configuration"> <managed-bean> <managed-bean-name>backing_input</managed-bean-name> <managed-bean-class>ajaxjsf.backing.Input</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <!--oracle-jdev-comment:managed-bean-jsp-link:1input.jsp--> </managed-bean> <navigation-rule> <from-view-id>/input.jsp</from-view-id> <navigation-case> <from-outcome>catalog</from-outcome> <to-view-id>/catalog.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>error</from-outcome> <to-view-id>/error.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config> リスト1 web.xml
<?xml version = '1.0' encoding = 'windows-1252'?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"> <description>Empty web.xml file for Web Application </description> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <filter> <display-name>Ajax4jsf Filter</display-name> <filter-name>ajax4jsf</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>ajax4jsf</filter-name> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <listener> <listener-class>com.sun.faces.config.ConfigureListener </listener-class> </listener> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>35</session-timeout> </session-config> <mime-mapping> <extension>html</extension> <mime-type>text/html</mime-type> </mime-mapping> <mime-mapping> <extension>txt</extension> <mime-type>text/plain</mime-type> </mime-mapping> <resource-ref> <res-ref-name>jdbc/OracleDBConnectionDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app> 要求の送信 アプリケーションを試すには、Ajax4JSFフレームワークを使用するJSF JSPページ「input.jsp」からAJAX要求を送信します。まずCatalog IDフィールドに <h:inputText binding="#{backing_input.inputText1}" id="inputText1"> <a4j:support event="onkeyup" action= "#{backing_input.inputText_action}" reRender= "inputText2,inputText3,inputText4,inputText5,inputText6, commandButton1,outputText1" /> </h:inputText> Ajax4JSFコンポーネントライブラリを使用するには、次の
<%@ taglib uri="https://ajax4jsf.dev.java.net/ajax"
prefix="a4j"%>
コマンドボタンのクリックによりフォームが送信されるときにカタログエントリを作成するには、コマンドボタンに
<h:commandButton value="Submit"
binding="#{backing_input.commandButton1}" action=
"#{backing_input.commandButton_action}"
id="commandButton1"/>
「catalog.jsp」を変更して、カタログエントリが作成されたことを伝えるメッセージを出力し、「error.jsp」を変更して、データベースの更新時にエラーが発生したことを伝えるメッセージを出力します。 Catalog IDフィールドに入力された値は、データベーステーブルCatalogが配置されているサーバ側で検証されます。ID値がデータベースに既に存在する場合は、「Catalog Id is not valid」というメッセージが入力フォームに表示されます。これは、番号が既に存在するため、そのID値は新しいID番号として「有効でない」ことを意味します。Catalog IDフィールドの値がデータベースに存在しない場合は、「Catalog Id is valid」という検証メッセージが入力フォームに表示されます。有効なID値を判断するビジネスロジックは、サーバ側で指定できます。 Catalog IDフィールドに値が指定されると、 InitialContext initialContext = new InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource)initialContext.lookup( "java:comp/env/jdbc/OracleDBConnectionDS"); java.sql.Connection connection = ds.getConnection(); SQL文でStatementオブジェクトを実行します。 Statement stmt = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); フォームに指定されたCatalog ID値を取得し、SQLクエリを作成してOracleデータベースで実行できます。 String catalogID = (String)inputText1.getValue(); String query = "SELECT * from Catalog WHERE CATALOGID=" + "'" + catalogID + "'"; SQLクエリを実行し、結果セットを取得します。 rs = stmt.executeQuery(query); 結果セットが空でない場合は、検証メッセージを「Catalog Id is not valid」に設定し、フィールド値を設定し、コマンドボタンを無効にします。 if (rs.next()) { inputText2.setValue(rs.getString(2)); inputText3.setValue(rs.getString(3)); inputText4.setValue(rs.getString(4)); inputText5.setValue(rs.getString(5)); inputText6.setValue(rs.getString(6)); outputText1.setValue(new String("Catalog Id is not Valid")); commandButton1.setDisabled(true); } 結果セットが空の場合、つまり、入力フォームに指定されたID値がデータベースに存在しない場合は、検証メッセージを「Catalog Id is valid」に設定し、フィールド値を空のStringに設定し、[Submit]ボタンを有効にします。 else { inputText2.setValue(new String()); inputText3.setValue(new String()); inputText4.setValue(new String()); inputText5.setValue(new String()); inputText6.setValue(new String()); outputText1.setValue(new String("Catalog Id is Valid")); commandButton1.setDisabled(false); } ID値が有効な場合、つまり、フィールドの値がデータベースに存在しない場合は、フォームフィールド値を取得し、データベースとの接続を確立し、新しいカタログエントリを作成します。 リスト2 input.jsp
<%@ taglib uri="https://ajax4jsf.dev.java.net/ajax" prefix="a4j"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <f:view> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/> <title>input</title> <h3>Catalog Entry Form</h3> </head> <body><h:form binding="#{backing_input.form1}" id="form1"> <h:panelGrid columns="2" binding= "#{backing_input.panelGrid1}" id="panelGrid1"> <h:outputLabel value="Catalog ID" binding="#{backing_input.outputLabel1}" id="outputLabel1"/> <h:inputText binding="#{backing_input.inputText1}" id="inputText1"> <a4j:support event="onkeyup" action= "#{backing_input.inputText_action}" reRender="inputText2,inputText3,inputText4,inputText5, inputText6,commandButton1,outputText1" /> </h:inputText> <h:outputLabel value="Journal" binding= "#{backing_input.outputLabel2}" id="outputLabel2"/> <h:inputText binding="#{backing_input.inputText2}" id="inputText2"/> <h:outputLabel value="Publisher" binding="#{backing_input.outputLabel3}" id="outputLabel3"/> <h:inputText binding="#{backing_input.inputText3}" id="inputText3"/> <h:outputLabel value="Edition" binding= "#{backing_input.outputLabel4}" id="outputLabel4"/> <h:inputText binding="#{backing_input.inputText4}" id="inputText4"/> <h:outputLabel value="Title" binding= "#{backing_input.outputLabel5}" id="outputLabel5"/> <h:inputText binding="#{backing_input.inputText5}" id="inputText5"/> <h:outputLabel value="Author" binding= "#{backing_input.outputLabel6}" id="outputLabel6"/> <h:inputText binding="#{backing_input.inputText6}" id="inputText6"/> <h:commandButton value="Submit" binding="#{backing_input.commandButton1}" action= "#{backing_input.commandButton_action}" id="commandButton1"/> <h:outputText binding="#{backing_input.outputText1}" id="outputText1"/> </h:panelGrid> </h:form></body> </html> </f:view> <%-- oracle-jdev-comment:auto-binding-backing-bean- name:backing_input--%> バッキングBeanクラスバッキングBeanクラス「Input.java」のコードを、リスト3に示します。 リスト3 Input.java
package ajaxjsf.backing; import java.sql.*; import javax.faces.component.html.HtmlCommandButton; import javax.faces.component.html.HtmlForm; import javax.faces.component.html.HtmlInputText; import javax.faces.component.html.HtmlOutputLabel; import javax.faces.component.html.HtmlOutputText; import javax.faces.component.html.HtmlPanelGrid; import javax.naming.InitialContext; public class Input { private HtmlForm form1; private HtmlPanelGrid panelGrid1; private HtmlOutputLabel outputLabel1; private HtmlInputText inputText1; private HtmlOutputLabel outputLabel2; private HtmlInputText inputText2; private HtmlOutputLabel outputLabel3; private HtmlInputText inputText3; private HtmlOutputLabel outputLabel4; private HtmlInputText inputText4; private HtmlOutputLabel outputLabel5; private HtmlInputText inputText5; private HtmlOutputLabel outputLabel6; private HtmlInputText inputText6; private HtmlCommandButton commandButton1; private HtmlOutputText outputText1; public void setForm1(HtmlForm form1) { this.form1 = form1; } public HtmlForm getForm1() { return form1; } public void setPanelGrid1(HtmlPanelGrid panelGrid1) { this.panelGrid1 = panelGrid1; } public HtmlPanelGrid getPanelGrid1() { return panelGrid1; } public void setOutputLabel1(HtmlOutputLabel outputLabel1) { this.outputLabel1 = outputLabel1; } public HtmlOutputLabel getOutputLabel1() { return outputLabel1; } public void setInputText1(HtmlInputText inputText1) { this.inputText1 = inputText1; } public HtmlInputText getInputText1() { return inputText1; } public void setOutputLabel2(HtmlOutputLabel outputLabel2) { this.outputLabel2 = outputLabel2; } public HtmlOutputLabel getOutputLabel2() { return outputLabel2; } public void setInputText2(HtmlInputText inputText2) { this.inputText2 = inputText2; } public HtmlInputText getInputText2() { return inputText2; } public void setOutputLabel3(HtmlOutputLabel outputLabel3) { this.outputLabel3 = outputLabel3; } public HtmlOutputLabel getOutputLabel3() { return outputLabel3; } public void setInputText3(HtmlInputText inputText3) { this.inputText3 = inputText3; } public HtmlInputText getInputText3() { return inputText3; } public void setOutputLabel4(HtmlOutputLabel outputLabel4) { this.outputLabel4 = outputLabel4; } public HtmlOutputLabel getOutputLabel4() { return outputLabel4; } public void setInputText4(HtmlInputText inputText4) { this.inputText4 = inputText4; } public HtmlInputText getInputText4() { return inputText4; } public void setOutputLabel5(HtmlOutputLabel outputLabel5) { this.outputLabel5 = outputLabel5; } public HtmlOutputLabel getOutputLabel5() { return outputLabel5; } public void setInputText5(HtmlInputText inputText5) { this.inputText5 = inputText5; } public HtmlInputText getInputText5() { return inputText5; } public void setOutputLabel6(HtmlOutputLabel outputLabel6) { this.outputLabel6 = outputLabel6; } public HtmlOutputLabel getOutputLabel6() { return outputLabel6; } public void setInputText6(HtmlInputText inputText6) { this.inputText6 = inputText6; } public HtmlInputText getInputText6() { return inputText6; } public void setCommandButton1( HtmlCommandButton commandButton1) { this.commandButton1 = commandButton1; } public HtmlCommandButton getCommandButton1() { return commandButton1; } public void setOutputText1(HtmlOutputText outputText1) { this.outputText1 = outputText1; } public HtmlOutputText getOutputText1() { return outputText1; } public String inputText_action() { ResultSet rs = null; try { InitialContext initialContext = new InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource)initialContext.lookup( "java:comp/env/jdbc/OracleDBConnectionDS"); java.sql.Connection connection = ds.getConnection(); Statement stmt = connection.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); String catalogID = (String)inputText1.getValue(); String query = "SELECT * from Catalog WHERE CATALOGID=" + "'" + catalogID + "'"; rs = stmt.executeQuery(query); if (rs.next()) { inputText2.setValue(rs.getString(2)); inputText3.setValue(rs.getString(3)); inputText4.setValue(rs.getString(4)); inputText5.setValue(rs.getString(5)); inputText6.setValue(rs.getString(6)); outputText1.setValue(new String( "Catalog Id is not Valid")); commandButton1.setDisabled(true); } else { inputText2.setValue(new String()); inputText3.setValue(new String()); inputText4.setValue(new String()); inputText5.setValue(new String()); inputText6.setValue(new String()); outputText1.setValue(new String( "Catalog Id is Valid")); commandButton1.setDisabled(false); } } catch (SQLException e) { System.out.println(e.getMessage()); } catch (javax.naming.NamingException e) { System.out.println(e.getMessage()); } return null; } public String commandButton_action() { try { //Obtain Connection InitialContext initialContext = new InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource)initialContext.lookup( "java:comp/env/jdbc/OracleDBConnectionDS"); java.sql.Connection conn = ds.getConnection(); String catalogId = (String)inputText1.getValue(); String journal = (String)inputText2.getValue(); String publisher = (String)inputText3.getValue(); String edition = (String)inputText4.getValue(); String title = (String)inputText5.getValue(); String author = (String)inputText6.getValue(); Statement stmt = conn.createStatement(); String sql = "INSERT INTO Catalog VALUES( " + "¥'" + catalogId + "¥'" + "," + "¥'" + journal + "¥'" + "," + "¥'" + publisher + "¥'" + "," + "¥'" + edition + "¥'" + "," + "¥'" + title + "¥'" + "," + "¥'" + author + "¥'" + ")"; stmt.execute(sql); stmt.close(); conn.close(); } catch (javax.naming.NamingException e) { return "error"; } catch (SQLException e) { return "error"; } return "catalog"; } } 応答の処理アプリケーションを実行して、フォームに指定されたID値を、Catalogデータベーステーブル内のデータに対して検証することができます。入力されたID値が既存の値の場合、アプリケーションはエントリを無効と判断し、その結果を伝えるメッセージを表示します。既存レコードのその他のフォームフィールド値も表示され、[Submit]ボタンが無効になります。 入力されたID値がデータベーステーブルに存在しない場合、アプリケーションはエントリを有効と判断し、その結果を伝えるメッセージを表示します。他のフォームフィールドは空のString値に設定され、[Submit]ボタンが有効になります。 有効なIDの場合は、カタログエントリを作成し、[Submit]ボタンを使ってそのエントリを格納できます。 「input.jsp」を右クリックし、[Run]を選択して、JSFページを実行します。Catalog IDフィールドに値を指定します。フィールドが変更されるたびに(文字が入力されるたびに)AJAX要求が送信され、ID番号が一意(有効)であることを示す検証メッセージが表示されます。 次に、データベースに既に存在するID値、例えば「catalog2」を指定してみましょう。「Catalog Id is not valid」メッセージが表示されることに注目してください。値がデータベースに存在するため、オートコンプリート機能によってフォームフィールドに値が設定され、[Submit]ボタンが無効になります。 これまでの説明でお分かりのように、Ajax4JSFコンポーネントライブラリによってJSFアプリケーションにAJAX機能を追加できます。AJAX機能を追加するためにJavaScriptコードをわざわざ作成する必要はありません。 著者紹介Deepak Vohra(Deepak Vohra)
O'Reillyの技術レビュー担当者として『WebLogic: The Definitive Guide』を担当。NuBeanコンサルタント、Web開発者でもある。Sun認定資格(Java 1.4プログラマおよびWebコンポーネントディベロッパJ2EEバージョン)を取得。メールの宛先はdvohra09@yahoo.com。 |