While playing around more with ExtJS and Spring, I ran in to one of
my favorite annoyances — setting up a new project. I can create a new
webapp in IDEA (or Eclipse) and add some dependencies, but it is still
pretty empty. Maven can go a bit farther, but I don’t like how it
handles transitive dependencies. None of these will really give me a
good starting point out of the box without either copying a bunch of
stuff over from other projects or writing a lot from scratch.
To finally scratch that itch, and move further along the Spring
& ExtJS path, I turned my demo project into a basic template. The
zip archive that you can grab at the bottom is a fully-configured
Spring web application, including Tiles, Spring Security, Spring MVC,
custom JSON view, Transactions and a Datasource.
To get started, grab the file, extract it to some directory. Open a
shell, navigate to the Template directory and run the ant command ant dist
.
This will compile the whole project and create a Template.war file in
the dist directory. Note, I use Java 6 for all development, so if
you’re not at least at Java 5, you won’t be able to use this.
Before you drop the war file into Tomcat’s webapp directory, you’ll need to setup the database. First, copy the jar files in lib/tomcat
into Tomcat’s lib
directory. This is the MySQL JDBC driver and the JTA files for
transactions. You’ll then need to create a new database on your local
MySQL instance called tomcat
. For simplicity in
development, create a user with all rights to the tomcat database.
Here’s the code to run from a MySQL shell:
create database tomcat;
use tomcat;
grant all on tomcat.* to tomcat@localhost identified by 'apache';
Your other option is to just put in your MySQL root username and
password. To do that, or change the connection string completely, edit context.xml
under web/META-INF
. If you don’t use MySQL, you will have to edit this file and also put the correct driver in Tomcat’s lib
directory.
Once you have the database setup, drop the Template.war file into your Tomcat webapps
directory and startup Tomcat. Assuming Tomcat is configured to listen on port 8080, you can open the sample by browsing to http://localhost:8080/Template
The application only has a couple pages. First, the login page:
Spring Security is configured to route unauthenticated requests
through this page for login. You can take a look at the
applicationContext-security.xml file in WEB-INF to see how this was
done. There are two users configured for now. User scott
with a password of tiger
and user bob
with a password of password
. Yes, not very clever, but it works. Scott is in both the ROLE_ADMIN and ROLE_USER roles, while Bob is only in ROLE_USER.
If you login with scott, you’ll be taken to the index page, which looks like this:
The index page simply contains a text box with a button. Entering a
message and pressing the button results in an Ajax call to the server
which echos the message back to the page. An HTML element in the middle
of the page is updated with the result via JavaScript.
You’ll notice in the footer of the page you can see the currently
logged in user on the left, and a link to log out on the right.
Clicking the log out link takes you to the logout page, which looks
like this:
Again, nothing fancy. Just a message saying you have logged out and
a link to login again. Use the login link to login as bob and try the
echo functionality again. This time you get a different result:
This demonstrates what happens with Spring Security via annotations. Here’s the echo method in the service layer:
As you can see, the method is secured with an annotation indicating
the user must be in the ROLE_ADMIN role to use the method. Bob is only
in the ROLE_USER role, so the call to this service fails.
The application makes use of a ResourceBundleMessageSource for the
pages mapped through the htmlDispatch servlet. The login.jsp and
logout.jsp don’t go through the dispatch servlet, so they can’t use the
message bundle for the window and page title.
There is way too much to this simple application to cover completely
now, but I’ll give the highlights of what to go look at in the major
configuration files. Paths are relative to the project root:
web/WEB-INF/web.xml
- notice that I configure two
dispatch servlets. One catching *.htm and one *.json. This sets things
up to treat Ajax requests differently. Spring Security is also
configured here.
web/WEB-INF/applicationContext.xml
– typical
application context for a Spring application. I turn on annotation
handling with package scanning under the sample.core package. Apache
Tiles is configured in this file, and I have also configured a
Transaction Manager around the JDBC DataSource. You should tweak this
based on your underlying persistence preferences. I’m a RowMapper fan,
but you can plug in Hibernate or JPA.
web/WEB-INF/htmlDispatch-servlet.xml
- the context for
web (*.htm) requests. This sets up the ResourceBundle for messages and
a typical ViewResolver mapping the *.htm requests to jsp files under
web/WEB-INF/jsp. Also configures component scanning for the sample.web
package.
web/WEB-INF/jsonDispatch-servlet.xml
– the context for
Ajax (*.json) requests. Configures component scanning for the
sample.json package and specifies a custom Ajax ViewResolver. This will
automagically serialize all ModelMaps returned out of the Controller
responded to *.json requests to JSON.
web/WEB-INF/applicationContext-security.xml
– so
simple to look at, yet so painful to figure out. This is the Spring
Security configuration file. Although it looks deceptively simple, it
was a beating to figure it all out. It enables annotation-driven
security, which you saw on the EchoService above. It also sets up the
form login and locks down all the pages. Note I leave the /resource
directory open. This is where I put all my javascript, stylesheets and
images. If you want to secure those resources, you’ll need to get more
specific on the intercept-urls.
Users are declared at the bottom. Passwords are clear text, which is
fine for a trivial demo, but you would want to replace this with
something more industrial-strength in a real application.
web/WEB-INF/tiles-config.xml
– the Apache Tiles configuration. I only setup one definition here to keep it simple.
web/WEB-INF/jsp/layouts/baseLayout.jsp
– the base
layout used for tiles. I’m only inserting content at two locations in
the template. In the HTML head section, I allow for an optional insert
of headerContent. I use this to include JavaScripts specific to a page.
The other content is within the center div called mainContent.
Note that the body is pretty empty and that the divs all have the
x-hidden class. This means they are not normally visible. I use an
ExtJS Viewport for layout, which uses the contents of these divs.
web/resources/javascripts/layout.js
– this JavaScript file was included in the baseLayout.jsp above. It creates the Viewport using a border layout.
web/resources/javascripts/index.js
– the JavaScript
file included for the index.jsp page. It decorates the plain HTML
inputs on the page to do the cool Ajax stuff. Note towards the bottom
how I use ExtJS to set focus on a form field and to bind the ENTER key
to the submit button.
web/resources/javascripts/login.js
– the JavaScript
file use for the login.jsp page. If you look at login.jsp, you’ll
notice there is no form. Everything is created by ExtJS from the
login.js file, including the cool box effect. One trick is that Spring
Security wants a normal form POST for the login form. I override the
form to do a standard submit instead of an Ajax submit and set the form
action explicitly.
This covers the major features. I’ll be using this as a base for
other projects and will be expanding out my ExtJS demo. Since there are
pretty much zero examples out there of tying together this stack, I
hope this can be of use to some folks.
Project Template
- 2/28/2009 – upgrade to ExtJS 2.2.1, fixed compile issue on Linux, added in iBatis for ORM
- 3/26/2009 – I’ve setup a dev server with the latest version of the template at CodeZombie.com
so you can check it out without having to install. User scott/tiger for
credentials. I’ll be updating this install with a more feature-rich
demo application shortly
- 3/28/2009 – changed around the project structure and build.xml to
use Ivy for dependency management. Check the README.txt file in the
root directory for the details.
- 4/28/2009 – updated the included JSON encoder to be able to return JSON arrays by using the key
_root
in the model map. If this key is found, its content will be used as the
root element of the return JSON instead of encoding the whole map. Also
removed the unicode characters from StringScrubber to make the compiler
on Linux happy.
p.s. this pulls together a lot of jars and pieces from different
folks to build the demo. If you use this for more than playing around,
you need to make sure you respect whatever licenses the authors have in
place.