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"> 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" />
+ <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>
- <%= currentUser.toString() %>
+ <div style="float:right;text-align: right;margin-right:1em">
+ <%= currentUser.toString() %>
+ <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"%>