Here is the command:
find . -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r | head
Here is the command:
find . -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r | headI have a collection of 160 photos that I would like to montage into a movie. Each photo was done on a different day and the brightness of each photo varies. This will definitely not look good on the photo, so I’ve decided to “normalize” the brightness across the images. That is:
I have used utility called identify from ImageMagick package
% identify -format "%[mean] %f\n" *JPG | sort -rn
44153.8 2011.06.22.JPG
37955.8 2011.06.11.JPG
#...many more...
23019.2 2011.06.01.JPG
21256.8 2011.06.06.JPG-format option allows for specifying what kind of information about the image we want to output. In this case I went for average brightness – %[mean] and filename – %f, see the full documentation if you’re interested in other possibilities.
The difference between top and bottom photos is quite big: 21256.8 for 2011.06.06.JPG and 44153.8 for 2011.06.22.JPG – see the photos below.


Now let’s calculate the average value of brightness – awk to the rescue!
% identify -format "%[mean] %f\n" *JPG | sort -rn | awk 'BEGIN {FS=" "} { sum += $1; } END { printf "%s",sum/NR}'
29481.9So I need to bring all the photos to the mean brightness of about 29481.9. The best option I’ve found to do that is to use -sigmoidal-contrast from ImageMagick. I don’t know what values for -sigmoidal-contrast I need to use, to get from one brightness to another, so I wrote a simple script that will try to do that using binary search algorithm. It’s really very quick & dirty script but it does the job. The main loop is as follows:
do {
$current = ($min + $max) / 2;
$brightness = adjust($current, $file);
$diff = $target - $brightness;
if($diff > 0) {
//we need to make it lighter
$min = $current;
} else {
//we need to make it darker
$max = $current;
}
$i++;
} while(abs($diff) > 200);adjust function basically calls external convert utility to perform the adjustment:
convert $file -sigmoidal-contrast '$value,0%' $tmpfileand then checks and returns the brightness after conversion. I use -sigmoidal-contrast option to increase brightness and +sigmoidal-contrast to decrease. Now, that’s much better:


Here is the complete script – as I’ve said: quick & dirty job.
Recently I had to locate the widest image in the set of photos in a directory. Here is how you can easily do it with identify command, from ImageMagick suit:
% identify -format '%w %f\n' * | sort -rn | head -n1
563 2010.12.30.JPGYou can see in the output that the widest image is 563 pixels wide and the filename is 2010.12.30.JPG.
mogrify is the tool you are looking for – it comes with the great imagemagick package and it’s designed especially to be used for bulk operations.
To resize all images in current directory to 600 pixels wide (width):
% mogrify -resize 600 *The same but 600 height:
% mogrify -resize x600 *I have a collection of related photos stored on my PC. The filenames were “ugly” – standard file names coming from the photo camera. I would like to rename them into a file containing the date when the photo was shoot, e.g. 2011.07.21.jpg. There is an excellent commandline tool to do just that – renrot. It’s packaged for Debian & Ubuntu so to install it, I’ve simply run:
apt-get install renrotThen, in the directory that contains my photos I’ve run:
renrot -n "%Y.%m.%d" *-n option allows for specifying the template used for renaming the files – it is year, month and day separated with dots in my case. If the tool creates more files, you can remove the originals:
rm *origRefer to manual page for the full options!
In this blog we’ll be looking at how to use hibernate tools with just ant. This may be useful if you need to plug some hibernate tasks into your build system or have them scripted in any way. We will create a stand-alone ant build file with the minimum number of required libraries.
I’ve extracted hibernate tools jar from eclipse hibernate plugin. You can find it in your eclipse installation directory, under plugins:
plugins/org.hibernate.eclipse_X.X.X.X/lib/tools. Take hibernate-tools.jar and freemarker.jar. From plugins/org.hibernate.eclipse_X.X.X.X/lib/hibernate grab more jars:
You will also need org.apache.commons.logging.jar and JDBC driver. I use MySQL, so I’ve added mysql-connector-java-5.1.13.jar as well. Put all the jars into “lib” directory. Create other directories: classes, src and generated. Or don’t bother – download the whole lot as I’ve set it up.
We will use two sample entity classes (POJOs) for that example: Password and Resource. A Resource can contain many Passwords.
public class Password implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String password;
// many-to-one association to Resource
private Resource resource;
public Password() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public Resource getResource() {
return this.resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
}public class Resource implements Serializable {
private static final long serialVersionUID = 15146339L;
private int id;
private String name;
public Resource() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}Next, let’s create simple hibernate.cfg.xml…
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernatetutorial</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">****</property>
<property name="hibernate.connection.pool_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- Mapping files -->
<mapping resource="password.hbm.xml"/>
<mapping resource="resource.hbm.xml"/>
</session-factory>
</hibernate-configuration>…and mapping files for password and resource.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="net.opensesam.entity.Password" table="password">
<id name="id" type="long" column="ID" />
<many-to-one name="resource_id" class="net.opensesam.entity.Resource" />
<property name="password">
<column name="password" />
</property>
</class>
</hibernate-mapping><?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="net.opensesam.entity.Resource" table="resource">
<id name="id" type="long" column="ID" />
<property name="name">
<column name="name" />
</property>
</class>
</hibernate-mapping>Finally we can build build.xml! We’ll first add paths to the required jars, then define new task: hibernatetool. We can then use our new task via <hibernatetool> tag – see the code below, it’s pretty self-explanatory.
<project name="MyProject" basedir="." default="default">
<path id="toolslib">
<path location="lib/dom4j-1.6.1.jar" />
<path location="lib/freemarker.jar" />
<path location="lib/hibernate3.jar" />
<path location="lib/hibernate-tools.jar" />
<path location="lib/log4j-1.2.15.jar" />
<path location="lib/org.apache.commons.logging.jar" />
<path location="lib/slf4j-api-1.5.8.jar" />
<path location="lib/slf4j-log4j12-1.5.8.jar" />
<path location="lib/mysql-connector-java-5.1.13.jar" />
</path>
<taskdef name="hibernatetool"
classname="org.hibernate.tool.ant.HibernateToolTask"
classpathref="toolslib" />
<target name="default">
<hibernatetool destdir="./generated">
<classpath>
<path location="." />
<path location="./classes" />
</classpath>
<configuration configurationfile="hibernate.cfg.xml"/>
<hbm2ddl export="false" outputfilename="sql.ddl"/>
</hibernatetool>
</target>
</project>We are running above hbm2ddl task to export database schema into ./generated/sql.ddl file. Other tasks you can use are:
Refer to the documentation for more details.
If you prefer to use hibernate annotations, you need to do few changes. Add two extra jars:
Change <configuration> tag into <annotationconfiguration>:
<annotationconfiguration configurationfile="hibernate.cfg.xml"/>Your hibernate.cfg.xml will obviously need to contain pointers to annotated classes, e.g.:
<mapping class="net.opensesam.entity.Password" />I have it configured with the open source project “Open Sesame” – you can see the whole configuration in git repository.
You can also download a full source code for the non-annotated example.
Remember me functionality is a mechanism that lets users log in automatically, even when they re-start their browser. In other words: after their session cookie is deleted by the browser (which is normally after closing the browser). This is implemented by setting up another cookie that will live in the browser’s database for a longer period (e.g. weeks). Spring out of the box offers two implementations of this feature. This tutorial presents two different approaches to cookie creation: hash-based token and persistent token. We will only look into the remember-me part of the Spring Security configuration, if you need more information look at basic setup.
Implemented by org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices, it creates a base64 encoded cookie that contains:
Hash is used to confirm that cookie is valid – e.g. no-one has tried to tweak the cookie manually. A key is a very important variable here – we set it in Spring’s configuration and it should be a unique, secret for our application. As nobody knows what key we have picked, no one will be able to generate valid hash. The above also means that:
The configuration itself is trivial, simply add one line with <remember-me> tag to security.xml (again, refer to the previous post for basics):
<http auto-config="true" >
<remember-me key="...verylonganduniquekey..." />
<intercept-url pattern="/*" access="ROLE_USER" />
</http>This automatically adds a new checkbox to the standard login form.

Once you login, notice additional cookie created: SPRING_SECURITY_REMEMBER_ME_COOKIE.

To test functionality, delete JSESSIONID cookie and refresh. Normally that would effectively result in a logging out but with our “remember me” cookie, new JSESSIONID is created straight away.
A better solution to remember me cookie is to use totally random string that will be stored as a cookie and has no meaningful data in itself. The disadvantage is that it requires storing some information on the server side. When token is presented from user’s browser, it is matched against a record in table with all tokens. Our Spring configuration will change only a bit.
<http auto-config="true" >
<remember-me data-source-ref="dataSource" />
<intercept-url pattern="/*" access="ROLE_USER" />
</http>We will also need a table “persistent_logins” to store tokens. For MySQL you can use following SQL.
CREATE TABLE IF NOT EXISTS `persistent_logins` (
`username` VARCHAR(64) DEFAULT NULL,
`series` VARCHAR(64) NOT NULL DEFAULT '',
`token` VARCHAR(64) DEFAULT NULL,
`last_used` datetime DEFAULT NULL,
PRIMARY KEY (`series`)
)As you can see there are actually two new pieces there: series and token. Both are random strings and both are passed back to user and stored in the cookie. The idea here is that token will be changed on every “remember me” login, so when a user comes with valid series but invalid token – the chances are that the cookie has been stolen and used for authentication! We could not prevent stealing the cookie but we can at least:
And this is exactly what Spring Security is doing.
Sometimes it might be very convenient to be able to debug application deployed on web server. This tutorial presents how to do it, if the application is deployed using Jetty plugin for Maven or Tomcat servers.
Set the following MAVEN_OPTS to the following:
export MAVEN_OPTS='-Xdebug -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=y'Run Jetty Maven plugin:
mvn jetty:runSample setting of the development environment can be found here: Eclipse environment for convenient development of Java web application using Maven, Spring, Struts2, and Hibernate running on Jetty server.
Use default options of Tomcat which are
-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=nor set JPDA_OPTS using the following command:
export JPDA_OPTS='-agentlib:jdwp=transport=dt_socket,address=4000,server=y,suspend=y'Run Tomcat:
catalina jpda startHere is list of parameters for the debugging.
Go to: Debug -> Debug Options…
Select: Remote Java Application
Select project
Use the same port as defined in ‘address’

Click: Debug
If ‘suspend=y’ then your application should start. At this stage when you put any break point in Eclipse, your application should stop there.
Please refer to:
In the tutorial below we will look at a basic integration of a Java web application with Spring Security 3. In this particular scenario we’ll be integrating Spring Security with existing web application that uses Struts & Spring. However, similar steps can be applied to any other web framework you may be using. We will also look at one of the core concepts Spring Security – AccessDecisionManager.
We will start with an application that has no security implemented. I’ve used this setup as my base. It already uses maven, so the first thing we do is to add a new repository:
<repository>
<id>org.springframework.security</id>
<name>Spring Security</name>
<url>http://maven.springframework.org/snapshot</url>
</repository>and bunch of new JARs:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.0.6.CI-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.0.6.CI-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.0.6.CI-SNAPSHOT</version>
</dependency>Spring Security is implemented as a filter – it can be plugged into the application without any changes. A request will be intercepted by DelegatingFilterProxy and authentication will take place, as defined in Spring security XML file. We will add filter to the top of web.xml and trigger it for all URLs (url pattern set to /*).
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>For the very basic integration, Spring Security will require only little configuration that we’ll put into security.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd
">
<http auto-config="true">
<intercept-url pattern="/*" access="ROLE_USER" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user authorities="ROLE_USER" name="guest" password="test" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>We are defining here that access to any resource (intercept-url pattern=”/*”) should be allowed only for users that have authority called ROLE_USER. Normally user credentials will need to be stored in a central place – typically a database or LDAP server. Above we are hard-coding an authentication-provider with one user (guest/test) that has authority ROLE_USER.
Finally, we need to tell Spring about security.xml. Since our application already uses Spring, we have defined in web.xml contextConfigLocation parameter already – it points to our beans definition (applicationContext.xml). We will add security.xml in the same place:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/resources/applicationContext.xml
/WEB-INF/resources/security.xml
</param-value>
</context-param>When we build the application now, any URL should automatically generate following login page:

Spring Security deals (or helps you deal with) two security concepts: first authentication and then authorization. Authentication filters are run first – they will make sure that a user is who he says he is. This is usually done by checking user credentials, e.g., username and password). Let’s skip authentication step for now and talk about authorization. Authorization takes care of deciding if authenticated user (meaning that authentication must precede authorization) should be allowed to access a resource.
Spring Security supports authorization with the help of AccessDecisionManager interface. AccessDecisionManagers in turn will use one or more AccessDecisionVoters. Each voter will make the decision about granting or denying the access for given user to given resource. Access decision manager will aggregate the votes and issue final decision. Voters can return: ACCESS_GRANTED,ACCESS_DENIED but also ACCESS_ABSTAIN if a voter can’t or doesn’t want to make a decision. Managers must make the final decision – user is either granted access or not. The “not granting the access” part is done by throwing an exception – usually AccessDeniedException. In the default configuration that we’ve created, Spring uses implementation of AccessDecisionManager called AffirmativeBased. It will grant the access if any voter returns ACCESS_GRANTED. The default voters are
We can see authorization in working when we enable higher logging level – simply add to log4j properties:
log4j.logger.org.springframework.security=DEBUG, consoleWhen we try to access protected page as anonymous user, among other messages we can see following entries, with AccessDeniedException thrown at the end. RoleVoter returns ACCESS_DENIED and AuthenticatedVoter returns ACCESS_ABSTAIN.
DEBUG | 2011-07-10 12:40:30,473 | AffirmativeBased.java | decide | 53 | Voter: org.springframework.security.access.vote.RoleVoter@1ae73783, returned: -1
DEBUG | 2011-07-10 12:40:30,474 | AffirmativeBased.java | decide | 53 | Voter: org.springframework.security.access.vote.AuthenticatedVoter@41ed8741, returned: 0
DEBUG | 2011-07-10 12:40:30,478 | ExceptionTranslationFilter.java | handleException | 153 | Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is deniedCompare it with the log after we provide correct credentials. This time RoleVoter returns ACCESS_GRANTED and as soon as it happens, AffirmativeBased access decision manager stops querying voters and allows for access:
DEBUG | 2011-07-10 12:43:33,468 | AffirmativeBased.java | decide | 53 | Voter: org.springframework.security.access.vote.RoleVoter@1ae73783, returned: 1
DEBUG | 2011-07-10 12:43:33,469 | AbstractSecurityInterceptor.java | beforeInvocation | 213 | Authorization successfulThere are other implementations of AccessDecisionManagers and AccessDecisionVoters but I think we will leave them for another time. Stay tuned!
Here is a full source code for the example above. Run it with:
mvn jetty:runWhen developing web application set up of convenient development environment might be crucial for more efficient work. Let’s consider web application that uses following frameworks:
In addition we want to use Eclipse as our editor.
This tutorial presents initial setting of Eclipse project to support all the frameworks mentioned above and allow the convenient and fast application development of web application on Jetty server.
[ad#adsense]
First step is to create Ecplise project, e.g., Dynamic Web Project, that would have the following structure:

Make sure that ‘src/main/java’ and ‘test/main/java’ are your source folders on building path and default output folder is ‘target/classes’.

Complete Eclipse project can be downloaded here:
Maven configuration is in ‘pom.xml’ file. It consists of:
Make sure that:
maven-war-plugin. The WAR Plugin is responsible for collecting all artifact dependencies, classes and resources of the web application and packaging them into a web application archive.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>src/main/webapp</directory>
<targetPath>/</targetPath>
<!-- enable filtering -->
<filtering>false</filtering>
</resource>
</webResources>
</configuration>
</plugin>maven-jetty-plugin. In order to run Jetty on a webapp project which is structured according to the usual Maven defaults.
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<stopKey>stop</stopKey>
<stopPort>9999</stopPort>
<scanTargets>
<scanTarget>src/</scanTarget>
</scanTargets>
</configuration>
</plugin>Configuration of ‘pom.xml‘ is presented below:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.zabuchy</groupId>
<artifactId>SpringSecurity</artifactId>
<version>0.1</version>
<packaging>war</packaging>
<name>SpringSecurity</name>
<url>http://www.zabuchy.net</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- I know people complains about java.net repository, but it solves dependencies
to JEE so... -->
<repository>
<id>java.net</id>
<name>Java.net Maven Repository</name>
<url>http://download.java.net/maven/2</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
<repository>
<id>com.springsource.repository.bundles.release</id>
<name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>
<url>http://repository.springsource.com/maven/bundles/release</url>
</repository>
<repository>
<id>com.springsource.repository.bundles.external</id>
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
<url>http://repository.springsource.com/maven/bundles/external</url>
</repository>
<repository>
<id>com.springsource.repository.libraries.release</id>
<name>SpringSource Enterprise Bundle Repository - SpringSource Library Releases</name>
<url>http://repository.springsource.com/maven/libraries/release</url>
</repository>
<repository>
<id>com.springsource.repository.libraries.external</id>
<name>SpringSource Enterprise Bundle Repository - External Library Releases</name>
<url>http://repository.springsource.com/maven/libraries/external</url>
</repository>
<repository>
<id>org.springframework.security</id>
<name>Spring Security</name>
<url>http://maven.springframework.org/snapshot</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<!-- Please add dependencies alphabetically so we can detect duplicates -->
<dependencies>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.jgeppert.struts2.jquery</groupId>
<artifactId>struts2-jquery-plugin</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.8.0.GA</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.6-Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.5.6-Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.13</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.0.6.CI-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.0.6.CI-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.0.6.CI-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>src/main/webapp</directory>
<targetPath>/</targetPath>
<!-- enable filtering -->
<filtering>false</filtering>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<stopKey>stop</stopKey>
<stopPort>9999</stopPort>
<scanTargets>
<scanTarget>src/</scanTarget>
</scanTargets>
</configuration>
</plugin>
</plugins>
</build>
</project>Configuration of ‘web.xml‘ is presented below:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SpringSecurity</display-name>
<!-- Struts2 filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<!-- Spring beans -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/resources/applicationContext.xml
</param-value>
</context-param>
<!-- log4j -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/resources/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>Configuration of ‘log4j.properties‘ is presented below:
### direct log messages to stdout ###
log4j.rootLogger=ERROR, file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%6p | %d | %F | %M | %L | %m%n
# AdminFileAppender - used to log messages in the admin.log file.
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=target/SpringSecurity.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%6p | %d | %F | %M | %L | %m%n
log4j.logger.net.zabuchy=DEBUG, consoleConfiguration of Spring beans should be placed in ‘applicationContext.xml’ file. In this project Spring beans configuration files were included in ‘applicationContext.xml’ file. ‘beans.xml’ defines ‘outcomeAction’ bean, which represents Struts2 action and other beans required by this action, i.e., ‘outcomeDeterminer’. ‘databaseBeans.xml’ includes configuration of beans required by Hibernate. ‘dataSource’ bean includes configuration of database to be used in this project. It should be changed accordingly. ‘sessionFactory’ bean includes configuration of Hibernate like dataSource (pointing to ‘dataSource’ bean) and packagesToScan for @Entity beans. Content of the files is presented below.
‘applicationContext.xml‘ file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="spring/beans.xml" />
<import resource="spring/databaseBeans.xml" />
</beans>‘spring/beans.xml‘ file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean class="net.zabuchy.actions.OutcomeAction" id="outcomeAction"
scope="session">
<property name="outcomeDeterminer" ref="outcomeDeterminer" />
<aop:scoped-proxy />
</bean>
<bean class="net.zabuchy.business.OutcomeDeterminer" id="outcomeDeterminer">
<aop:scoped-proxy />
</bean>
</beans>‘spring/databaseBeans.xml‘ file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- Data source configuration -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/db" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<!-- Hibernate session factory -->
<bean
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
id="sessionFactory">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!-- In prod set to "validate", in test set to "create-drop" -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- In prod set to "false" -->
<prop key="hibernate.show_sql">false</prop>
<!-- In prod set to "false" -->
<prop key="hibernate.format_sql">true</prop>
<!-- In prod set to "false" -->
<prop key="hibernate.use_sql_comments">true</prop>
<!-- In prod set to "false", in test set to "true" -->
<prop key="hibernate.cache.use_second_level_cache">false</prop>
</props>
</property>
<property name="packagesToScan" value="net.zabuchy" />
</bean>
</beans>Struts2 actions are defined in ‘struts.xml‘ file, which is presented below. ‘getOutcome’ action uses ‘outcomeAction’ bean configuration and invokes ‘getOutcome’ method from this bean. If ‘getOutcome’ method returns ‘success’,'success.jsp’ will be displayed. If ‘getOutcome’ method returns ‘error’,'error.jsp’ will be displayed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package extends="struts-default" name="default">
<global-results>
<result name="error">error.jsp</result>
</global-results>
<action class="outcomeAction" method="getOutcome" name="getOutcome">
<result name="success">/WEB-INF/content/success.jsp</result>
</action>
</package>
</struts>Sample Java classes code, which was used in this project is presented below. Two classes were created and defined as Spring beans in ‘beans.xml’ file: ‘OutcomeAction’, which is Struts2 action and ‘OutcomeDeterminer’, which is class used by this action.
‘OutcomeAction.java‘ file in package net.zabuchy.actions
package net.zabuchy.actions;
import net.zabuchy.business.OutcomeDeterminer;
import org.apache.struts2.dispatcher.DefaultActionSupport;
public class OutcomeAction extends DefaultActionSupport {
private static final long serialVersionUID = 4794228472575863567L;
private OutcomeDeterminer outcomeDeterminer;
public String getOutcome() {
return outcomeDeterminer.getOutcome();
}
public OutcomeDeterminer getOutcomeDeterminer() {
return outcomeDeterminer;
}
public void setOutcomeDeterminer(OutcomeDeterminer outcomeDeterminer) {
this.outcomeDeterminer = outcomeDeterminer;
}
}‘OutcomeDeterminer.java‘ file in package net.zabuchy.business
package net.zabuchy.business;
import java.util.Random;
import org.apache.log4j.Logger;
public class OutcomeDeterminer {
private static final Logger logger = Logger.getLogger(OutcomeDeterminer.class
.getName());
private Random generator;
public OutcomeDeterminer() {
generator = new Random();
}
public String getOutcome() {
int randomNumber = generator.nextInt(5);
if (logger.isDebugEnabled()) {
logger.debug("Random number is: " + randomNumber);
}
if (randomNumber == 0) {
return "error";
}
return "success";
}
}The easiest way to add required libraries to Eclipse is allow Maven to download all the required libraries (defined as dependencies in pom.xml) and add them to ‘Referenced Libraries’. In order to do so in root directory of the application run:
mvn packageThis command should build war package to be deployed on web server including:

In Eclipse add libraries from ‘target/{projectName}/WEB-INF/lib’ to build path. It might be required to move them to the top ‘Order and Export’.

We are going to use jetty server to run the application. ‘jetty:run’ command allows the automatic reloads, so during development the changes done in Eclipse are automatically deployed to the server. In order to run the application type:
mvn jetty:runmaven-jetty-plugin automatically scans ‘src’ (configured in ‘scanTargets’ section of maven-jetty-plugin) every 5 seconds (configured in ‘scanIntervalSeconds’ section of maven-jetty-plugin) for changes.
To deploy the project on different web server, e.g., Tomcat, just use ‘mvn package’ command and copy war file to appropriate directory on your Tomcat server.
In your web browser access the following link: ‘http://localhost:8080/SpringSecurity/getOutcome.action’. You should be able to see either success or error page.