Committing plain JSF+Spring sample

This commit is contained in:
Jeremy Grelle
2008-03-27 13:34:14 +00:00
parent 6380f210a0
commit 494c0ae237
63 changed files with 3209 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2004-2008 the original authorimport javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.support;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* {@link PhaseListener} that logs the execution of the individual phases of the JSF lifecycle. Useful during JSF
* application development in order to detect unreported JSF errors that cause the lifecycle to short-circuit. Turn
* logging level to DEBUG to see its output.
*
* @author Jeremy Grelle
*/
public class RequestLoggingPhaseListener implements PhaseListener {
private Log logger = LogFactory.getLog(RequestLoggingPhaseListener.class);
public void afterPhase(PhaseEvent event) {
// no-op
}
public void beforePhase(PhaseEvent event) {
if (logger.isDebugEnabled()) {
logger.debug("Entering JSF Phase: " + event.getPhaseId());
}
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}

View File

@@ -0,0 +1,179 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
/**
* A Hotel Booking made by a User.
*/
@Entity
public class Booking implements Serializable {
private static final long serialVersionUID = 1171567558348174963L;
private Long id;
private User user;
private Hotel hotel;
private Date checkinDate;
private Date checkoutDate;
private String creditCard;
private String creditCardName;
private int creditCardExpiryMonth;
private int creditCardExpiryYear;
private boolean smoking;
private int beds;
public Booking() {
}
public Booking(Hotel hotel, User user) {
this.hotel = hotel;
this.user = user;
Calendar calendar = Calendar.getInstance();
setCheckinDate(calendar.getTime());
calendar.add(Calendar.DAY_OF_MONTH, 1);
setCheckoutDate(calendar.getTime());
}
@Transient
public BigDecimal getTotal() {
return hotel.getPrice().multiply(new BigDecimal(getNights()));
}
@Transient
public int getNights() {
return (int) (checkoutDate.getTime() - checkinDate.getTime()) / 1000 / 60 / 60 / 24;
}
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Basic
@Temporal(TemporalType.DATE)
public Date getCheckinDate() {
return checkinDate;
}
public void setCheckinDate(Date datetime) {
this.checkinDate = datetime;
}
@ManyToOne
public Hotel getHotel() {
return hotel;
}
public void setHotel(Hotel hotel) {
this.hotel = hotel;
}
@ManyToOne
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Basic
@Temporal(TemporalType.DATE)
public Date getCheckoutDate() {
return checkoutDate;
}
public void setCheckoutDate(Date checkoutDate) {
this.checkoutDate = checkoutDate;
}
public String getCreditCard() {
return creditCard;
}
public void setCreditCard(String creditCard) {
this.creditCard = creditCard;
}
@Transient
public String getDescription() {
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
return hotel == null ? null : hotel.getName() + ", " + df.format(getCheckinDate()) + " to "
+ df.format(getCheckoutDate());
}
public boolean isSmoking() {
return smoking;
}
public void setSmoking(boolean smoking) {
this.smoking = smoking;
}
public int getBeds() {
return beds;
}
public void setBeds(int beds) {
this.beds = beds;
}
public String getCreditCardName() {
return creditCardName;
}
public void setCreditCardName(String creditCardName) {
this.creditCardName = creditCardName;
}
public int getCreditCardExpiryMonth() {
return creditCardExpiryMonth;
}
public void setCreditCardExpiryMonth(int creditCardExpiryMonth) {
this.creditCardExpiryMonth = creditCardExpiryMonth;
}
public int getCreditCardExpiryYear() {
return creditCardExpiryYear;
}
public void setCreditCardExpiryYear(int creditCardExpiryYear) {
this.creditCardExpiryYear = creditCardExpiryYear;
}
@Override
public String toString() {
return "Booking(" + user + "," + hotel + ")";
}
}

View File

@@ -0,0 +1,87 @@
package org.springframework.webflow.samples.booking;
import java.util.Calendar;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
public class BookingController {
private static final String REVIEW_BOOKING_OUTCOME = "reviewBooking";
private BookingService bookingService;
private Long hotelId;
private Hotel hotel = new Hotel();
private Booking booking = new Booking(hotel, new User());
private boolean initialized = false;
public String processBooking() {
FacesContext context = FacesContext.getCurrentInstance();
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -1);
boolean valid = true;
if (booking.getCheckinDate().before(calendar.getTime())) {
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Check in date must be a future date.", "Check in date must be a future date."));
valid = false;
} else if (!booking.getCheckinDate().before(booking.getCheckoutDate())) {
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Check out date must be later than check in date",
"Check out date must be later than check in date"));
valid = false;
}
if (valid) {
return REVIEW_BOOKING_OUTCOME;
} else {
return null;
}
}
public String confirm() {
bookingService.saveBooking(booking);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("booking");
return "confirm";
}
public String cancel() {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("booking");
return "cancel";
}
public Long getHotelId() {
return hotelId;
}
public void setHotelId(Long hotelId) {
if (hotelId != null && hotelId != 0 && !initialized) {
booking = bookingService.createBooking(hotelId, "jeremy");
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("booking", booking);
initialized = true;
}
this.hotelId = hotelId;
}
public Hotel getHotel() {
return hotel;
}
public void setHotel(Hotel hotel) {
this.hotel = hotel;
}
public Booking getBooking() {
return booking;
}
public void setBooking(Booking booking) {
this.booking = booking;
}
public void setBookingService(BookingService bookingService) {
this.bookingService = bookingService;
}
}

View File

@@ -0,0 +1,52 @@
package org.springframework.webflow.samples.booking;
import java.util.List;
/**
* A service interface for retrieving hotels and bookings from a backing repository. Also supports the ability to cancel
* a booking.
*/
public interface BookingService {
/**
* Find bookings made by the given user
* @param username the user's name
* @return their bookings
*/
public List<Booking> findBookings(String username);
/**
* Find hotels available for booking by some criteria.
* @param criteria the search criteria
* @return a list of hotels meeting the criteria
*/
public List<Hotel> findHotels(SearchCriteria criteria);
/**
* Find hotels by their identifier.
* @param id the hotel id
* @return the hotel
*/
public Hotel findHotelById(Long id);
/**
* Create a new, transient hotel booking instance for the given user.
* @param hotelId the hotelId
* @param userName the user name
* @return the new transient booking instance
*/
public Booking createBooking(Long hotelId, String userName);
/**
* Cancel an existing booking.
* @param booking the booking to cancel
*/
public void cancelBooking(Booking booking);
/**
* Save a new booking.
* @param booking the booking to save
*/
public void saveBooking(Booking booking);
}

View File

@@ -0,0 +1,110 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* A hotel where users may book stays.
*/
@Entity
public class Hotel implements Serializable {
private static final long serialVersionUID = 4011346719502656269L;
private Long id;
private String name;
private String address;
private String city;
private String state;
private String zip;
private String country;
private BigDecimal price;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Column(precision = 6, scale = 2)
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Booking createBooking(User user) {
return new Booking(this, user);
}
@Override
public String toString() {
return "Hotel(" + name + "," + address + "," + city + "," + zip + ")";
}
}

View File

@@ -0,0 +1,29 @@
package org.springframework.webflow.samples.booking;
public class HotelController {
private BookingService bookingService;
private Long hotelId;
private Hotel hotel;
public Hotel getHotel() {
if (hotel == null && hotelId != null) {
hotel = bookingService.findHotelById(hotelId);
}
return hotel;
}
public void setBookingService(BookingService bookingService) {
this.bookingService = bookingService;
}
public void setHotelId(Long hotelId) {
this.hotelId = hotelId;
}
public Long getHotelId() {
return hotelId;
}
}

View File

@@ -0,0 +1,92 @@
package org.springframework.webflow.samples.booking;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
/**
* A JPA-based implementation of the Booking Service. Delegates to a JPA entity manager to issue data access calls
* against the backing repository. The EntityManager reference is provided by the managing container (Spring)
* automatically.
*/
@Service("bookingService")
@Repository
public class JpaBookingService implements BookingService {
private EntityManager em;
@PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Booking> findBookings(String username) {
if (username != null) {
return em.createQuery("select b from Booking b where b.user.username = :username order by b.checkinDate")
.setParameter("username", username).getResultList();
} else {
return null;
}
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Hotel> findHotels(SearchCriteria criteria) {
String pattern = getSearchPattern(criteria);
return 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(
criteria.getPageSize()).setFirstResult(criteria.getPage() * criteria.getPageSize()).getResultList();
}
@Transactional(readOnly = true)
public Hotel findHotelById(Long id) {
return em.find(Hotel.class, id);
}
@Transactional(readOnly = true)
public Booking createBooking(Long hotelId, String username) {
Hotel hotel = em.find(Hotel.class, hotelId);
User user = findUser(username);
return new Booking(hotel, user);
}
// read-write transactional methods
@Transactional
public void cancelBooking(Booking booking) {
booking = em.find(Booking.class, booking.getId());
if (booking != null) {
em.remove(booking);
}
}
// read-write transactional methods
@Transactional
public void saveBooking(Booking booking) {
em.persist(booking);
}
// helpers
private String getSearchPattern(SearchCriteria criteria) {
if (StringUtils.hasText(criteria.getSearchString())) {
return "'%" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%'";
} else {
return "'%'";
}
}
private User findUser(String username) {
return (User) em.createQuery("select u from User u where u.username = :username").setParameter("username",
username).getSingleResult();
}
}

View File

@@ -0,0 +1,83 @@
package org.springframework.webflow.samples.booking;
import java.util.ArrayList;
import java.util.List;
import javax.faces.model.SelectItem;
import org.springframework.stereotype.Service;
@Service
public class ReferenceData {
private List<SelectItem> bedOptions;
private List<SelectItem> smokingOptions;
private List<SelectItem> creditCardExpMonths;
private List<SelectItem> creditCardExpYears;
private List<SelectItem> pageSizeOptions;
public List<SelectItem> getBedOptions() {
if (bedOptions == null) {
bedOptions = new ArrayList<SelectItem>();
bedOptions.add(new SelectItem(new Integer(1), "One king-size bed"));
bedOptions.add(new SelectItem(new Integer(2), "Two double beds"));
bedOptions.add(new SelectItem(new Integer(3), "Three beds"));
}
return bedOptions;
}
public List<SelectItem> getSmokingOptions() {
if (smokingOptions == null) {
smokingOptions = new ArrayList<SelectItem>();
smokingOptions.add(new SelectItem(Boolean.TRUE, "Smoking"));
smokingOptions.add(new SelectItem(Boolean.FALSE, "Non-Smoking"));
}
return smokingOptions;
}
public List<SelectItem> getCreditCardExpMonths() {
if (creditCardExpMonths == null) {
creditCardExpMonths = new ArrayList<SelectItem>();
creditCardExpMonths.add(new SelectItem(new Integer(1), "Jan"));
creditCardExpMonths.add(new SelectItem(new Integer(2), "Feb"));
creditCardExpMonths.add(new SelectItem(new Integer(3), "Mar"));
creditCardExpMonths.add(new SelectItem(new Integer(4), "Apr"));
creditCardExpMonths.add(new SelectItem(new Integer(5), "May"));
creditCardExpMonths.add(new SelectItem(new Integer(6), "Jun"));
creditCardExpMonths.add(new SelectItem(new Integer(7), "Jul"));
creditCardExpMonths.add(new SelectItem(new Integer(8), "Aug"));
creditCardExpMonths.add(new SelectItem(new Integer(9), "Sep"));
creditCardExpMonths.add(new SelectItem(new Integer(10), "Oct"));
creditCardExpMonths.add(new SelectItem(new Integer(11), "Nov"));
creditCardExpMonths.add(new SelectItem(new Integer(12), "Dec"));
}
return creditCardExpMonths;
}
public List<SelectItem> getCreditCardExpYears() {
if (creditCardExpYears == null) {
creditCardExpYears = new ArrayList<SelectItem>();
creditCardExpYears.add(new SelectItem(new Integer(2008), "2008"));
creditCardExpYears.add(new SelectItem(new Integer(2009), "2009"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2010"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2011"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2012"));
}
return creditCardExpYears;
}
public List<SelectItem> getPageSizeOptions() {
if (pageSizeOptions == null) {
pageSizeOptions = new ArrayList<SelectItem>();
pageSizeOptions.add(new SelectItem(new Integer(5), "5"));
pageSizeOptions.add(new SelectItem(new Integer(10), "10"));
pageSizeOptions.add(new SelectItem(new Integer(20), "20"));
}
return pageSizeOptions;
}
}

View File

@@ -0,0 +1,65 @@
package org.springframework.webflow.samples.booking;
import java.util.List;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
public class SearchController {
private BookingService bookingService;
private SearchCriteria searchCriteria = new SearchCriteria();
private DataModel hotels = null;
private DataModel bookings = null;
public String search() {
searchCriteria.resetPage();
executeSearch();
return "reviewHotels";
}
public void nextListener(ActionEvent event) {
searchCriteria.nextPage();
executeSearch();
}
public void prevListener(ActionEvent event) {
searchCriteria.previousPage();
executeSearch();
}
private void executeSearch() {
hotels = new ListDataModel();
hotels.setWrappedData(bookingService.findHotels(searchCriteria));
}
public SearchCriteria getSearchCriteria() {
return searchCriteria;
}
public void setBookingService(BookingService bookingService) {
this.bookingService = bookingService;
}
public DataModel getHotels() {
return hotels;
}
public DataModel getBookings() {
if (bookings == null) {
bookings = new ListDataModel(bookingService.findBookings("jeremy"));
}
return bookings;
}
public void cancelBookingListener(ActionEvent event) {
Booking booking = (Booking) bookings.getRowData();
bookingService.cancelBooking(booking);
((List) bookings.getWrappedData()).remove(booking);
}
}

View File

@@ -0,0 +1,66 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
/**
* A backing bean for the main hotel search form. Encapsulates the criteria needed to perform a hotel search.
*/
public class SearchCriteria implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The user-provided search criteria for finding Hotels.
*/
private String searchString = "";
/**
* The maximum page size of the Hotel result list
*/
private int pageSize = 5;
/**
* The current page of the Hotel result list.
*/
private int page;
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public void nextPage() {
page++;
}
public void previousPage() {
page--;
}
public void resetPage() {
page = 0;
}
public String toString() {
return "[Search Criteria searchString = '" + searchString + "'";
}
}

View File

@@ -0,0 +1,62 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* A user who can book hotels.
*/
@Entity
@Table(name = "Customer")
public class User implements Serializable {
private static final long serialVersionUID = -3652559447682574722L;
private String username;
private String password;
private String name;
public User() {
}
public User(String username, String password, String name) {
this.username = username;
this.password = password;
this.name = name;
}
@Id
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User(" + username + ")";
}
}