You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/05/26 23:47:03 UTC

svn commit: r948605 - in /openjpa/trunk/openjpa-examples/openbooks/web: cart.jsp checkout.jsp footer.jsp header.jsp intro.jsp openbooks.css openbooks.js orders.jsp query.jsp search.jsp

Author: ppoddar
Date: Wed May 26 21:47:02 2010
New Revision: 948605

URL: http://svn.apache.org/viewvc?rev=948605&view=rev
Log:
Add explain panel, code browsing support/linkage

Modified:
    openjpa/trunk/openjpa-examples/openbooks/web/cart.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/checkout.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/footer.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/header.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/intro.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/openbooks.css
    openjpa/trunk/openjpa-examples/openbooks/web/openbooks.js
    openjpa/trunk/openjpa-examples/openbooks/web/orders.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/query.jsp
    openjpa/trunk/openjpa-examples/openbooks/web/search.jsp

Modified: openjpa/trunk/openjpa-examples/openbooks/web/cart.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/cart.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/cart.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/cart.jsp Wed May 26 21:47:02 2010
@@ -28,6 +28,23 @@
 
 <%@include file="header.jsp"%>
 
+<div id="help">
+  <h3>Shopping Cart</h3>
+<% if (ACTION_ADD.equals(request.getParameter(KEY_ACTION))) {
+%>
+   You have just added a Book to the cart. 
+   <br>
+<% 
+  }  
+%>
+  A <a HREF="generated-html/openbook/domain/ShoppingCart.java.html#items" type="popup">Shopping Cart</a> contains 
+  <a HREF="generated-html/openbook/domain/Book.java.html#class" type="popup">Books</a> that are persistent objects. 
+  <a HREF="generated-html/openbook/domain/ShoppingCart.java.html#non-persistent" type="popup">
+  Shopping Cart</a>  itself, however, is <em>not</em> a persistent object.
+  Shopping Cart is an in-memory data structure to hold the Books in the current web session and transfer 
+   it to the server when a Purchase Order is to be placed. 
+
+</div>
 <div id="content" style="display: block">
 
 <% 
@@ -41,15 +58,17 @@
    }
    if (cart.isEmpty()) {
 %>
-   <h3><%= customer.getName() %>, your Shopping Cart is empty.</h3><br>
-   <A HREF="<%= PAGE_SEARCH %>">Continue Shopping</A>
+      <%= customer.getName() %>, your Shopping Cart is empty.<br>
+      <A HREF="<%= PAGE_SEARCH %>">Continue Shopping</A>
 <%    
-   } else {
+      return;
+   } 
 %>
 
 
-<table border="0">
-  <caption><%= customer.getName() %>, your Shopping Cart has <%= cart.getTotalCount() %> books</caption>
+<table>
+  <caption><%= cart.getTotalCount() %> book <%= cart.getTotalCount() == 1 ? "" : "s" %> in 
+         <%= customer.getName() %>'s Shopping Cart</caption>
   <thead>
     <tr>
       <th>Title</th> <th>Price</th> <th>Quantity</th>
@@ -63,12 +82,12 @@
   </tfoot>
   <tbody>
 <%
-   }
+   
    Map<Book,Integer> books = cart.getItems();
    int i = 0;
    for (Book b : books.keySet()) {
 %>
-   <TR style="<%= JSPUtility.getRowStyle(i++) %>">
+   <TR class="<%= i++%2 == 0 ? ROW_STYLE_EVEN : ROW_STYLE_ODD %>">
       <TD> <%= b.getTitle() %> </TD>
       <TD> <%= JSPUtility.format(b.getPrice()) %> </TD>
       <TD> <%= books.get(b) %> </TD>

Modified: openjpa/trunk/openjpa-examples/openbooks/web/checkout.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/checkout.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/checkout.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/checkout.jsp Wed May 26 21:47:02 2010
@@ -30,24 +30,65 @@
 
 <%@include file="header.jsp"%>
 
+<div id="help">
+<h3>Composite Pattern and Derived Identity</h3>
 
+  You have just created a  
+  <a href="generated-html/openbook/domain/PurchaseOrder.java.html#init" type="popup">new Purchase Order 
+  </a>.  Each Book in 
+  the Shopping Cart is turned into separate line item for the order and the Purchase
+  Order and all its line items are inserted as new database records. All this happened with
+  this <a href="generated-html/openbook/server/OpenBookServiceImpl.java.html#placeOrder" type="popup">
+  few lines of Java Code</a> 
+  <br>
+  <ul>
+  <li><b>Transitive Persistence</b>:
+  The line items are persisted without any <em>explicit</em> call to persist because persist operation 
+  <a href="generated-html/openbook/domain/PurchaseOrder.java.html#items" type="popup"> cascades 
+  via the order-line item relation</a>. During persist, the JPA provider generated a new
+  <a href="generated-html/openbook/domain/PurchaseOrder.java.html#id" type="popup"> identity of 
+  the Purchase Order</a> automatically. 
+  </li>
+  <li><b>Compound, Derived identity</b>:
+  The identity generation, in this case, is more interesting if you look at the 
+  <a href="generated-html/openbook/domain/LineItem.java.html#id" type="popup">
+  identity used by the line items</a>. Line Item uses <em>compound, derived</em>
+  identity. It is <em>compound</em> because more than one field make up the identity.
+  It is <em>derived</em> because one of the identity field borrows its value
+  from the owning Purchase Order's identity. Because of such dependency, the persistent
+  identity of a Line Item can only be assigned only after a new 
+  identity value for a Purchase Order gets generated during transaction commit.    
+  </li>
+  <li><b>Composite Relation</b>: Purchase Order - Line Item relationship is by semantics,
+  a composite relation. Simply stated, life time of a Line Item is completely controlled
+  by the owning Purchase Order. It is noteworthy that the Line Item constructor is
+  package protected to ensure that only Purchase Order can create them.
+  <br>
+  The Java language provides no support for composite
+  relationship -- but it is a common pattern for persistent objects. The new JPA features
+  of derived identity combined with orphan delete (another new feature) and cascaded 
+  persistent operations provides an application to reliably express a classic Master-Details
+  pattern in their application.     
+  </li>
+  </ul>
+  
+</div>
 
 <div id="content" style="display: block">
-<h2>Thank you for buying books from OpenBooks!</h2>
 <% 
    OpenBookService service = (OpenBookService)session.getAttribute(KEY_SERVICE); 
    ShoppingCart cart = (ShoppingCart)session.getAttribute(KEY_CART);
    PurchaseOrder order = service.placeOrder(cart);
    
 %>
-Order : <%= order.getId() %> <br>
-Placed on <%= JSPUtility.format(order.getPlacedOn()) %>
+Purchase Order ID : <%= order.getId() %> <br>
+Placed on : <%= JSPUtility.format(order.getPlacedOn()) %><br>
 
-<table border="0">
+<table>
   <caption><%= order.getItems().size() %> items</caption>
   <thead>
     <tr>
-      <th>Title</th> <th>Price</th> <th>Quantity</th>
+      <th>Title</th> <th>Quantity</th><th>Price</th> 
     </tr>
   </thead>
   <tfoot>
@@ -61,7 +102,7 @@ Placed on <%= JSPUtility.format(order.ge
   List<LineItem> items = order.getItems();
   for (LineItem item : items) {
 %>
-   <TR style="<%= JSPUtility.getRowStyle(i++) %>">
+   <TR class="<%= i++%2 == 0 ? ROW_STYLE_EVEN : ROW_STYLE_ODD %>">
       <TD> <%= item.getBook().getTitle() %> </TD>
       <TD> <%= item.getQuantity() %> </TD>
       <TD> <%= JSPUtility.format(item.getBook().getPrice() * item.getQuantity()) %> </TD>
@@ -70,7 +111,7 @@ Placed on <%= JSPUtility.format(order.ge
   }
 %>
   <TR>
-  <TD>Total</TD><TD><%= JSPUtility.format(order.getTotal()) %></TD>
+  <TD>Total</TD><TD> </TD><TD><%= JSPUtility.format(order.getTotal()) %></TD>
   </TR>
   </tbody>
 </table>

Modified: openjpa/trunk/openjpa-examples/openbooks/web/footer.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/footer.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/footer.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/footer.jsp Wed May 26 21:47:02 2010
@@ -22,8 +22,11 @@
 <!-- ========================================================================= -->
 <%@page import="org.apache.openjpa.conf.OpenJPAVersion"%>
 <div id="footer">
-   <img src="images/openjpa-logo-small.png" height="20px">
-   Running on <%= OpenJPAVersion.VERSION_ID %>
+   Running on <img src="images/openjpa-logo-small.png" height="40px"> &nbsp; version 
+    <%= OpenJPAVersion.MAJOR_RELEASE + "." +  OpenJPAVersion.MINOR_RELEASE %>
+    <div style="float:right;text-align: right;margin-right:1em">
+         <img alt="" src="images/java_link.png" border="0"> links to Java Source Code
+    </div>
 </div>
 </BODY>
 </HTML>

Modified: openjpa/trunk/openjpa-examples/openbooks/web/header.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/header.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/header.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/header.jsp Wed May 26 21:47:02 2010
@@ -61,56 +61,46 @@
     public static String PAGE_CHECKOUT  = "checkout.jsp";
     
     public static String FORM_TITLE     = "title";
-    public static String FORM_AUTHOR    = "title";
+    public static String FORM_AUTHOR    = "author";
     public static String FORM_PRICE_MAX = "maxPrice";
     public static String FORM_PRICE_MIN = "minPrice";
+    
+    
+    public static String ROW_STYLE_EVEN = "even";
+    public static String ROW_STYLE_ODD  = "odd";
 %>
 
 <!-- Header division displays the title and right-justified current user name -->
 <!-- and a Shopping Cart icon for active sessions                             -->
 <div id="header">
-<table>
-  <colgroup>
-    <col align="left"  width="75%">
-    <col align="right" width="25%">
-  </colgroup>
-  <TBODY>
-  <TR>
-   <TD><img src="images/OpenBooks.jpg" width="25px" height="25px" border="0"> OpenBooks</TD>
-   <TD>
+    <img alt="OpenBooks Logo" src="images/OpenBooks.jpg" border="0" width="25px" height="25px" />
+    &nbsp;&nbsp;<A HREF=".">OpenBooks</A>: JPA 2.0 Application 
 <% 
   Object currentUser = session.getAttribute("user");
   boolean activeSession = currentUser != null;
   if (activeSession) {
 %>
-   <A HREF="cart.jsp"><img src="images/Add2Cart.jpg" border="0" width="25px" height="25px"></A>
-   &nbsp;&nbsp; <%= currentUser.toString() %> 
+     <div style="float:right;text-align: right;margin-right:1em">
+           <%= currentUser.toString() %>&nbsp;&nbsp;
+           <A HREF="cart.jsp"><img src="images/Add2Cart.jpg" border="0" width="25px" height="25px"></A>
+     </div>
 <%
   }
 %>
-  </TD>
-  </TR>
-  </TBODY>
-</table>
 </div>
 
 <!-- Left menu navigation displays the items based on current session status  -->
-<!-- and a Shopping Cart icon for active sessions                             -->
 
 <div id="left">
 
-<ul>
-  <li><a href="intro.jsp">Login</a></li>
 <%
   if (activeSession) {
 %>
-  <li><a href="search.jsp">Search/Buy Books</a></li>
+<ul>
+  <li><a href="search.jsp">Search Books</a></li>
   <li><a href="orders.jsp">View Orders</a></li>
-<%
-  }
-%>
-  <li><a href="http://fisheye6.atlassian.com/browse/openjpa/trunk/openjpa-examples/openbooks/src/main/java/openbook/server/OpenBookService.java?r=HEAD"
-  target="_blank">
-  View Code</a></li>
 </ul>
 </div>
+<% 
+  }
+%>

Modified: openjpa/trunk/openjpa-examples/openbooks/web/intro.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/intro.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/intro.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/intro.jsp Wed May 26 21:47:02 2010
@@ -18,16 +18,41 @@
 --%>
 
 <%@include file="header.jsp"%>
+<div id="help">
+<center><h3>Begin by entering your name.</h3></center>
+OpenBooks do not ask you to register or remember one more password.
+You enter a name so that OpenBooks can refer you by name.
+<hr>
+OpenBooks is a sample (and perhaps simple) web application to demonstrate
+some of the new features of JPA 2.0 API. OpenBooks performs basic operations
+such as <br>
+<OL>
+<LI>Search for Books using a form-base query</LI>
+<LI>Place Purchase Orders for a set of Books</LI>
+<LI>Show the status of pending Purchase Orders </LI>
+<LI>Change the status of pending orders </LI>
+</OL>
 
-<div id="content" style="display: block">
-<b>OpenBooks</b> is a sample web application demonstrating some new features in JPA 2.0 API.
+Each of these actions invokes a  service that queries or transacts against a database. 
+This database interaction takes place via Java Persistence API (JPA). 
+OpenBooks is designed to work with <em>any</em> JPA 2.0 compliant provider.
+Currently OpenBooks is deployed with <A HREF="http://openjpa.apache.org" target="_blank">
+OpenJPA 2.0</A> as its JPA provider.
 <br>
-Please enter your name below to start a OpenBooks session.
-<br> 
+As you navigate through the pages, you can browse through the <em>actual</em> code in parallel. 
+For example, when you hit the <b>Enter</b> button in this page, this is the 
+<a HREF="generated-html/openbook/server/OpenBookServiceImpl.java.html#login" type="popup">
+corresponding Java code</a> executed on the server side.
+<br>   
+</div>
+
+
+<div id="content" style="display: block">
 <% 
     Object service = session.getAttribute(KEY_SERVICE);
     if (service == null) {
 %>
+<A name="login"></A>
       <form method="get" action="<%= PAGE_LOGIN %>">
         Your Name :<br> <input type="text" name="<%= KEY_USER %>" size="40">  <br>
         <input type="SUBMIT" value="Enter">

Modified: openjpa/trunk/openjpa-examples/openbooks/web/openbooks.css
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/openbooks.css?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/openbooks.css (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/openbooks.css Wed May 26 21:47:02 2010
@@ -28,50 +28,118 @@
   All divisions are referred by id in HTML <div> tag.
   -------------------------------------------------------------------------- */
   
+body {
+	font-size:14pt;
+}
+
 #header {
+  position:fixed;
+  top:0;
   width: 100%;
-  height: 30px;
-  margin: 5px;
-  padding: 10px;
+  height: 1.5em;
+  margin: 0.0em;
+  padding: 0.0em;
 
   background: #fff;
   z-index: 100;
 
-  font-size:120%;
-
   border-bottom: 1px solid #999;
+  
+  text-align: left;
+  float:left;
 }
 
 #left {
-	position: absolute;
-	
-	width: 120px;
-	top: 60px;
-	margin-left:10px;
+	position: fixed;
 	
-	font:16pt;
+	width: 10em;
+	top: 5em;
+	margin-left:0.5em;
+    text-align: left;
+    float:left;
 }
 
 #content {
-  top: 0;
-  margin-left: 160px;
-  margin-right: 300px;
-  margin-top:30px;
-  padding: 10px 10px;
+/*  top: 0; */
+  
+  width:30em;
+  height:20em;
+  margin-left: 10em;
+  margin-right: 15em;
+  margin-top:1.5em;
+  padding: 0.5em 0.5em;
+  
+}
+#help {
+  position: fixed;
+  
+  width: 25em;
+  right: 0.75em;
+  top: 3em;
+  margin-left:1em;
+  padding-left:1em;
+/*  outline: 1px solid #000; */
+  border-left-style:solid;
+  float:right;
 }
 
 #footer {
   position: fixed;
   
   width: 100%;
-  height: 20px;
+  height: 3em;
   
-  padding-top: 2px;
-  padding-bottom: 2px;
+  padding-top: 0.1em;
+  padding-bottom: 0.1em;
   bottom: 0;
-  z-index: 10;
+  z-index: 100;
   background: #fff;
   text-align: left;
   border-top: 1px solid #000;
-  font-size:120%;
+  float:left;
+}
+
+table {
+  border-spacing:0;
+}
+
+th {
+	background-color:#BD2031;
+	text-align:center;
+}
+
+tr.even {
+	background-color:#9BE1FB;
+}
+
+tr.odd {
+	background-color:#C5EFFD;
+}
+td {
+	margin-right :0.5em;
+    padding-right:1em;
+    
+	margin-left :1em;
+    padding-left:1em;
+    
+	margin-top:0.1em;
+	padding-top:0.1em;
+	
+	margin-bottom:0.1em;
+    padding-bottom:0.1em;
+    
+    text-align:center;
+}
+
+/**
+ * The links that point to source code uses special marker
+ */ 
+a[href^="generated-html/"] {
+	color:red;
+    padding-right: 2.0em;
+    background-image: url(images/java_link.png);
+    background-position: right !important;
+    background-repeat: no-repeat;
+}
+
 }
\ No newline at end of file

Modified: openjpa/trunk/openjpa-examples/openbooks/web/openbooks.js
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/openbooks.js?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/openbooks.js (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/openbooks.js Wed May 26 21:47:02 2010
@@ -25,3 +25,41 @@ function showPage(id, body) {
   el.innerHTML = body;
 }
 
+/**
+ * Pops up a new window.
+ */
+function popup(url) {
+	newwindow = window.open(url,'SourceCode','height=300,width=1500,left=200,top=800,scrollbars=yes');
+	if (window.focus) {
+	   newwindow.focus()
+	}
+	return false;
+}
+
+/**
+  * All hyperlink reference tags of type = 'popup' is re-written
+  * with onclick event handler to pop up a new window with 
+  * popup() function defined in this script  
+  */
+function onload() {
+   var x = document.getElementsByTagName('a');
+   for (var i=0; i<x.length; i++) {
+	  if (x[i].getAttribute('type') == 'popup') {
+		x[i].onclick = function () {
+			return popup(this.href)
+		}
+	  }
+   }
+   var y = document.getElementsByTagName('A');
+   for (var i=0; i<y.length; i++) {
+	  if (y[i].getAttribute('type') == 'popup') {
+		y[i].onclick = function () {
+			return popup(this.href)
+		}
+	  }
+   }
+}
+
+
+
+

Modified: openjpa/trunk/openjpa-examples/openbooks/web/orders.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/orders.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/orders.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/orders.jsp Wed May 26 21:47:02 2010
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.    
 --%>
-<!-- ===============================================================================================      -->
-<!--      This JSP page demonstrates usage of OpenBookService to browse, select and purchase Books.       -->
-<!-- ===============================================================================================      -->
+<!-- ===========================================================================      -->
+<!--      This JSP page demonstrates changing status of a Purchase Order.             -->
+<!-- ===========================================================================      -->
 <%@page import="openbook.server.OpenBookService"%>
 <%@page import="openbook.domain.Book"%>
 <%@page import="openbook.domain.Customer"%>
@@ -31,6 +31,31 @@
 
 <%@include file="header.jsp"%>
 
+<div id="help">
+<h3>Optimistic semantics and Orphan Delete</h3>
+
+This page displays all the orders placed by the current users. 
+This page also allows to 
+<A HREF="generated-html/openbook/server/OpenBookServiceImpl.java.html#deliver" type="popup">
+<em>deliver</em></A> an order. Delivering an order essentially amounts to
+decrementing the inventory for each line item, 
+<A href="generated-html/openbook/domain/PurchaseOrder.java.html#setDelivered" type="popup">changing the status</A>
+which, as an interesting side-effect, nullifies the Line Items.
+<ul>
+<li><b>Optimistic Semantics</b>: Delivery is one of the operations that may fail due to
+optimistic transaction model used by OpenBooks and which is also the default transaction model
+proposed in JPA. The optimistic transaction model promoted that an Order can <em>always</em>
+be placed, even if the inventory is inadequate. Only while fulfilling the order in a separate
+transaction, the insufficient inventory may fail to deliver an order. 
+</li>
+<li><b>Orphan Delete</b>: JPA 2.0 had added support for composite relation via new orphan delete
+functionality. To demonstrate its effect, on delivery an Order nullifies its Line Items. As a 
+result, the Line Items gets deleted from the database as they are no more referred. That is why,
+for pending orders, you can see their line items -- but once an order is delivered its line items
+are no more available.  
+</li>
+</ul>
+</div>
 <div id="content" style="display: block">
 
 <% 
@@ -48,30 +73,22 @@
    
    Customer customer = (Customer)session.getAttribute(KEY_USER);
    List<PurchaseOrder> orders = service.getOrders(null, customer);
+   if (orders.isEmpty()) {
+%>
+       <%= customer.getName() %>, you have not placed any order yet.<br>
+<%
+       return;
+   }
 %>
-All <%= orders.size() %> Purchase Order placed by <%= customer.getName() %> is shown.
-The <code>Deliver</code> button will deliver the pending order. Delivery of a pending
-order <br>
-<OL>
-<LI>decrements inventory of all associated LineItems</LI>
-<LI>changes status to ORDERED and finally </LI>
-<LI>nullifies the association between Purchase Order and Line Items. Nullifying the
-association has the important side-effect of deleting the line items from the database
-because Purchase Order and Line Items relation is annotated as orphan delete.</LI>
-</OL>
-<br>
   
-<table border="0">
-  <caption><%= customer.getName() %> placed <%= orders.size() %> orders</caption>
+<table>
+  <caption><%= customer.getName() %>, you have placed <%= orders.size() %> orders</caption>
   <thead>
     <tr>
-      <th>ID</th> <th>Total</th> <th>Placed On</th> <th>Status</th> <th>Delivered On</th> 
+      <th>ID</th> <th>Total</th> <th>Placed On</th> <th>Status</th> <th>Delivered On</th> <th></th>
     </tr>
   </thead>
   <tfoot>
-    <tr>
-      <td><A HREF="<%= PAGE_SEARCH %>">Continue Shopping</A></td>
-    </tr>
   </tfoot>
   <tbody>
 <%
@@ -79,7 +96,7 @@ because Purchase Order and Line Items re
   for (PurchaseOrder order : orders) {
       session.setAttribute(""+order.getId(), order);
 %>
-   <TR style="<%= JSPUtility.getRowStyle(i++) %>">
+   <TR class="<%= i++%2 == 0 ? ROW_STYLE_EVEN : ROW_STYLE_ODD %>">
       <TD> <A HREF="<%= 
           JSPUtility.encodeURL(PAGE_ORDERS, 
               KEY_ACTION, ACTION_DETAILS, 
@@ -88,17 +105,16 @@ because Purchase Order and Line Items re
       <TD> <%= JSPUtility.format(order.getPlacedOn()) %> </TD>
       <TD> <%= order.getStatus() %> </TD>
 <% 
-    if (order.getStatus().equals(PurchaseOrder.Status.PENDING)) {
+    if (order.isDelivered()) {
 %>        
-      <TD>  </TD>
-      <TD> <A HREF="<%= 
-          JSPUtility.encodeURL(PAGE_ORDERS, KEY_ACTION, ACTION_DELIVER, 
-                  KEY_OID, order.getId()) %>">Deliver</A></TD>
+      <TD> <%= JSPUtility.format(order.getDeliveredOn()) %> </TD>
+      <TD> </TD>
 <%
     } else {
 %>
-      <TD> <%= JSPUtility.format(order.getDeliveredOn()) %> </TD>
-      <TD> </TD>
+      <TD>  </TD>
+      <TD> <A HREF="<%= JSPUtility.encodeURL(PAGE_ORDERS, KEY_ACTION, ACTION_DELIVER, 
+                  KEY_OID, order.getId()) %>">Deliver</A></TD>
 <%        
     }
 %>
@@ -115,34 +131,45 @@ because Purchase Order and Line Items re
       String oid = request.getParameter(KEY_OID);
       PurchaseOrder order = (PurchaseOrder)session.getAttribute(oid);
       List<LineItem> items = order.getItems();
-      if (items != null && order.getStatus().equals(PurchaseOrder.Status.PENDING)) {
-%>
-<table border="0">
-  <caption><%= items.size() %> line items of Order <%= order.getId() %></caption>
-  <thead>
-    <tr>
-      <th>Title</th> <th>Price</th> <th>Quantity</th> <th>Cost</th>
-    </tr>
-  </thead>
-  <tbody>
-<%
-  int j = 0;
-  for (LineItem item : items) {
+      if (items == null) {
+          if (order.isDelivered()) {
 %>
-   <TR style="<%= JSPUtility.getRowStyle(j++) %>">
-      <TD> <%= item.getBook().getTitle() %> </TD>
-      <TD> <%= JSPUtility.format(item.getBook().getPrice()) %> </TD>
-      <TD> <%= item.getQuantity() %> </TD>
-      <TD> <%= JSPUtility.format(item.getBook().getPrice() * item.getQuantity()) %> </TD>
-   </TR>
-<%
-  }
-%>
-  <TR>
-  <TD>Total</TD><TD><%= JSPUtility.format(order.getTotal()) %></TD>
-  </TR>
-  </tbody>
-</table>
+             Order <%= order.getId() %> has been delivered. Line items of delivered orders are automatically
+             deleted due to orphan delete nature of Master-Details relationship. 
+<%        } else {
+%>
+             Order <%= order.getId() %> has no line items. This is an implementation error because 
+             pending orders must have at least one line item by design.
+<%
+          }
+      } else {
+%>               
+        <table>
+          <caption><%= items.size() %> line items of Order <%= order.getId() %></caption>
+          <thead>
+            <tr>
+              <th>Title</th> <th>Price</th> <th>Quantity</th> <th>Cost</th>
+            </tr>
+          </thead>
+          <tbody>
+<%
+          int j = 0;
+          for (LineItem item : items) {
+%>
+            <TR class="<%= j++%2 == 0 ? ROW_STYLE_EVEN : ROW_STYLE_ODD %>">
+              <TD> <%= item.getBook().getTitle() %> </TD>
+              <TD> <%= JSPUtility.format(item.getBook().getPrice()) %> </TD>
+              <TD> <%= item.getQuantity() %> </TD>
+              <TD> <%= JSPUtility.format(item.getBook().getPrice() * item.getQuantity()) %> </TD>
+            </TR>
+<%
+           }
+%>
+          <TR>
+            <TD>Total</TD><TD><%= JSPUtility.format(order.getTotal()) %></TD>
+          </TR>
+          </tbody>
+        </table>
 <%
       }
   }

Modified: openjpa/trunk/openjpa-examples/openbooks/web/query.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/query.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/query.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/query.jsp Wed May 26 21:47:02 2010
@@ -29,6 +29,27 @@
 <%@page import="openbook.util.JSPUtility"%>
 <%@page import="java.util.List"%>
 
+<div id="help">
+   <h3>Query Result</h3>
+   
+   This page is displaying the result of the query specified in the previous Search page.
+   <ul>
+   <li><B>Readability</B>: Criteria query is more powerful than JPQL but hardly as readable.
+   JPA specification says nothing about how a Criteria Query should be displayed.
+   OpenJPA implementation provides a simple 
+   <a HREF="generated-html/openbook/server/OpenBookServiceImpl.java.html#getQuery" type="popup">
+   <code>toString()</code></a> method to display a query string that is quite <em>similar</em> to 
+   an equivalent JPQL string.
+   </li>
+   <li><B>Eager Fetching</B>: The query result displays the Author names as well, though the query 
+   had only selected the Books. But the Authors have also been fetched because
+   many-to-many <a href="generated-html/openbook/domain/Book.java.html#authors" type="popup">
+   Book-Author relationship</a> is annotated to be <em>eagerly fetched</em>.
+   </li>
+   </ul>
+</div>
+
+
 <div id="content" style="display: block">
 <%!
      /**
@@ -66,15 +87,25 @@
   List<Book> books = service.select(title, minPrice, maxPrice, author);
   String query = service.getQuery(title, minPrice, maxPrice, author);
 %>
-The query executed on the server was <br>
-<pre><%= query %></pre>
+Query : <code><%= query %></code>
+<br>
+<%
+   if (books.isEmpty()) {
+%>
+    This query did not select any Book.
+    <br>
+    <p align="right"><A HREF="<%= PAGE_SEARCH %>">Search again</A></p>
+<%       
+    return;
+   }
+%>
 <br>
-This query selected <%= books.size() %> books.<br>
-<table border="0">
+<table>
+  <caption><%= books.size() %> Books selected</caption>
   <thead>
     <tr>
       <th>ISBN</th> <th>Title</th> <th>Price</th> <th>Authors</th> 
-      <th><img src="images/Add2Cart.jpg" border="0" width="20px" height="20px"></th>
+      <th>Add to Cart</th>
     </tr>
   </thead>
   <tfoot>
@@ -88,7 +119,7 @@ This query selected <%= books.size() %> 
   for (Book book : books) {
       session.setAttribute(book.getISBN(), book);
 %>
-   <TR style="<%= JSPUtility.getRowStyle(i++) %>">
+   <TR class="<%= i++%2 == 0 ? ROW_STYLE_EVEN : ROW_STYLE_ODD %>">
       <TD> <%= book.getISBN() %> </TD>
       <TD> <%= book.getTitle() %> </TD>
       <TD> <%= JSPUtility.format(book.getPrice()) %> </TD>

Modified: openjpa/trunk/openjpa-examples/openbooks/web/search.jsp
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-examples/openbooks/web/search.jsp?rev=948605&r1=948604&r2=948605&view=diff
==============================================================================
--- openjpa/trunk/openjpa-examples/openbooks/web/search.jsp (original)
+++ openjpa/trunk/openjpa-examples/openbooks/web/search.jsp Wed May 26 21:47:02 2010
@@ -16,14 +16,49 @@
  * specific language governing permissions and limitations
  * under the License.    
 --%>
-<!-- ===============================================================================================      -->
-<!--      This JSP page demonstrates usage of OpenBookService to browse, select and purchase Books.       -->
-<!-- ===============================================================================================      -->
+<!-- ===========================================================      -->
+<!--      This JSP page demonstrates usage of form-based query.       -->
+<!-- ===========================================================      -->
 <%@page import="openbook.server.OpenBookService"%>
 <%@page import="openbook.domain.Book"%>
 
 <%@include file="header.jsp"%>
 
+<div id="help">
+  <h3>Criteria Query & Form-based Search</h3>
+  
+  This is a typical search form in a web page. The user fills in one or more fields
+  about a Book, clicks <b>Search</b> and a set of Books matching
+  the user criteria appear on the web page.
+  <br>
+  <ul>
+  <li><b>Dynamic Query</b>:
+  Behind the page, the user input will be used to build up a query, executed on a database and the results
+  returned. The problem is how to build the right query based on the fields that the user had filled in. 
+  If there are 6 input fields -- potentially there are <code>2<sup>6</sup>=64</code>
+  ways to fill in the form and, hence, 64 possible queries. 
+  <br>
+  <b>Criteria Query</b> -- introduced in JPA 2.0 -- can solve this combinatorial problem 
+  by building the query  
+  <a href="generated-html/openbook/server/OpenBookServiceImpl.java.html#buildQuery" type="popup">
+  <em>dynamically</em></a>. 
+  <br>
+  The code shows how the predicates are created based on availability of particular input fields.
+  In the end, all the predicates are anded together to create the final selection criteria.
+  </li>
+  <li><b>Safety by Strong Typing</b>: This new query API is also strongly typed via usage of generic 
+  type arguments. 
+  For example, the API signature enforces that the type of the result returned by a query must match 
+  the type of arguments selected. Or, a String field can not be compared by mistake against a numeric
+  value. All these new features reduces the risk of runtime errors that can be caused by String-based
+  query.   
+  </li>
+  </ul>
+  <br>
+  More about Criteria Query can be found 
+  <A href="http://www.ibm.com/developerworks/java/library/j-typesafejpa/" target="_blank">here</A>.
+</div>
+
 <div id="content" style="display: block">
 
 <% 
@@ -34,19 +69,31 @@
 <%
    }
 %>
-OpenBooks database contains <%= service.count(Book.class) %> books.
+
 <br>
 Fill in the details for a book you are searching for. 
 <br>
-You can leave one, more or all fields empty.
-<hr>
 <form method="GET" action="<%= PAGE_BOOKS %>">
   Title : <br> <input type="text" name="<%= FORM_TITLE %>"><br>
   Author: <br> <input type="text" name="<%= FORM_AUTHOR %>"><br>
   Price : <br> from <input type="text" name="<%= FORM_PRICE_MIN %>"> to 
   <input type="text" name="<%= FORM_PRICE_MAX %>"><br>
-  <hr>
+  <br>
 <input type="submit" value="Search">
 </form>
+<p>
+<b>Search Tips</b>: 
+   <ol>
+   <li>You can leave one, more or all fields empty.</li>
+   <li>OpenBooks database currently contains <%= service.count(Book.class) %> books.</li>
+   <li>Book titles are <code>Book-1</code>, <code>Book-2</code>, <code>Book-3</code>,...</li>
+   <li>Author names are <code>Author-1</code>, <code>Author-2</code>, <code>Author-3</code>,...</li>
+   <li>Both Book and Author names accept wildcard characters. For example, <code>Book-3_</code>
+   will return <code>Book-31</code>, <code>Book-32</code>, <code>Book-33</code> ...
+   <li>A Book is written by one or more Author(s).
+   <li>An Author may have written zero or more Book(s).
+    
+   </ol>
+  
 </div>
 <%@include file="footer.jsp"%>