Note: As of June 2018, this code is unmaintained. It was originally written starting in 2011, which is an eternity ago in user-interface terms. Today, GWT is basically dead as a user interface development framework, making this code mostly irrelevant. Besides that, the Santa Exchange backend no longer works with the most recent Java 8 API for Google AppEngine, so as of January 2019, there won't even be any infrastructure on which it will run. I don't have the time or the motivation to fix it, so it remains here as a historical example.
Santa Exchange GWT Demonstration Project
A "Secret Santa" exchange is a party where people get together to exchange surprise gifts. The gift assignments are secret, and the gifts are usually fairly small.
santa-exchange.appspot.com was a Java-based Google Web Toolkit (GWT v2) web site built using the Mvp4g framework. It runs on Google AppEngine (GAE). The web site lets users manage a gift exchange and send invitations via email. The project was originally maintained at Google Code, but moved here to BitBucket when Google announced retirement of the Google Code service.
This project is intended to provide a solid foundation for use in building other web sites, and I've used it for that purpose myself in both personal and professional projects.
Although the application is pretty small from an end-user perspective, all of the important underlying frameworks have been implemented and thoroughly tested. My goal was to demonstrate all of the features needed in an enterprise-quality software project. I chose to implement Secret Santa functionality because I am comfortable with the problem domain, which is limited in scope. This allowed me to focus on the design patterns and frameworks rather than the problem domain.
A major result of this effort was the CedarCommon project, a library of common Java functionality. Between the two of them, CedarCommon and SantaExchange provide a good example of how to build a solid GWT application using Mvp4g.
See the Table of Contents at the bottom of this page for a list of other wiki pages related to SantaExchange.
The code is managed in a Mercurial repository hosted on BitBucket:
|SantaExchange||https://bitbucket.org/cedarsolutions/santa-exchange||Java source code for the GWT web site|
Shared functionality tied to CedarCommon is kept in a separate Mercurial repository.
Both CedarCommon and SantaExchange are Eclipse projects, targeted at Java 6 and Eclipse 4. Both projects are managed using Gradle 2 and Maven. It's easier to work with SantaExchange using the Google Plugin for Eclipse, but it's not necessary to have the plugin (or even Eclipse, for that matter).
Note: SantaExchange is designed to be used with Java 6 and sets a Java 6 source and target compatibility level. However, recent versions of the AppEngine runtime only work with Java 7. So, although the code is compatible with Java 6, you'll need a Java 7 JDK to build or test the code.
GAE supports two standard roles: user and administrator. For SantaExchange, role-level authorization is implemented both at the UI layer and at the back-end.
At the UI layer, users log into the site using a Google account. Originally, login via OpenId was supported -- including AOL, Yahoo, and MySpace logins in addition to Google. However, as of sometime in 2014, Google apparently made the decision to begin phasing out support for the federated authentication mechanism in AppEngine, so I formally moved away from OpenId as of February 1, 2015.
Mvp4g modules and filters are configured to divide the site into 3 regions: external, internal, and administrative. The external region is visible to the public, the internal region is visible to any authenticated user, and the administrative region is visible only to authenticated administrators.
All GWT remote procedure calls (RPCs) are implemented as Spring services using GWT-SL. Spring security is integrated into the RPC layer. Service interfaces or method calls can be annotated with
@Secured("ROLE_USER"). The Spring security framework will make sure that only authenticated users of the proper type are allowed to invoke the RPCs. A third role,
ROLE_ENABLED, can be used to restrict locked users from calling RPCs.
The back-end DAO (data access object) layer is implemented using Objectify 3. CedarCommon provides an abstract DAO layer and includes an efficient, generalized pagination framework.
The back-end email implementation uses Velocity templates. Email is sent via the usual GAE infrastructure, but CedarCommon provides access to the infrastructure via a Spring service.
The user-visible portions of the implementation are fully localized, although I have not yet found time to have the site translated into any language other than English.
When I originally wrote SantaExchange, I checked dependency jars into revision control, because this is what the Google Plugin for Eclipse encourages you to do. This was less than ideal: the Mercurial repository eventually grew very large due to the frequent AppEngine upgrade cycle. Upgrades in general were painful, and I also had to manually track the source and version of each jar, etc. in my own documentation.
Using Gradle has simplified the whole process, even if it does add an extra setup step for anyone who wants to work with the code. There are notes in the wiki under DevelopmentEnvironment and SourceCode that will walk you through the process.
There is a substantial unit test suite, with over 90% code coverage and nearly 700 test cases implemented as of this writing. Many unit tests rely on
StubbedTestRunner, a JUnit4 test runner that allows much (but not all) of the GWT client code to be tested using standard JUnit 4 unit tests and Mockito mocks. Presenters and certain portions of the view layer code can be tested with JUnit 4. Code that deals directly with user interface widgets must still be tested using the slower and less-flexible GWT client-side unit tests.
Besides the unit test suite, there is also a functional acceptance test suite implemented using Cucumber and Capybara. Cucumber tests are written in a business-readable domain-specific language. Test bindings are written in Ruby, and then Capybara drives a browser session using Selenium. Acceptance test coverage is not as complete as unit test coverage, but the acceptance test suite still provides a good smoke test to prove that the application is working normally.
Table of Contents
- Development Environment
- Working with the Source Code
- Browser Support for GWT Development Mode
- Rolling Back a Google AppEngine (GAE) Deployment
- Using Cucumber with Santa Exchange
- Summary of Application Structure
- GWT Security
- Google AppEngine (GAE) Datastore and Pagination
- Email on Google AppEngine (GAE)
- Velocity on Google AppEngine (GAE)
- Coverage for GWT Client Tests
- XSS and CSRF/XSRF Protection
- RPC Caller Mechanism
- Code Splitting/Compiler Analysis
- Cucumber and Capybara
- Permgen Space