[jboss-cvs] jboss-seam/examples/booking/view/exp ...
Norman Richards
norman.richards at jboss.com
Mon Jul 16 15:21:41 EDT 2007
User: nrichards
Date: 07/07/16 15:21:41
Modified: examples/booking/view/exp bookingExp.html
confirmExp.html loginExp.html mainExp.html
registerExp.html workspaceExp.html
Log:
update explanation pages, fix some newlines
Revision Changes Path
1.7 +95 -90 jboss-seam/examples/booking/view/exp/bookingExp.html
(In the diff below, changes in quantity of whitespace are not shown.)
Index: bookingExp.html
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/booking/view/exp/bookingExp.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- bookingExp.html 10 Nov 2006 19:07:54 -0000 1.6
+++ bookingExp.html 16 Jul 2007 19:21:41 -0000 1.7
@@ -69,58 +69,63 @@
@Logger
private Log log;
+ private boolean bookingValid;
+
@Begin
- public String selectHotel()
+ public void selectHotel(Hotel selectedHotel)
{
- hotel = em.merge( hotelSearch.getSelectedHotel() );
- return "hotel";
+ hotel = em.merge(selectedHotel);
}
- public String bookHotel()
+ public void bookHotel()
{
booking = new Booking(hotel, user);
Calendar calendar = Calendar.getInstance();
booking.setCheckinDate( calendar.getTime() );
calendar.add(Calendar.DAY_OF_MONTH, 1);
booking.setCheckoutDate( calendar.getTime() );
-
- return "book";
}
- public String setBookingDetails()
+
+ public void setBookingDetails()
{
- if (booking==null || hotel==null) return "main";
- if ( !booking.getCheckinDate().before( booking.getCheckoutDate() ) )
+ Calendar calendar = Calendar.getInstance();
+ calendar.add(Calendar.DAY_OF_MONTH, -1);
+ if ( booking.getCheckinDate().before( calendar.getTime() ) )
+ {
+ facesMessages.addToControl("checkinDate", "Check in date must be a future date");
+ bookingValid=false;
+ }
+ else if ( !booking.getCheckinDate().before( booking.getCheckoutDate() ) )
{
- facesMessages.add("Check out date must be later than check in date");
- return null;
+ facesMessages.addToControl("checkoutDate", "Check out date must be later than check in date");
+ bookingValid=false;
}
else
{
- return "confirm";
+ bookingValid=true;
}
}
+ public boolean isBookingValid()
+ {
+ return bookingValid;
+ }
+
@End
- public String confirm()
+ public void confirm()
{
- if (booking==null || hotel==null) return "main";
em.persist(booking);
facesMessages.add("Thank you, #{user.name}, your confimation number for #{hotel.name} is #{booking.id}");
log.info("New booking: #{booking.id} for #{user.username}");
- events.raiseEvent("bookingConfirmed");
- return "confirmed";
+ events.raiseTransactionSuccessEvent("bookingConfirmed");
}
@End
- public String cancel()
- {
- return "main";
- }
+ public void cancel() {}
- @Destroy @Remove
+ @Remove
public void destroy() {}
-
}</code>
<p>
1.6 +51 -52 jboss-seam/examples/booking/view/exp/confirmExp.html
(In the diff below, changes in quantity of whitespace are not shown.)
Index: confirmExp.html
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/booking/view/exp/confirmExp.html,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- confirmExp.html 10 Nov 2006 19:07:54 -0000 1.5
+++ confirmExp.html 16 Jul 2007 19:21:41 -0000 1.6
@@ -27,14 +27,15 @@
<code class="block">
<h:commandButton value="Confirm"
action="#{hotelBooking.confirm}"
- class="button"/>
+ id="confirm"/>
</code>
<p>
The <code>confirm()</code> method is tagged with the <code>@End</code> annotation,
which ends the long-running conversation and results in all state associated with
- the conversation being destroyed at the end of the request. Actually, since the
- <code>confirmed</code> outcome triggers a redirect, the state will not be destroyed
+ the conversation being destroyed at the end of the request.
+ Since the <code>pages.xml</code> file specifies a redirect for this action, the state
+ will not be destroyed
until <em>after the redirect completes</em>. Note that even the success message
that we create using the built-in <code>facesMessages</code> component is transparently
propagated across the redirect!
@@ -42,21 +43,18 @@
<code class="block">
@End
- public String confirm()
+ public void confirm()
{
if (booking==null || hotel==null) return "main";
em.persist(booking);
- facesMessages.add("Thank you, #{user.name}, your confimation number for #{hotel.name} is #{booking.id}");
+ facesMessages.add("Thank you, #{user.name}, your confimation number " +
+ "for #{hotel.name} is #{booking.id}");
log.info("New booking: #{booking.id} for #{user.username}");
events.raiseEvent("bookingConfirmed");
- return "confirmed";
}
@End
- public String cancel()
- {
- return "main";
- }
+ public void cancel() {}
@Destroy @Remove
public void destroy() {}
@@ -87,7 +85,8 @@
@Observer("bookingConfirmed")
public void getBookings()
{
- bookings = em.createQuery("from Booking b where b.user.username = :username order by b.checkinDate")
+ bookings = em.createQuery("from Booking b where b.user.username = " +
+ ":username order by b.checkinDate")
.setParameter("username", user.getUsername())
.getResultList();
}
1.6 +16 -19 jboss-seam/examples/booking/view/exp/loginExp.html
(In the diff below, changes in quantity of whitespace are not shown.)
Index: loginExp.html
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/booking/view/exp/loginExp.html,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- loginExp.html 24 Feb 2007 03:53:42 -0000 1.5
+++ loginExp.html 16 Jul 2007 19:21:41 -0000 1.6
@@ -41,8 +41,9 @@
... ...
<div class="buttonBox">
- <h:commandButton action="#{identity.login}"
- value="Account Login" class="button" />
+ <h:commandButton id="login"
+ action="#{identity.login}"
+ value="Account Login" />
</div>
</code>
@@ -75,8 +76,10 @@
this.password = password;
}
+
@Id
- @Length(min=5, max=15)
+ @Length(min=4, max=15)
+ @Pattern(regex="^\\w*$", message="not a valid username")
public String getUsername () {
return username;
}
@@ -107,13 +110,11 @@
</p>
<code class="block">
- at Stateful
+ at Stateless
@Scope(EVENT)
@Name("authenticator")
public class AuthenticatorAction implements Authenticator
{
- @In Identity identity;
-
@PersistenceContext EntityManager em;
@Out(required=false, scope = SESSION)
@@ -121,11 +122,9 @@
public boolean authenticate()
{
- List results = em.createQuery(
- "select u from User u where u.username=:username " +
- "and u.password=:password")
- .setParameter("username", identity.getUsername())
- .setParameter("password", identity.getPassword())
+ List results = em.createQuery("select u from User u where" +
+ " u.username=#{identity.username}" +
+ " and u.password=#{identity.password}")
.getResultList();
if ( results.size()==0 )
@@ -138,19 +137,17 @@
return true;
}
}
-
- @Remove @Destroy
- public void destroy() {}
}
</code>
<p>
- The <code>@In</code> annotation tells Seam to inject an <code>Identity</code>
- (a built-in Seam component that provides security functionality)
- when any method of <code>AuthenticatorAction</code> is invoked. The <code>@Out</code>
+ The <code>@Out</code>
annotation indicates the <code>AuthenticatorAction</code> bean can change the
value of the <code>user</code> context variable and make the new instance
- available to other session beans and JSF pages.
+ available to other session beans and JSF pages. The query expression
+ makes use of a special syntax in Seam that allows EL expressions to
+ serve as query parameters. This query references the <code>identity</code> component,
+ a built-in Seam component that provides security functionality.
</p>
<form>
1.6 +62 -44 jboss-seam/examples/booking/view/exp/mainExp.html
(In the diff below, changes in quantity of whitespace are not shown.)
Index: mainExp.html
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/booking/view/exp/mainExp.html,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- mainExp.html 10 Nov 2006 19:07:54 -0000 1.5
+++ mainExp.html 16 Jul 2007 19:21:41 -0000 1.6
@@ -26,15 +26,15 @@
</p>
<code class="block">
-<h:inputText value="#{hotelSearch.searchString}" />
-<h:commandButton value="Find Hotels"
- action="#{hotelBooking.find}"
- styleClass="button" />
-<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
+<h:inputText id="searchString" value="#{hotelSearch.searchString}" >
+ <a:support event="onkeyup" actionListener="#{hotelSearch.find}"
+ reRender="searchResults"/>
+</h:inputText>
+
<h:selectOneMenu value="#{hotelSearch.pageSize}" id="pageSize">
<f:selectItem itemLabel="5" itemValue="5"/>
<f:selectItem itemLabel="10" itemValue="10"/>
- <f:selectItem itemLabel="20" itemValue="20"/>
+ <f::selectItem itemLabel="20" itemValue="20"/>
</h:selectOneMenu>
</code>
@@ -44,7 +44,10 @@
<code>pageSize</code> attributes of <code>HotelSearchingAction</code>
before calling the <code>find()</code> action listener method. We've used a
session-scope stateful bean because we want it's state (the search results) to
- be held in the session between requests to the server.
+ be held in the session between requests to the server. The <code><a:support></code>
+ tax specfies that after a keypress, the contents of the <code><a:outputPanel></code> whose
+ id is <code>searchResults</code> should be rerendererd. This is done through an AJAX-style
+ call back to the server with no additional code required of the application.
</p>
<code class="block">
@@ -54,32 +57,41 @@
@LoggedIn
public class HotelSearchingAction implements HotelSearching
{
-
@PersistenceContext
private EntityManager em;
private String searchString;
private int pageSize = 10;
+ private int page;
@DataModel
private List<Hotel> hotels;
- @DataModelSelection
- private Hotel selectedHotel;
- public String find()
+ public void find()
+ {
+ page = 0;
+ queryHotels();
+ }
+ public void nextPage()
+ {
+ page++;
+ queryHotels();
+ }
+
+ private void queryHotels()
{
- String searchPattern = searchString==null ? "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%';
- hotels = em.createQuery("from Hotel where lower(name) like :search or lower(city) like :search or lower(zip) like :search or lower(address) like :search")
- .setParameter("search", searchPattern)
+ hotels = em.createQuery("select h from Hotel h where lower(h.name) " +
+ "like #{pattern} or lower(h.city) like #{pattern} " +
+ "or lower(h.zip) like #{pattern} or " +
+ "lower(h.address) like #{pattern}")
.setMaxResults(pageSize)
+ .setFirstResult( page * pageSize )
.getResultList();
-
- return "main";
}
- public Hotel getSelectedHotel()
+ public boolean isNextPageAvailable()
{
- return selectedHotel;
+ return hotels!=null && hotels.size()==pageSize;
}
public int getPageSize() {
@@ -90,6 +102,13 @@
this.pageSize = pageSize;
}
+ @Factory(value="pattern", scope=ScopeType.EVENT)
+ public String getSearchPattern()
+ {
+ return searchString==null ?
+ "%" : '%' + searchString.toLowerCase().replace('*', '%') + '%';
+ }
+
public String getSearchString()
{
return searchString;
@@ -100,9 +119,8 @@
this.searchString = searchString;
}
- @Destroy @Remove
+ @Remove
public void destroy() {}
-
}</code>
<p>
@@ -113,16 +131,12 @@
variable named <code>hotels</code>. So, when the search page is re-rendered, the
result list is available to the JSF <code>dataTable</code>.
Each row of the data table has an associated command button or link
- (see below). When the user
- clicks on the button / link, the <code>Hotel</code> represented by that
- row is injected into the <code>hotel</code> field annotated by the
- <code>@DataModelSelection</code> annotation. Other application components
- can then access the selected hotel via the
- <code>HotelSearching.selectedHotel</code> property.
+ (see below).
</p>
<code class="block">
-<h:outputText value="No Hotels Found" rendered="#{hotels != null and hotels.rowCount==0}"/>
+<h:outputText value="No Hotels Found"
+ rendered="#{hotels != null and hotels.rowCount==0}"/>
<h:dataTable value="#{hotels}" var="hot" rendered="#{hotels.rowCount>0}">
<h:column>
<f:facet name="header">Name</f:facet>
@@ -142,7 +156,8 @@
</h:column>
<h:column>
<f:facet name="header">Action</f:facet>
- <s:link value="View Hotel" action="#{hotelBooking.selectHotel}"/>
+ <s:link value="View Hotel"
+ action="#{hotelBooking.selectHotel(hot)}"/>
</h:column>
</h:dataTable>
</code>
@@ -150,7 +165,7 @@
<p>
The "View Hotel" link is the above mentioned command link associated
with each row of the data table. It is implemented
- using a Seam <code><s:Link></code>, which is part of Seam's
+ using a Seam <code><s:link></code>, which is part of Seam's
extension of JSF controls.
This JSF control let's us call an action, and pass a request parameter, without
submitting any JSF form. The advantage of <code><s:link></code> is that,
@@ -159,9 +174,13 @@
</p>
<p>
When this link is clicked, the <code>selectHotel()</code> method of the
- <code>HotelBookingAction</code> bean is called. It gets the selected
- hotel from the <code>HotelSearching.selectedHotel</code> property,
- merges it to the current persistence context (in case the same
+ <code>HotelBookingAction</code> bean is called with the <code>hot</code>
+ parameter that is specified in the query. The parameter values are evaluated
+ at invocation time, not when the link is generated, so the <code><s:link></code>
+ tag adds a dataModelSelection parameter that indicates the value of the
+ <code>hot</code> loop variable for the given row.</p>
+ <p> The <code>selectHotel()</code> method merges the selected hotel into
+ the current persistence context (in case the same
hotel has been accessed before in the same session),
and starts a Seam conversation. We will discuss Seam conversations
in the next step.
@@ -177,10 +196,9 @@
... ...
@Begin
- public String selectHotel()
+ public void selectHotel(Hotel selectedHotel)
{
- hotel = em.merge( hotelSearch.getSelectedHotel() );
- return "hotel";
+ hotel = em.merge(selectedHotel);
}
}
</code>
1.5 +2 -1 jboss-seam/examples/booking/view/exp/registerExp.html
(In the diff below, changes in quantity of whitespace are not shown.)
Index: registerExp.html
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/booking/view/exp/registerExp.html,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- registerExp.html 10 Nov 2006 19:07:54 -0000 1.4
+++ registerExp.html 16 Jul 2007 19:21:41 -0000 1.5
@@ -174,7 +174,8 @@
{
if ( user.getPassword().equals(verify) )
{
- List existing = em.createQuery("select username from User where username=:username")
+ List existing = em.createQuery("select username from User " +
+ "where username=:username")
.setParameter("username", user.getUsername())
.getResultList();
if (existing.size()==0)
1.3 +60 -48 jboss-seam/examples/booking/view/exp/workspaceExp.html
(In the diff below, changes in quantity of whitespace are not shown.)
Index: workspaceExp.html
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/booking/view/exp/workspaceExp.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- workspaceExp.html 10 Nov 2006 19:07:54 -0000 1.2
+++ workspaceExp.html 16 Jul 2007 19:21:41 -0000 1.3
@@ -50,16 +50,28 @@
<p>
We do need to specify what text will be displayed by <code>#{entry.description}</code>.
- We do this by creating a <code>pages.xml</code> file in our <code>WEB-INF</code>
- directory.
+ We do this by setting the <code>description</code> value for each page in <code>pages.xml</code>.
</p>
<code class="block">
<pages>
- <page view-id="/hotel.xhtml">View hotel: #{hotel.name}</page>
- <page view-id="/book.xhtml">Book hotel: #{hotel.name}</page>
- <page view-id="/confirm.xhtml">Confirm: #{booking.description}</page>
-</pages>
+ <!-- ... -->
+ <page view-id="/hotel.xhtml"
+ conversation-required="true"
+ login-required="true">
+
+ <description>View hotel: #{hotel.name}</description>
+ <!-- ... -->
+ </page>
+
+ <page view-id="/book.xhtml"
+ conversation-required="true"
+ login-required="true">
+
+ <description>Book hotel: #{hotel.name}</description>
+ <!-- ... -->
+ </page>
+<pages>
</code>
<p>
More information about the jboss-cvs-commits
mailing list