| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| <!-- |
| Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| --> |
| <head> |
| <link rel="stylesheet" type="text/css" href="../../netbeans.css" |
| media="screen"> |
| <meta name="author" content="Tinuola Awopetu"> |
| <meta name="keywords" |
| content="NetBeans IDE, ICEfaces 1.7, NetBeans 6.0.1, CRUD Applications"> |
| <title>Building Collaborative CRUD Applications With ICEfaces and |
| NetBeans</title> |
| </head> |
| <body> |
| <p><img style="margin-right:10px;width: 180px; height: 69px;" alt="ICEfaces" |
| src="../../images_www/partners/iceSoft.jpg" align="left"></p> |
| <h1>Building Collaborative CRUD Applications With ICEfaces and NetBeans</h1> |
| <br> |
| <p><em>Published: May 2008</em></p> |
| |
| <img src="../../images_www/articles/60/netbeans-stamp.gif" class="stamp" width="114" height="114" |
| alt="Content on this page applies to NetBeans IDE 6.0.1" |
| title="Content on this page applies to NetBeans IDE 6.0.1"> |
| CRUD-style applications remain the mainstay of enterprise |
| application development, but more and more, application developers are |
| looking to add Rich Internet Application (RIA) capabilities into their |
| development process. <a href="http://www.icefaces.org">ICEfaces</a> |
| provides a comprehensive development framework for building RIAs using |
| pure Java techniques based on <a |
| href="http://java.sun.com/javaee/javaserverfaces/">JavaServer Faces |
| (JSF)</a>, but beyond RIA features ICEfaces can truly revolutionize |
| web applications by facilitating real time collaboration using Ajax |
| Push. The latest ICEfaces 1.7 release includes complete |
| integration with <a |
| href="http://download.netbeans.org/netbeans/6.0/final/">NetBeans |
| 6.0.1</a> making it easy to build collaborative RIA-style applications; |
| <a href="http://glassfish.dev.java.net/">Glassfish</a> |
| combined |
| with the Asynchronous Request Processing (ARP) features of <a |
| href="http://grizzly.dev.java.net/">Grizzly</a> provides the |
| scalable deployment infrastructure required for push-style web |
| applications.<span style="font-weight: bold;"></span><br> |
| <br> |
| Essentially, CRUD-style applications enable users to interact with |
| enterprise data, including <span style="font-weight: bold;">C</span>reating, |
| <span style="font-weight: bold;">R</span>eading, <span |
| style="font-weight: bold;">U</span>pdating and <span |
| style="font-weight: bold;">D</span>eleting data, thus the CRUD |
| acronym. If we apply RIA techniques to a CRUD application, our |
| primary motivation is to make interactions between user and data more |
| effective. This might mean providing sortable table headers, |
| improving data navigation through hierarchical tree representations, |
| and |
| enriching master/detail views onto the data. While making the |
| user interaction with the application more effective is a worthwhile |
| exercise onto itself, it does nothing to enhance the interactions |
| between the users of that data. This is where Ajax Push |
| techniques come into play, as they enable asynchronous real time data |
| push to the user when data changes. Now, when those changes occur as |
| the result of one user manipulating the data, all users interested in |
| that particular data can be instantaneously informed of the |
| change. Web-based collaboration is the essence of Web 2.0 and |
| Ajax Push enables it, fundamentally changing what is possible in |
| web applications and turning dusty old CRUD applications into rich, |
| interactive, collaboration platforms.<br> |
| <br> |
| So what does it take to build collaborative CRUD applications? |
| In the remainder of this article we will work through a very basic |
| example using ICEfaces and NetBeans to illustrate how easily attainable |
| they are. While the example is simplistic, it fully exposes all |
| the technique you will require to leverage rich ICEfaces features and |
| Ajax Push all through the NetBeans JSF Visual Design Editor. The |
| example uses the ICEfaces 1.7, and NetBeans 6.0.1 releases. The |
| completed NetBeans project can be download from the ICEfaces <a |
| href="http://www.icefaces.org/main/resources/tutorials.iface">tutorial |
| page</a> under the <span style="font-style: italic;">IDE Tutorials</span> |
| tab.<br> |
| <br> |
| <h2>Installing the ICEfaces Plugins in NetBeans</h2> |
| <ol> |
| <li>Registered ICEfaces community members can download the |
| ICEfaces/NetBeans integration bundle <a |
| href="http://www.icefaces.org/main/downloads/os-downloads.iface">here</a>. |
| The bundle is located under <span style="font-style: italic;">IDE Tool |
| Integrations > NetBeans</span>, and is called <span |
| style="font-style: italic;">ICEfaces-1.7.0-Netbeans-6.0.1-modules.zip. |
| </span>Unpack the bundle somewhere that you can access it from |
| NetBeans.<br> |
| </li> |
| <li>Install the ICEfaces plugins into NetBeans from <span |
| style="font-style: italic;">Tools > Plugins</span> dialog, using |
| the <span style="font-style: italic;">Downloaded</span> tab. The <span |
| style="font-style: italic;">Add Plugins</span> button is used |
| to select the ICEfaces plugins which are called <span |
| style="font-style: italic;">com-icesoft-faces-vwp-ide.nbm</span> and <span |
| style="font-style: italic;">com-icesoft-ide-netbeans-libs-module.nbm</span>. |
| Once you have selected the plugins, you should see something like this, |
| and just need to hit the <span style="font-style: italic;">Install</span> |
| button.</li> |
| <br> |
| <img style="width: 653px; height: 341px;" |
| alt="ICEfaces Plugin Installation" |
| src="../../images_www/articles/icefaces-crudapps/nb-plugin-install.png"><br> |
| <br> |
| </ol> |
| <span style="font-weight: bold;"></span> |
| <h2>Creating an ICEfaces Project</h2> |
| <ol> |
| <li>Create a new project using <span style="font-style: italic;">File |
| > New Project</span> wizard, and |
| select <span style="font-style: italic;">Web > Web Application</span> |
| for the project type and hit <span style="font-style: italic;">Next |
| ></span> |
| button.</li> |
| <li>Name the project<span style="font-style: italic;"> |
| CollaborativeCRUD</span> and select GlassFish V2 |
| server, and Java EE 5, then hit the <span style="font-style: italic;">Next |
| ></span> button.</li> |
| <li>Select the Visual Web ICEfaces framework, as illustrated below, |
| and hit Finished button.</li> |
| <li><img style="width: 728px; height: 477px;" |
| alt="New Web Application" |
| src="../../images_www/articles/icefaces-crudapps/new-webapp.png"></li> |
| </ol> |
| <h2>Connecting an ice:DataTable to a Database Table</h2> |
| <ol> |
| <li>In the Visual Design Editor, you see the template for an ICEfaces |
| page called Page1. Delete the default <span style="font-style: italic;">InputTextarea</span>, |
| and from the |
| ICEfaces Palette drag an <span style="font-style: italic;">ice:DataTable</span> |
| onto the page as illustrated below.</li> |
| <img style="width: 821px; height: 390px;" alt="Drag DataTable" |
| src="../../images_www/articles/icefaces-crudapps/datatable-drag.png"><br> |
| <br> |
| <li>Next, drag a database table onto the<span |
| style="font-style: italic;"> ice:DataTable</span>. This |
| can be done from the <span style="font-style: italic;">Services</span> |
| tab under <span style="font-style: italic;">Databases</span>, as |
| illustrated |
| below. For this example you will use the <span |
| style="font-style: italic;">Person</span> table, from the <span |
| style="font-style: italic;">Travel</span> database. Make sure the drag |
| target is the <span style="font-style: italic;">dataTable</span> |
| and |
| not the <span style="font-style: italic;">htmlForm</span>. You |
| will see that the column data in the <span style="font-style: italic;">ice:DataTable</span> |
| now reflect |
| the content of the <span style="font-style: italic;">Person</span> |
| database table.</li> |
| <img style="width: 839px; height: 298px;" alt="Drag Person DB" |
| src="../../images_www/articles/icefaces-crudapps/drag-person-db.png"><br> |
| <br> |
| <li>Add a Sortable Header and a Row Selector using the context menu |
| for the <span style="font-style: italic;">ice:DataTable</span> as |
| illustrated below.</li> |
| <img style="width: 876px; height: 388px;" alt="Add Sort Header" |
| src="../../images_www/articles/icefaces-crudapps/add-sort-header.png"><br> |
| <br> |
| <li>When the row selector binding dialog appears, simply accept the |
| defaults and close, as illustrated below. Later you will use the <span |
| style="font-style: italic;">rowSelectior1_processAction</span> |
| listener to implement the editing logic for |
| selected rows.</li> |
| <img style="width: 607px; height: 319px;" alt="Row Select Binding" |
| src="../../images_www/articles/icefaces-crudapps/rowselect-binding.png"><br> |
| <br> |
| <li>You can now test that this all works by building the project and |
| running it. The result, illustrated below, is a sortable table of |
| the <span style="font-style: italic;">Person</span> database with row |
| selection, which at this point does |
| nothing.</li> |
| <img style="width: 750px; height: 400px;" alt="Run 1" |
| src="../../images_www/articles/icefaces-crudapps/run-one.png"><br> |
| </ol> |
| <br> |
| <ol> |
| </ol> |
| <h2>Implement Simple Data Model To Support Editing</h2> |
| <ol> |
| <li>First you need to create a wrapper class for the person |
| data.<br> |
| <br> |
| <span style="font-weight: bold;">package CollaborativeCRUD;</span><br |
| style="font-weight: bold;"> |
| <br style="font-weight: bold;"> |
| <span style="font-weight: bold;">import java.sql.Timestamp;</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;">import java.util.TreeMap;</span><br |
| style="font-weight: bold;"> |
| <br style="font-weight: bold;"> |
| <span style="font-weight: bold;">public class Person {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private Integer |
| personId;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private String |
| name;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private String |
| jobTitle;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private Integer |
| frequentFlyer;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private |
| Timestamp lastDateUpdated;</span><br style="font-weight: bold;"> |
| <br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public Integer |
| getFrequentFlyer() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return frequentFlyer;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setFrequentFlyer(Integer frequentFlyer) {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.frequentFlyer = frequentFlyer;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public String |
| getJobTitle() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return jobTitle;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setJobTitle(String jobTitle) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.jobTitle = jobTitle;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public |
| Timestamp getLastDateUpdated() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return lastDateUpdated;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setLastDateUpdated(Timestamp lastDateUpdated) {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.lastDateUpdated = lastDateUpdated;</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public String |
| getName() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return name;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setName(String name) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.name = name;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public Integer |
| getPersonId() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return personId;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setPersonId(Integer personId) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.personId = personId;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public Person() |
| {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public |
| Person(Integer personId, String name, String jobTitle, Integer |
| frequentFlyer, Timestamp lastDateUpdated) {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.personId = personId;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.name = name;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.jobTitle = jobTitle;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.frequentFlyer = frequentFlyer;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.lastDateUpdated = lastDateUpdated;</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public |
| Person(TreeMap data) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.personId = (Integer) data.get("PERSON.PERSONID");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.name = (String) data.get("PERSON.NAME");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.jobTitle = (String) data.get("PERSON.JOBTITLE");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.frequentFlyer = (Integer) data.get("PERSON.FREQUENTFLYER");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.lastDateUpdated = (Timestamp) data.get("PERSON.LASTUPDATED");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;">}</span><br |
| style="font-weight: bold;"> |
| <br> |
| </li> |
| <li>Next you will establish some state in your page bean to support |
| editing of the selected row. You need to capture the selected |
| person, |
| and maintain a boolean indicating whether editing is disabled.<br> |
| <br> |
| public class Page1 extends AbstractPageBean {<br> |
| // Managed Component Definitions<br> |
| ...<br> |
| <span style="font-weight: bold;"> private Person |
| blankPerson = new Person(0, "", "", 0, null);</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private Person |
| selectedPerson = blankPerson;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private boolean |
| editDisabled = true;</span><br style="font-weight: bold;"> |
| <br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public boolean |
| isEditDisabled() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return editDisabled;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setEditDisabled(boolean editDisabled) {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.editDisabled = editDisabled;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public Person |
| getSelectedPerson() {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return selectedPerson;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setSelectedPerson(Person selectedPerson) {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.selectedPerson = selectedPerson;</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <br> |
| </li> |
| <li>Next you need to implement the row selection logic in the action |
| listener previously defined for this. You need to extract the row |
| out of the data model associated with the <span |
| style="font-style: italic;">ice:DataTable</span>, in this case |
| the <span style="font-style: italic;">dataTableSortableDataModel</span>. |
| You also need to enable editing |
| when the row is selected.<br> |
| <br> |
| public void |
| rowSelector1_processAction(RowSelectorEvent rse) {<br> |
| int selectedRowIndex = |
| rse.getRow();<br> |
| <span style="font-weight: bold;"> |
| editDisabled = false;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| dataTable1SortableDataModel.setRowIndex(selectedRowIndex);</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| selectedPerson = new Person((TreeMap) |
| dataTable1SortableDataModel.getRowData());</span><br |
| style="font-weight: bold;"> |
| } <br> |
| <br> |
| </li> |
| <li>Build the project so that the new objects will be available for |
| binding into the page.<br> |
| <br> |
| </li> |
| </ol> |
| <h2>Create Editing Form</h2> |
| <ol> |
| <li>Add a second <span style="font-style: italic;">ice:Form</span> |
| by dragging one from the ICEfaces component |
| palette onto the page. Make sure the new form follows the |
| existing one, and is not nested inside it. You will also have to resize |
| the form to accept the editing controls that you will add next.</li> |
| <li>To keep the example as simple as possible, the editing feature |
| will display the selected name in an <span style="font-style: italic;">ice:OutputText</span>, |
| and allow editing |
| of the job description in an <span style="font-style: italic;">ice:InputText</span>. |
| Start by dragging an <span style="font-style: italic;">ice:OutputText</span> |
| onto the |
| new form. Right click the <span style="font-style: italic;">OutputText</span> |
| to |
| display the context menu, and select <span style="font-style: italic;">Bind |
| To Data</span>. You need to |
| create the binding <span style="font-style: italic;">#{Page1.selectedPerson.name}</span> |
| as illustrated below.<br> |
| <br> |
| <img style="width: 665px; height: 451px;" alt="Output Text Binding" |
| src="../../images_www/articles/icefaces-crudapps/output-textbinding.png"><br> |
| <br> |
| </li> |
| <li>Now drag an <span style="font-style: italic;">ice:InputText</span> |
| onto the form, and create the binding <span style="font-style: italic;">#{Page1.selectedPerson.jobTitle}</span> |
| in the same manner that you did for |
| the <span style="font-style: italic;">OutputText</span>. Once |
| you have done that you will add one |
| additional binding to enable and disable the <span |
| style="font-style: italic;">InputText</span>. Again, |
| right click the <span style="font-style: italic;">InputText</span> and |
| from the context menu select <span style="font-style: italic;">Property |
| Bindings</span>. You need to bind the <span style="font-style: italic;">disabled</span> |
| property to your <span style="font-style: italic;">editDisabled</span> |
| boolean in the page bean, as illustrated below.</li> |
| <img style="width: 778px; height: 520px;" alt="Disabled Binding" |
| src="../../images_www/articles/icefaces-crudapps/disabled-binding.png"><br> |
| <br> |
| <li>Finally, drag an <span style="font-style: italic;">ice:CommandButton</span> |
| onto the form. When you |
| are done, your page design should look something like illustrated |
| below. As with the <span style="font-style: italic;">InputText</span>, |
| you want to bind the <span style="font-style: italic;">CommandButton</span> |
| <span style="font-style: italic;">disabled</span> property to the <span |
| style="font-style: italic;">editDisabled</span> boolean with a binding |
| like <span style="font-style: italic;">disabled=#{Page1.editDisabled}</span>.</li> |
| <img style="width: 702px; height: 491px;" alt="Form Design View" |
| src="../../images_www/articles/icefaces-crudapps/formdesign-view.png"><br> |
| <br> |
| </ol> |
| <h2>Add The Editing Logic</h2> |
| <ol> |
| <li>Right click the <span style="font-style: italic;">submit</span> |
| button and from the context menu select <span |
| style="font-style: italic;">Edit Event Handler > |
| processAction</span>, which will create the Java code |
| for the <span style="font-style: italic;">button1_processAction()</span> |
| event listener in the page bean. You need to add logic to this member |
| function to persist the data, and |
| disable editing until the next row selection occurs. To do this |
| you will use the NetBeans data provider that was established |
| automatically when you associated the <span style="font-style: italic;">Person</span> |
| table with the <span style="font-style: italic;">ice:DataTable</span>. |
| The |
| code for achieving this is shown below.<br> |
| <br> |
| public void button1_processAction(ActionEvent ae) {<br> |
| <span style="font-weight: bold;"> |
| personDataProvider.setCachedRowSet((javax.sql.rowset.CachedRowSet) |
| getValue("#{SessionBean1.personRowSet}"));</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| persistPerson(selectedPerson);</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| selectedPerson = blankPerson;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| editDisabled = true;</span><br style="font-weight: bold;"> |
| }<br> |
| <br> |
| </li> |
| <li>The logic for persisting a person into the database is |
| implemented as follows.<br> |
| <br> |
| <span style="font-weight: bold;"> private void |
| persistPerson(Person person) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| if (personDataProvider != null) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| java.util.Date d = new java.util.Date();</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| Timestamp ts = new Timestamp(d.getTime());</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| boolean done = false;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| try {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| if (personDataProvider.getRowCount() > 0) {</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.cursorFirst();</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| do {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| if |
| (personDataProvider.getValue("PERSON.PERSONID").equals(person.getPersonId())) |
| {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.setValue("PERSON.NAME", person.getName());</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.setValue("PERSON.JOBTITLE", person.getJobTitle());</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.setValue("PERSON.FREQUENTFLYER", |
| person.getFrequentFlyer());</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.setValue("PERSON.LASTUPDATED", ts);</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| done = true;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| }</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| } while (!done && personDataProvider.cursorNext());</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| }</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.commitChanges();</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| } catch (Exception ex) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| System.out.println("Exception occured: " + ex);</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| ex.printStackTrace();</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| }</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| }</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <br> |
| </li> |
| <li>One last thing you need to do is ensure that the table view on |
| the data is refreshed before the render occurs to ensure it is up to |
| date. This is done in the <span style="font-style: italic;">prerender()</span> |
| member function as shown |
| below.<br> |
| <br> |
| public void prerender() {<br> |
| <span style="font-weight: bold;"> |
| try {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| CachedRowSet cachedRowSet = (CachedRowSet) |
| getValue("#{SessionBean1.personRowSet}");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| cachedRowSet.execute();</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personDataProvider.refresh();</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| dataTable1SortableDataModel.setWrappedData((javax.sql.rowset.CachedRowSet) |
| getValue("#{SessionBean1.personRowSet}"));</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| } catch (Exception ex) {</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| System.out.println("Exception occured: " + ex);</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| ex.printStackTrace();</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| }</span><br style="font-weight: bold;"> |
| }<br> |
| <br> |
| </li> |
| <li>You can now build and run the application. When a row is |
| selected it should look something like this.</li> |
| <img style="width: 906px; height: 541px;" alt="Run 2" |
| src="../../images_www/articles/icefaces-crudapps/run-two.png"><br> |
| <br> |
| <li>Now try interacting with the application from 2 different browser |
| clients. You will see that if changes are made in one client, |
| they are not reflected in the other client until you interact with that |
| client, at which time the data is updated to reflect the existing |
| content in the database. Without Ajax Push implemented in this |
| applications, the client's view onto the data can be stale at any |
| moment in time.</li> |
| </ol> |
| <h2>Add Ajax Push</h2> |
| <ol> |
| <li>The Ajax Push infrastructure in ICEfaces is organized under an |
| application scope bean called <span style="font-style: italic;">RenderManager</span>. |
| To add this bean |
| to your application open the <span style="font-style: italic;">faces-config.xml</span> |
| in XML view in the |
| editor. Right click an existing managed bean definition and from |
| the context menu select<span style="font-style: italic;"> JavaServer |
| Faces > Add Managed Bean</span>, as |
| illustrated below.</li> |
| <img style="width: 908px; height: 480px;" alt="Add Managed Bean" |
| src="../../images_www/articles/icefaces-crudapps/add-managedbean.png"><br> |
| <br> |
| <li>Define a managed bean called <span style="font-style: italic;">RenderManager</span> |
| with the class <span style="font-style: italic;">com.icesoft.faces.async.render.RenderManager</span> |
| in applications scope as |
| illustrated below.</li> |
| <img style="width: 563px; height: 320px;" alt="RenderManager Bean" |
| src="../../images_www/articles/icefaces-crudapps/render-manager.png"><br> |
| <br> |
| <li>This will result in the following code being added to your <span |
| style="font-style: italic;">faces-config.xml</span>.<br> |
| <br> |
| <managed-bean><br> |
| |
| <managed-bean-name>RenderManager</managed-bean-name><br> |
| |
| <managed-bean-class>com.icesoft.faces.async.render.RenderManager</managed-bean-class><br> |
| |
| <managed-bean-scope>application</managed-bean-scope><br> |
| </managed-bean><br> |
| <br> |
| </li> |
| <li>You will need access to the <span style="font-style: italic;">RenderManager</span> |
| from your page bean so |
| add it as a managed property with the following code.<br> |
| <br> |
| <managed-bean><br> |
| |
| <managed-bean-name>Page1</managed-bean-name><br> |
| |
| <managed-bean-class>CollaborativeCRUD.Page1</managed-bean-class><br> |
| |
| <managed-bean-scope>request</managed-bean-scope><br> |
| <span style="font-weight: bold;"> |
| <managed-property></span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <property-name>renderManager</property-name></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <property-class>com.icesoft.faces.async.render.RenderManager</property-class></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <value>#{renderManager}</value></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| </managed-property></span><br style="font-weight: bold;"> |
| </managed-bean><br> |
| <br> |
| </li> |
| <li>Next you need your page bean to implement the <span |
| style="font-style: italic;">Renderable</span> interface as shown below.<br> |
| <br> |
| public class Page1 extends AbstractPageBean<span |
| style="font-weight: bold;"> implements Renderable</span> {<br> |
| <br> |
| Now if you right click the page, and select <span |
| style="font-style: italic;">Insert Code</span> from the context menu, |
| you will see a dialog from which you can select <span |
| style="font-style: italic;">Implement Method</span>. You can now |
| select the Renderable interface and generated the members as shown |
| below.</li> |
| <br> |
| <img style="width: 434px; height: 195px;" alt="Renderable Methods" |
| src="../../images_www/articles/icefaces-crudapps/renderable-methods.png"><br> |
| <br> |
| <li>Before you complete the implementation, you need to add some |
| state to your page bean as shown below. You will need access to |
| the <span style="font-style: italic;">PersistentFacesState</span>, <span |
| style="font-style: italic;">RenderManager</span>, and an <span |
| style="font-style: italic;">OnDemandRenderer</span> to hold the list |
| of <span style="font-style: italic;">Renderables</span> (1 per client |
| session). The <span style="font-style: italic;">OnDemandRenderer</span> |
| is a named singleton that will be created by the <span |
| style="font-style: italic;">RenderManager</span>.<br> |
| <br> |
| <span style="font-weight: bold;"> private |
| PersistentFacesState state = null;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private |
| RenderManager renderManager;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> private |
| OnDemandRenderer personGroup = null;</span><br |
| style="font-weight: bold;"> |
| <br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public void |
| setRenderManager(RenderManager renderManager){</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| if(renderManager != null){</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| this.renderManager = renderManager;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personGroup = renderManager.getOnDemandRenderer("personGroup");</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| personGroup.add(this);</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| }</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> </span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> public |
| RenderManager getRenderManager(){</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| return renderManager;</span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> }</span><br |
| style="font-weight: bold;"> |
| <br> |
| </li> |
| <li>Make sure the persistentFacesState is initialized in the page |
| bean init() member.<br> |
| <br> |
| public void init() {<br> |
| ...<br> |
| // Perform application |
| initialization that must complete<br> |
| // *after* managed |
| components are initialized<br> |
| // TODO - add your own |
| initialization code here<br> |
| <span style="font-weight: bold;"> |
| state = PersistentFacesState.getInstance(); </span><br |
| style="font-weight: bold;"> |
| }<br> |
| <br> |
| </li> |
| <li>Now you can complete the implementation of the <span |
| style="font-style: italic;">Renderable</span> interface with the |
| following code.<br> |
| <br> |
| public PersistentFacesState getState() {<br> |
| <span style="font-weight: bold;"> |
| return state;</span><br style="font-weight: bold;"> |
| }<br> |
| <br> |
| public void renderingException(RenderingException |
| re) {<br> |
| <span style="font-weight: bold;"> |
| personGroup.remove(this);</span><br style="font-weight: bold;"> |
| }<br> |
| <br> |
| </li> |
| <li>Finally, you need to request a render whenever changes are |
| committed to the database. This is done in the action listener |
| for the <span style="font-style: italic;">submit</span> button as |
| shown below.<br> |
| <br> |
| public void button1_processAction(ActionEvent ae) {<br> |
| |
| personDataProvider.setCachedRowSet((javax.sql.rowset.CachedRowSet) |
| getValue("#{SessionBean1.personRowSet}"));<br> |
| |
| persistPerson(selectedPerson);<br> |
| selectedPerson = blankPerson;<br> |
| editDisabled = true;<br> |
| <span style="font-weight: bold;"> |
| personGroup.requestRender();</span><br style="font-weight: bold;"> |
| }<br> |
| <br> |
| </li> |
| <li>You can now build and run the application. If you view it |
| in two different browsers you should see changes pushed to both when |
| changes are made to the data. You now have a fully functional |
| collaborative CRUD application. The application will also work |
| from multiple windows in the same browser instance, but first you will |
| need to turn on <span style="font-style: italic;">concurrentDOMViews</span> |
| in the <span style="font-style: italic;">web.xml</span> as shown below.<br> |
| <br> |
| <context-param><br> |
| |
| <param-name>com.icesoft.faces.concurrentDOMViews</param-name><br> |
| <param-value><span |
| style="font-weight: bold;">true</span></param-value><br> |
| </context-param><br> |
| </li> |
| </ol> |
| <h2>Configure The Grizzly ARP Engine</h2> |
| <ol> |
| <li>The current deployment of the application relies on a standard |
| Servlet to handle the Ajax Push connection, which is not a scalable |
| solution. By configuring Grizzly into the deployment you can make |
| the application scale well for large numbers of concurrent users. |
| In future releases of ICEfaces, Grizzly configuration will be |
| automated, but for now there is a bit of manual configuration that you |
| must do. First you must add the Grizzly Servlet as the first |
| Servlet in your <span style="font-style: italic;">web.xml</span>, as |
| shown below.<br> |
| <br> |
| <span style="font-weight: bold;"> <servlet></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <servlet-name>Grizzly Push Servlet</servlet-name></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <servlet-class></span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| com.icesoft.faces.webapp.http.servlet.GrizzlyPushServlet</span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| </servlet-class></span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <load-on-startup> 1 </load-on-startup></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> </servlet></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> </span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <servlet-mapping></span><br style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <servlet-name>Grizzly Push Servlet</servlet-name></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| <url-pattern>/block/receive-updated-views/*</url-pattern></span><br |
| style="font-weight: bold;"> |
| <span style="font-weight: bold;"> |
| </servlet-mapping></span><br style="font-weight: bold;"> |
| <br> |
| <servlet><br> |
| |
| <servlet-name>Persistent Faces Servlet</servlet-name><br> |
| |
| <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class><br> |
| |
| <load-on-startup>1</load-on-startup><br> |
| </servlet><br> |
| <br> |
| </li> |
| <li>Next you have to add the <span style="font-style: italic;">cometSupport</span> |
| property to the http-listener in your Glassfish <span |
| style="font-style: italic;">domain.xml</span> file. NetBeans can tell |
| you the location of this file for your installation |
| from the <span style="font-style: italic;">Services</span> tab under <span |
| style="font-style: italic;">Servers</span>. Right click the |
| Glassfish server and select properties from the context menu, and you |
| will see the directory path to your <span style="font-style: italic;">domain.xml</span> |
| file as illustrated below. Also, you will need to turn off <span |
| style="font-style: italic;">Enable HTTP Monitor</span> to see the true |
| performance of the application.<br> |
| <br> |
| <img style="width: 769px; height: 512px;" alt="Glassfish Properties" |
| src="../../images_www/articles/icefaces-crudapps/glassfish-properties.png"><br> |
| <br> |
| Once you have located the <span style="font-style: italic;">domain.xml |
| </span>file, you need to add the <span style="font-style: italic;">cometSuppor</span>t |
| property as shown below.<br> |
| <br> |
| <http-listener acceptor-threads="1" address="0.0.0.0" |
| blocking-enabled="false" default-virtual-server="server" enabled="true" |
| family="inet" |
| <br> |
| |
| id="http-listener-1" port="17154" security-enabled="false" |
| server-name="" xpowered-by="true"><br> |
| <property |
| name="proxiedProtocols" value="ws/tcp"/><br> |
| <span style="font-weight: bold;"> |
| <property name="cometSupport" value="true"/></span><br |
| style="font-weight: bold;"> |
| </http-listener><br> |
| <br> |
| </li> |
| <li>Now rebuild the application, and restart the server. The |
| application is now running with Grizzly configured to handle all the |
| Ajax Push connections.</li> |
| </ol> |
| <h2>Inspiration Time</h2> |
| You have now completed your first collaborative CRUD application. |
| While simplistic, the example illustrates all the key concepts required |
| to build sophisticated collaborative applications with ICEfaces and |
| NetBeans. Take what you have learned here, and apply your own |
| inspiration to future application development. You can change the |
| way your enterprise collaborates, and usher your colleagues and |
| customers into the Web 2.0 era.<br> |
| <br> |
| <div style="text-align: right;"><span style="font-style: italic;">(May |
| 2008)</span> <br> |
| </div> |
| <br> |
| </body> |
| </html> |