Sunday, October 21, 2007

Maven 2 Resources

Maven 2 - One bite at a time Series

For some reason, lots and lots of people complain that maven is too hard to use, and or that the documentation is inadequate. I have been very happily been using Maven and Maven2 for a few years now and have always found the answer that I was looking for.

I usually find my answer within one of the following maven resources:



The key to Maven2 documentation is locating the documentation for the particular plug-in that you are interested in. This can sometimes be difficult as that documentation must be written by the plug-in developer and it seems like they the maven plug-in developer community (as well as the software industry in general) is lacking when it comes to good documentation. The take away here is this: many bloggers and commenters are complaining that Maven is difficult when after reading the post of comment it appears that many times it is a specific third party plug-in that they are having problems with.

Thursday, August 23, 2007

LinkBuilder

I wrote this class a few years ago. I have used it many projects. I just rewrote it. Its down from 275 lines of code to 170, it is completely javadoced, and uses generics.

When I wrote it before, I used a ton of StringBuffers. I think the way that It is now, it is going to be a lot more readable, easier to modify, and thus less bug prone. I was also able to combine three methods (two overloaded the one) down to just the one, and cut the number of private methods way down. It was a mess before. I don't know what I was thinking three years ago. What a noob.

Here is a link to the old ugly version. The following is an explanation of the API and links to the new version, and tests.


final LinkBuilder linkBuilder = new LinkBuilder();
linkBuilder.setName("Google search 'link builder'");
linkBuilder.setBaseUrl("http://www.google.com");
linkBuilder.addParameter("q", "link builder");

final String result = linkBuilder.getLink(LinkBuilder.LINK_TEXT, true);


Result now equals <a href="http://www.google.com?q=link builder">Google search 'link builder'</a>

Alternatively, you can call


final String url = linkBuilder.getBuiltUrl();


to get http://www.google.com?q=link builder. This makes this class useful for generating links that will be displayed on a web page, or for generating URLs that you need to call from within your code.

The class is pretty versatile. It allows you to use an image instead of text, allows you to link to a bookmark (#top for example) and allows you to set a target frame if
you want to open the link in a new window.

After setup, such as


LinkBuilder linkBuilder = new LinkBuilder();

linkBuilder.setName("google search 'Link Builder'");
linkBuilder.setBaseUrl("http://www.google.com");
linkBuilder.addParameter("q", "Link Builder");
linkBuilder.addParameter("number", 7);
linkBuilder.addParameter("boolean", true);
linkBuilder.setTarget("newSearchWindow");
linkBuilder.setImageUrl("images/search.png");
linkBuilder.setWrapper("small");


There are four ways to get the link. Textual or an image, and active or not active. A not active link is a link without the link. So just text or just the image.


linkBuilder.getLink(LinkBuilder.LINK_TEXT, true);


restults in:

<small><a href="http://www.google.com?q=Link Builder&number=7&boolean=true" target="newSearchWindow">google search 'Link Builder'</a></small>



linkBuilder.getLink(LinkBuilder.LINK_TEXT, false);


results in:


<small>google search 'Link Builder'</small>



linkBuilder.getLink(LinkBuilder.LINK_IMAGE, true);


results in:


<small><a href="http://www.google.com?q=Link Builder&number=7&boolean=true" target="newSearchWindow"><img src="images/search.png" alt="google search 'Link Builder'" border="0"/></a></small>



linkBuilder.getLink(LinkBuilder.LINK_IMAGE, false);


results in:


<small><img src="images/search.png" alt="google search 'Link Builder'" border="0"/></small>


LinkBuilder.java raw

LinkBuilderTest.java raw

Saturday, August 11, 2007

irc channels

I learn so much from the guys in the IRC channels. As a developer using these enourmous libraries, its sometimes tough to find the answers to unique questions. I have found the designers and developers of these frameworks to be extremely helpful. If you have a question, come on in, or just come say Hi and complement the developers on these terrificly successful projects.


Tuesday, July 17, 2007

architecture rules

If you want to, skip my blog and go straight to the project's home page. I wrote them both, so I don't mind ( :

I'm a big fan of architecture. I am learning quickly how important it is to have an architecture that is solid and ingrained throughout your entire code base in order to create a more modifiable and understandable project source. So when I found this article on dzone last week about using jdpend to test your architecture, I jumped right on it.

Once I started using jdepend though, I thought its configuration was straightforward, but it was difficult to scan the test code and see what the architecture rules were.

Jdepend looks like this:


import junit.framework.TestCase;
import jdepend.framework.JavaPackage;
import jdepend.framework.JDepend;

public class ArchitecturalRulesTest extends TestCase {
private static final String DIRECTORY_TO_ANALYZE = "C:/dev/project-sandbox/brewery/classes";
private JDepend jdepend;
private String dataLayer = "com.beer.business.data";
private String businessLayer = "com.beer.business.service";
private Collection dataLayerViolations = new ArrayList();

public ArchitecturalRulesTest(String name) {
super(name);
}

protected void setUp() throws IOException {
jdepend = new JDepend();
jdepend.addDirectory(DIRECTORY_TO_ANALYZE);
// Calling the businessLayer from the dataLayer is a violation
dataLayerViolations.add(businessLayer);
}


Now that says that com.beer.business.data may not depend upon com.beer.business.service which is readable, but once I got up to 8 or 9 packages that I wanted to monitor, the configuration was huge. So, I set out to make the configuration easier and came up with architecture-rules, and that is why you are here now.

I don't want to duplicate what I wrote there, but this should get you intrigued...

Sample Configuration breakdown and explanation

<?xml version="1.0"?>

<architecture>

<configuration>

<sources no-packages="ignore">
<source not-found="ignore">core/target/classes</source>
<source not-found="ignore">util/target/classes</source>
<source not-found="exception">parent-pom/target/classes</source>
<source not-found="ignore">web/target/classes</source>
</sources>

<cyclicalDependency test="true"/>

</configuration>


<rules>

<rule>
<id>dao</id>
<package>com.nereson.pagerank.core.dao</package>
<violations>
<violation>com.nereson.pagerank.core.services</violation>
<violation>com.nereson.pagerank.core.builder</violation>
<violation>com.nereson.pagerank.util</violation>
</violations>
<comment>The dao interface package should rely on nothing.</comment>
</rule>

<rule>
<id>strategy</id>
<package>com.nereson.pagerank.core.strategies</package>
<violations>
<violation>com.nereson.pagerank.core.services</violation>
<violation>com.nereson.pagerank.core.dao.hibernate</violation>
</violations>
<comment>strategies should be as pluggable as possible</comment>
</rule>

<rule>
<id>model</id>
<package>com.nereson.pagerank.core.model</package>
<violations>
<violation>com.nereson.pagerank.core.dao</violation>
<violation>com.nereson.pagerank.core.dao.hibernate</violation>
<violation>com.nereson.pagerank.core.services</violation>
<violation>com.nereson.pagerank.core.strategy</violation>
<violation>com.nereson.pagerank.core.builder</violation>
<violation>com.nereson.pagerank.util</violation>
</violations>
<comment>model should remain competely isolated</comment>
</rule>

</rules>

</architecture>

Sunday, June 24, 2007

Spring on Code organization for large projects

Code organization for large projects.

I discovered this 88 minute presentation on dzone.com today. Not a lot of people have time the time to sit through a presentation this long, so I have decided to write about the presentation. The majority of my comments below are simply paraphrasing what the presenter says, and I take no credit for his thoughts or words. I simply found them to be enlightening and want to share them.

Before I start on the presentation, I want to go over some of the terms that are used, as they are the principals that are under discussion.

Cohesion: A measure of how well the lines of source code within a module work together to provide a specific piece of functionality. That is, how well a module of code focuses on one single task or function.

Low Coupling: Refers to a relationship in which one module interacts with another module through a stable interface and does not need to be concerned with the other module's internal implementation. The benefit of low coupling is that when a change in one module is required, it will not require a change in the implementation of another module.

Dependency: A state where one object uses a functionality of another object.

Java Package: A set of Java classes organized for convenience in the same directory.

Now then, the complete presentation includes video and a slide show and can be found at http://www.infoq.com/presentations/code-organization-large-projects.

Summary

Juergen Hoeller shares his experiences working on large projects (including his role as chief architect of the Spring Framework) to provide general guidelines on Packaging and package interdependencies, Layering and module decomposition, Evolving a large code base. Juergen will also discuss how tools can play a role in enforcing architectural soundness.

Bio

Juergen Hoeller has been the most active Spring developer since the open source project began from Rod's Interface21 framework back in February 2003. Juergen and Rod together continue to provide the direction for Spring.

About the conference

The Spring Experience conference is hosted by Interface21 and NoFluffJustStuff Java Symposiums

Why worry about code organization?

Many organization and or programmers don't spend time thinking about code organization, it simply evolves without thought.

Personally, I usually come up with some sort of rough package structure before I start coding, but I don’t document it, and I don’t think about modules. My packages are usually based upon the layers of my multi-tiered design.

For example, my packages typically look like:

com.mycompany.myapp.dao
dao interfaces

com.mycompany.myapp.dao.hibernate
hibernate implementations of the dao interfaces

com.mycompany.myapp.services
service class interfaces and implementations

com.mycompany.myapp.web.springmvc
or com.mycompany.myapp.web.struts
for my web controllers

com.mycompany.myapp.model
for all my model classes

I share my package structure with you so that you can be reassured that others do it this way if this is how you structure your packages. If you don’t structure your packages this way, I am interested in how you do it and why.

There isn't a lot of literature on package dependency and interdependency best practices.

I have to agree with Juergen. Given all the books that I have read, the blogs that I subscribe to and the classes that I have taken, no one has ever spoken on best practices when it comes to package organization. I may have read about package interdependency without realizing what I was reading at the time.

Code needs to be logically organization. Code bases needs to be able to evolve based on its original structure and, even years later, based on completely new requirements.

Refactoring and agile development are fine, but how do you preserve backwards compatibility once the code is released? What do you do if you already have people using your published code?

How should modules evolve? Separate modules might need to interact in a later revision, despite the original design not having intended it, thereby introducing new interdependencies at the module or package level.

How well does the code base allow for repackaging into more fine-grained modules if the need arises, while preserving the API?

I like that question. I think it’s fascinating how the Spring Framework can be divided up into a dozen packages or one single package, allowing the users to include only those packages that they need to use for their application. For example, you can use spring-full for the entire spring framework, or just spring-ldap, spring-aop, or spring-core, if you have more specific needs. That fact that the project can be divided into so many modules is a testament to the care and thought that they have put into their package design and code maintainability.

Package Interdependencies

Most public code bases are not good examples of good package design. For example the JDK libraries and many open source projects such as Hibernate. They contain bad practices such as cyclical package dependencies.

Later in the presentation, Juergen goes on to demonstrate how java.lang depends on java.util and how java.util depends on java.lang. For example the String class. He also shows that, on average, any given class in Hibernate depends on two-thirds of the entire Hibernate library.

As a counter example, Juergen states that “Spring does not contain any package circles.”

Typical scenario: Package B depends on package A according to the initial architectural design. New code in package A could use some code in Package B. Since you don't want to duplicate code, you call the code from package A to package B. Now you have package B using package A using package B.

Read as “Now you have package B dependent on Package A dependent on Package B”

Central rule: Packages should have one way dependencies between each other - at most. That is B can call A, but A should not call B.

Why are one-way dependencies between packages so important? Why are circles so undesirable?

Typically, circles are not deliberate, they usually sneek in. Over time, as more programmers touch the code, the original intent or design of the code is lost. Circles can be an indication of code deterioration and indicate to the state or maintenance of the code base.

Consequences of cyclical dependencies include limited reuse of packages.

Cyclical dependencies create dependencies so that you can not extract that package for use with another project or some other code base. The packages becomes inseparable. Neither package can be compiled without the other package. So that in the event that you needed to extract some code for another project, you would also need to bring along some other package that has nothing to do with the new code base.

Avoid circular dependencies between packages. This is easier said than done, and many times you don't even realize that you have done it. To remove these circular dependencies, creative refactoring is usually required, which creates backwards compatibility challenges. Regardless, always avoid code duplication.

How do you avoid circular dependencies while at the same time avoid code duplication? Usually this means taking the time to analyze your package architecture to determine the best place for this new code. For example, at first thought you might want to put the code in some deeper package, but after some careful consideration, you determine that the code really needs to be placed in a shallower package.

Module Decomposition and Layering

Modules are conceptual in java. They are conceptual boundaries within your code base. Generally modules are a collection of specific packages that collaborate and/or are conceptually related. They might live in separate source directories but do not have to. Some modules might consist of a single package only, while others may consist of many packages. Identifying modules can be challenging.

Typically, modules are driven by deployment needs as much as conceptual boundaries. For example part of the code might be used by one application deployed on one server, while another part of the code might be used be a second application. Others created modules based on multi-tier separation. However, this is unnatural since it does not match conceptual boundaries.

So, the package structure that I use, which I described above would be considered a package structure based on multi-tier separation which Juergen states is “unnatural.”

Sometimes modules are isolated by specific dependencies, such as JDK 1.5 or Hibernate. However, this is not a conceptual boundary, so it is a rather incorrect use of module separation. Sometimes modules are created to keep jar file size down. Again, this is an incorrect usage.

Desirable characteristics of modules include low coupling to other modules, and high cohesion within the module.

Modules are conceptual units as much as a source management and deployment unit. Modules should allow for individual usage or a distinct role within a larger system. For example, a new developer on the team, or a new user of your code should be able to review a module and understand the reasoning or the usage of that module - thus it is a complete, implemented concept with clear boundaries.

This sounds ideal. I know it would be great if when I was assigned to a new project I could pull it down and see distinct modules, and know what each of their responsibilities were, and knew that they did not overlap.

Modules should not have circular dependencies. Therefore module 1 -> module 2 -> module 1 is an undesirable situation.

Layering is essentially a logical view on the package structure. Higher layers build on lower layers. That is, higher level packages depend on lower level packages, not the other way around.

I seem to follow this rule of thumb with my DAO packages, being com.mycompany.myapp.dao and com.mycompany.myapp.dao.hibernate.

The module structure might have a straightforward mapping into layers. However this is not strictly necessary since modules might be a vertical slice. Modules are often driven by deployment considerations more than layering. That is, modules are usually vertical while layers are usually horizontal.

Establish natural conceptual boundaries in your code base. It does not mater where your code resides. It could be a single shared source root, or one source root per module. It does help if the source code structure mirrors the conceptual structure. This creates a natural package naming system and makes navigation easier.

Evolving a Large Code Base

The hardest challenge is evolving the code as well as the architecture over time without letting the code deteriorate and without compromising on architectural quality. This becomes exponentially harder with growing size of the overall code base. Consider the situation where you have many developers involved and no single point of architectural management or enforcement at the fine-grained artifact or module level.

You are going to see inconsistencies across the code, duplicated code, inconsistent naming, and most likely a decrease in loose coupling and high cohesion.

What is the trade-off between backwards compatibility and architectural quality? Strict 100% backwards compatibility might not allow for sustaining the architectural quality level. Nevertheless, there is always a better solution than compromising on architectural quality. For example a creative internal refactoring that allows to preserve compatibility as well as well-defined package dependencies.

Certain packages, for example the public API or core packages, can almost never be changed. The code base must revolve around these packages. One solution, if you must change the public API or core, is deprecation but even this is sometimes not possible. Some changes can only be done by breaking backwards compatibility. What do you do in that case? Break backwards compatibility or reduce the integrity of the architecture? The Spring development team is willing to accept a small breakage of backwards compatibility as long as the end result is a strong architecture.

Case Study: the Evolution of Spring

Background of Spring core:

  • Origins back to early 2001.
  • First public release was in 2002
  • First public source release was mid 2003
  • 1.0 release in 2004
  • 2.0 release in 2006, largely compatible with 1.2.

The spring project has faced many code evolution challenges including a broad public API used by applications; sophisticated SPI used by advanced applications as well as sister products and third-party frameworks; and new requirements addressed in every release, often implying some refactoring.

A tough situation that would not have been possible if not for their straightforward architecture and their strict adherence to the rules: accept small breakages of backwards compatibility as long as the end result is a strong architecture, and right from the start, no circles allowed at package level, not even as a temporary measure.

How has the Spring code base survived in its original shape for 3.5 years?

Strict architecture management and loosely coupled packages with well-defined interdependencies.

Right from the start, no circles allowed at package level, not even as a temporary measure.

When introducing new code or functionality, great care is given in determining where the new code will go.

  • Challenges
    • Ever changing third party libraries.
    • Hibernate 2.1 -> 3.0 -> 3.1 -> 3.2
      • Resulted in the creation of the package hibernate3
    • Quartz 1.3 -> 1.4 -> 1.5 -> 1.6

What do you do in case of incompatible API changes in such libraries? The goal is always to try to maintain backwards compatibility, so in many cases, Spring developers were required to use runtime reflection to determine which library is in use and to maintain this compatibility. With reflection Spring can check to see if a certain method exists, and if it does, it is called, if it does not, it is skipped.

Tools for Architectural Analysis

How do we make sure that our architecture remains sound and avoids architectural violations? The best thing to do is to always keep these restrictions in mind, but even this can only get you so far.

Manual analysis only gets you so far, it is like manual testing vs. automated, repeatable testing. The only way to guarantee this is to use tools. Since 2003, Spring has been using JDepend before every public release. They have also recently introduced the SonarJ tool.

JDepend traverses Java class file directories and generates design quality metrics for each Java package. JDepend allows you to automatically measure the quality of a design in terms of its extensibility, reusability, and maintainability to manage package dependencies effectively.

JDepend is an open source tool that has been around since 2001. It is typically used as a command line tool. It can generate an analysis report which, among many other things, includes package dependency cycles.

SonarJ is an innovative solution that helps you to manage and monitor the logical architecture and the technical quality of your Java projects.

SonarJ is a commercial tool, is gui-driven, and is highly customizable. SonarJ also allows for on-the-fly analysis.

The presentation ends with a demonstration using SonarJ to analyze Spring.

I was about to go check out JDepend, when I realized that the IDE that I use, IntelliJ, contains cyclic dependency and backwards compatibility tests via the Analyze menu. Fellow IntelliJ users should see http://www.jetbrains.com/idea/features/code_analysis.html#Dependencies_Analysis and http://blogs.jetbrains.com/idea/2006/04/analyzing-code-dependencies-part-i/

Monday, March 5, 2007

Spring: Multiple WebApplictionContext

I have migrated this post. Sorry for any inconvenience.

http://72miles.com/blog/posts/spring-loading-multiple-contexts/

Tuesday, February 27, 2007

Spring: System properties read into applicationContext.xml

This is a simple one. Create a propertyConfigurer bean in your context xml file.

It's going to look like this.


<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">


Now I can use variables like ${java.io.tmpdir} right in my configuration files.

I needed this becuase I am importing a database to a temp directory so that I can read entities from the imported database, and copy them to my primary database.

Here is the complete configuration that I use to accomplish this.


<beans xmlns="http://www.springframework.org/schema/beans"
xsi="http://www.w3.org/2001/XMLSchema-instance"
jee="http://www.springframework.org/schema/jee"
schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<bean id="externalDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
method="close">

<property
name="driverClassName"
value="sun.jdbc.odbc.JdbcOdbcDriver">
<property
name="url"
value="jdbc:odbc:;DRIVER=...(*.mdb);DBQ=${java.io.tmpdir}\tempdb.mdb;">
<property
name="username"
value="itsasecret">
<property
name="password"
value="toeverybody">
</property>

</bean>
</beans>


I found this solution in the Spring Forums.

Spring: Many applicationContext.xml > One applicationContext.xml

I have migrated this post. Sorry for any inconvenience.

http://72miles.com/blog/posts/spring-many-applicationcontextxml-one-applicationcontextxml/

Spring: OpenSessionInViewInterceptor vs. OpenSessionInViewFilter Part II

Migrated posts and comments to a new site.

Spring: OpenSessionInViewInterceptor & OpenSessionInViewFilter Examples at 72miles.com

Maven: Build sources jar alongside compiled jar

This is a great Maven 2 plugin that creates a project-version-sources.jar right along side the project-version.jar in the target directory.


<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</build>


Now whevever you package your application, you get two jars.


/target/project-version.jar
/target/project-version-sources.jar


This is perfect for open projects, weather its open to the world, or open to other developers in your company or office.

I learned about this on the maven-users mailing list today.

Maven: Keep track of your Build Number

Problem: You need to differentiate between build numbers. For example, you've just redeployed your application and need to ensure that the new version is what you are viewing and not the old one. Or, you need to keep track of how many times you build. There could be many reasons why you want to know the build number that you are on. For me, its just for fun.

Solution: maven-buildnumber-plugin. This Maven2 plugin will generate a unique build number each time your build your project. You can even configure which maven phase triggers the incrementation of the number. This plugin can also fetch data from SVN to ensure that a team of developers all get unique build numbers.

As a bonus, it generates a buildNumber.properties file so that you can read in this build number from anywhere in your project. Here is how I use the plugin.

First, update your pom.


<groupId>com.mycompany.myapp</groupId>
<artifactId>projectname</artifactId>
<packaging>war</packaging>
<version>1.0</version>

...

<pluginRepositories>
<pluginRepository>
<id>tlc</id>
<name>TLC Repository</name>
<url>http://commons.ucalgary.ca/pub/m2</url>
</pluginRepository>
</pluginRepositories>

...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>maven-buildnumber-plugin</artifactId>
<version>0.9.4</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>true</doCheck>
<doUpdate>false</doUpdate>
<format>${version}.{0,number}</format>
<items>
<item>buildNumber0</item>
</items>
</configuration>
</plugin>
</plugins>
</build>
Now, by adding the following to your pom.xml, when you package your project, you'd get a file called

projectname-1.0.1.war


<build>
<finalName>${project.artifactId}-${project.version}.{buildNumber}</finalName>
</build>


What I wanted, was to see the version on my application's index page. To do this, I use an ant filter to write the version and timestamp to a version.html file, and then copy it to my project' web app directory. I added this to my pom.xml.


<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<configuration>
<tasks>
<!-- versioning -->
<echo message="[build version]"/>
<delete file="target/projectname/version.html"/>
<tstamp>
<format property="rightNow" pattern="d MMM yyyy" locale="en"/>
</tstamp>
<copy todir="target/projectname">
<fileset dir="src/main/webapp">
<include name="version.html"/>
</fileset>
<filterset>
<filter token="VERSION" value="${buildNumber}"/>
<filter token="BUILTON" value="${rightNow}"/>
</filterset>
</copy>
<echo message=" version is ${buildNumber}"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


version.html is simple!

<label><em>Version</em></label> <small>@VERSION@</small><br>
<label><em>Built On</em></label> <small>@BUILTON@</small><br>

Finally, in my index page...

<jsp:include page="/version.html"/>
Almost everything you want to know about this plugin can be found on the plugin's site: http://commons.ucalgary.ca/projects/maven-buildnumber-plugin/introduction.html

Spring: OpenSessionInViewInterceptor vs. OpenSessionInViewFilter

Migrated posts and comments to a new site.

Spring: OpenSessionInViewInterceptor vs OpenSessionInViewFilter at 72miles.com

Spring MVC Controller processing

I found this in the Springframework Web forum. It was orginally created for the SpringMVC release Spring 1.2, but its also still good for Spring 2.x.







This is a very useful reference for developing your controllers and validators.

Spring: Authenticated User without Acegi using Interceptor

Spring 2.0.1
Problem: You want to make sure a user has logged in before allowing a page to be viewed.

Solution: Spring forums and documents all suggest using Acegi. The problem that I have with Acegi is that it is farily heavy weight. I've not used it, but I have been around projects that have used it. For the purposes of my current project, I wanted something simple. This internal application doesn't need a lot of security. My solution is made up of HandlerInterceptor implementation that I named AuthenticatedHandlerInterceptor.

More about my solution: I didn't make this up. I found it somewhere. Basically, before any controller is executed, the AuthenticatedHandlerInterceptor preHandle is executed. In this method, I ensure that a user has logged in via checking the session. If a user is not logged in, the request is redirected to the login page and a message is added to be displayed on the view.

Some views don't require the user to be logged in, so I had to provide a means for exluding pages. I did this by providing a String[] of pages in the AuthenticatedHandlerInterceptor. Lets look at my configuration. One of my applicationContext files (applicationContext-web.xml) contains this:


<!-- The interceptor to check that the user is indeed logged in. -->
<bean id="authenticatedInterceptor"
class="com.intellicare.contentloader.aspect.AuthenticatedHandlerInterceptor">
<property name="pagesThatDoNotRequireAuthentication">
<list>
<value>/login.page</value>
<value>/logout.page</value>
</list>
</property>
</bean>


pagesThatDoNotRequireAuthentication will be compared to the contextPath to determine if the requested view requires a user to be authenticated.

Next, I need to tell all my controllers to use this interceptor. In the case of my application, I am using a SimpleUrlHandlerMapping so my action-servlet.xml looks like this:


<!-- The interceptor to check that the user is indeed logged in. -->

<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<!-- url mappings -->
<property name="mappings">
<props>
<prop key="/login.page">loginController</prop>
<prop key="/logout.page">logoutController</prop>
</props>
</property>

<!-- the interceptor -->
<property name="interceptors">
<list>
<ref bean="authenticatedInterceptor"/>
</list>
</property>
</bean>


Finally, here's a look at the AuthenticatedHandlerInterceptor.


import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AuthenticatedHandlerInterceptor implements HandlerInterceptor {

private String[] pagesThatDoNotRequireAuthentication;


/*
* @see org.springframework.web.servlet.HandlerInterceptor
* #preHandle(HttpServletRequest, HttpServletResponse, Object)
*/

public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {

/* first, check if the requested view even required authentication */
if (isAuthenticationRequired(request)) {

/* check to see that user is logged in */
if (null == request.getSession().getAttribute("authenticated_user")) {
return forwardToLogonPage(request, response);
}

/* all is ok - pass the request on */
return true;
}
}

/**
* determines if the view that was requested requires the user to be authenticated
*
* @param request HttpServletRequest
* @return boolean flase if the requested view
* is in pagesThatDoNotRequireAuthentication
*/

private boolean isAuthenticationRequired(final HttpServletRequest request) {

String contextPath = request.getRequestURL().toString();

for (int i = 0; i < pagesThatDoNotRequireAuthentication.length; i++) {

String page = pagesThatDoNotRequireAuthentication[i];

if (0 > contextPath.indexOf(page)) {
return false;
}
}

return true;

}

/**
* sends a redirect to the login page
*/

private boolean forwardToLogonPage(HttpServletRequest request,
HttpServletResponse response)
throws IOException {

response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + "/index.jsp"));
return false;
}

public void setPagesThatDoNotRequireAuthentication(String[] pages) {
this.pagesThatDoNotRequireAuthentication = pages;
}
}


Bonus: When you implement the HandlderInterceptor interface, you'll have to also implement the method


void postHandle(final HttpServletRequest request,
final HttpServletResponse response,
final Object handler,
final ModelAndView modelAndView) throws Exception


If you want, you can do something after the controller has executed. In my case, I left this method with an empty body, but you might have something you'd like to do, like logging.