This is an old revision of the document!


New Java Web Applications

If you are making a company project :

  • You NEED nexus access, contact anthony.arents@mentoringsystems.be

All new projects have specific requirements in the buildprocess :

  • Netbeans project
  • Maven
  • Spring (3.0.5.RELEASE → standard)
  • Spring Security (3.0.5.RELEASE → standard)
  • Hibernate (3.6.10.FINAL → standard)
  • Javamelody (extra used for statistics, developer tool)
  • ExtJS 5
  • Tomcat 7
  • Use Java 7 for compiling, I recommend Java 8 for running tomcat (no permgen errors) ;-).

Package structure :

be.mentoringsystems.applicationname.dao

Contains DAO interfaces, naming ObjectnameDAO

be.mentoringsystems.applicationname.dao.hibernate

Contains DAO implementations, naming HibernateObjectnameDAO, extends HibernateDaoSupport, implements ObjectnameDAO

be.mentoringsystems.applicationname.model.db

Contains models which will be stored in the database, naming Ojectname

be.mentoringsystems.applicationname.presentation

Contains controllers which will be accessed via Rest, naming ObjectnameController

be.mentoringsystems.applicationname.security

Contains overrides for security

be.mentoringsystems.applicationname.service

Contains Service interfaces, naming ObjectnameService

be.mentoringsystems.applicationname.service.impl

Contains Service implementations, naming ObjectnameServiceImpl, implements ObjectnameService, uses ObjectnameDAO & Transactional annotations

German Projects

de.jcpis.applicationname

see above for details.

How to start :

Start with creating mocks & database model

Create a new project : New Project → Maven → Web Application

POM :

Change the POM (configuration files → pom.xml) to this :

<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">
    <!-- remove parent if you are not making a company project -->
    <parent>
        <groupId>com.msfcore</groupId>
        <artifactId>MentoringSystems</artifactId>
        <version>1.2</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>be.mentoringsystems.applicationname</groupId>
    <artifactId>applicationname</artifactId>
    <packaging>war</packaging>
    <description>A description of the application</description>
    <version>1.0-SNAPSHOT</version>
 
    <name>applicationname</name>
    <url>http://maven.apache.org</url>
 
    <!--properties>
        <skipTests>false</skipTests>
    </properties-->
 
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-asm</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.0.5.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-acl</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-aspects</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-lgpl</artifactId>
            <version>1.6.9</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-lgpl</artifactId>
            <version>1.6.9</version>
        </dependency>
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>jta</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>3.3.1</version>
        </dependency>
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm-attrs</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>jtidy</artifactId>
            <version>r8-21122004</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.0.GA</version>
        </dependency>
        <dependency>
            <groupId>antlr</groupId>
            <artifactId>antlr</artifactId>
            <version>2.7.6</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>3.6.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.6.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-tools</artifactId>
            <version>3.2.3.GA</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-commons-annotations</artifactId>
            <version>3.2.0.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.6.10.Final</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.5.5</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils-bean-collections</artifactId>
            <version>1.8.3</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils-core</artifactId>
            <version>1.8.3</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!-- javamelody-core -->
        <dependency>
            <groupId>net.bull.javamelody</groupId>
            <artifactId>javamelody-core</artifactId>
            <version>1.52.0</version>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat6-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <mode>both</mode>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.8</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.7</version>
                <configuration>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.15</version>
                <configuration>
                    <skipTests>${skipTests}</skipTests>
                    <argLine>-XX:-UseSplitVerifier</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

This will set most of your dependencies straight,
the parent pom ensures all projects use UTF-8 encoding for files & sets some maven plugins.

web.xml :

Now we need the following in our WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
			classpath:net/bull/javamelody/monitoring-spring.xml
			/WEB-INF/applicationname.xml
		</param-value>
    </context-param>
    <listener>
        <listener-class>net.bull.javamelody.SessionListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>applicationname</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>applicationname</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <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>
    <filter>
        <filter-name>monitoring</filter-name>
        <filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
        <init-param>
            <param-name>url-exclude-pattern</param-name>
            <param-value>/static/.*</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>monitoring</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <session-config>
        <session-timeout>
            240
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.htm</welcome-file>
    </welcome-file-list>
    <mime-mapping>
        <extension>json</extension>
        <mime-type>application/json</mime-type>
    </mime-mapping>
</web-app>

applicationname.xml :

applicationname.xml is a spring context file which will bind most of the configuration files together
Here is a basic file for /WEB-INF/applicationname.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
">
 
    <bean id="paramResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
        <property name="paramName" value="action" />
        <property name="defaultMethodName" value="defaultMethod" />
    </bean>
 
    <import resource="classpath:/applicationname-*.xml" />
    <import resource="classpath*:/config/applicationname-*.xml" />
 
</beans>

seperate config files (services, security & database) now go into /WEB-INF/classes,
you get them there by creating the following folder : /src/main/resources which in netbeans will translate to Other Sources/src/main/resources/

Now that we have a skeleton, it's time to add some classes

Class buildup

Model

Let's start with a model

package be.mentoringsystems.applicationname.model.db;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Type;
 
// JPA: mark it as a database entity
@Entity
// JPA: which table
@Table(name = "Login")
// JSON: hide properties (hibernate properties have difficulty serializing, these properties were added automatically by hibernate byte code manipulation)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "password"})
public class Login implements Serializable {
 
    private Integer id;
    private String login;
    private String password;
    private boolean admin = false;
    private boolean active = true;
    private String firstname;
    private String lastname;
    private String email;
	private Date createdOn = new Date();
	private Date lastModified = new Date();
 
	// JPA: marks date fields
    @Temporal(TemporalType.TIMESTAMP)
    // JPA: column definition, non-nullable fields require mentioning
    @Column(name = "createdOn", nullable = false, length = 19)
    // you can add serializers to always return the date formatted like dd.MM.yyyy
    //@JsonSerialize(using = DateTimeFormatter.class)
    public Date getCreatedOn() {
        return this.createdOn;
    }
 
    public void setCreatedOn(final Date createdOn) {
        this.createdOn = createdOn;
    }
 
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "lastModified", length = 19)
    //@JsonSerialize(using = DateTimeFormatter.class)
    public Date getLastModified() {
        return this.lastModified;
    }
 
    public void setLastModified(final Date lastModified) {
        this.lastModified = lastModified;
    }
 
    /*@Column(name="rabat")
    public String getRabat() {
        return rabat;
    }
 
    public void setRabat(String rabat) {
        this.rabat = rabat;
    }*/
 
    /*public LoginAttribut getLoginAttribut(final String key) {
        for(LoginAttribut attribut : this.getLoginAttributs()) {
            if(attribut.getParamKey().equals(key)) {
                return attribut;
            }
        }
        final LoginAttribut loginAttribut = new LoginAttribut();
        loginAttribut.setParamKey(key);
        loginAttribut.setLogin(this);
        this.getLoginAttributs().add(loginAttribut);
        return loginAttribut;
    }
 
	// JPA: when this object is linked to multiple other objects, note fetchtype lazy.
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "login")
    // Hibernate: This ensures the dependant records will be removed by hibernate before the delete query is executed. JPA Cascade doesn't work in this version.
    @Cascade(CascadeType.ALL)
    public List<LoginAttribut> getLoginAttributs() {
        return loginAttributs;
    }
 
    public void setLoginAttributs(List<LoginAttribut> loginAttributs) {
        this.loginAttributs = loginAttributs;
    }*/
 
    public Login() {
    }
 
	// JPA mark ID
    @Id
    // JPA unique field
    @Column(name = "id", unique = true, nullable = false)
    // Hibernate Type & GeneratedValue for UUID (need to change the type of id to UUID)
    //@Type(type = "uuid-char")
    //@GeneratedValue(generator = "guid")
    // Hibernate GeneratedValue for mysql autoincrement columns INT(10) auto increment, Primary.
    @GeneratedValue(strategy = IDENTITY)
    public Integer getId() {
        return id;
    }
 
    public void setId(final Integer id) {
        this.id = id;
    }
 
    /* 
    // JPA : when several of this object are linked to the other object
    @ManyToOne(fetch = FetchType.LAZY)
    // the column that defines the relation, usually contains the ID of other object
    @JoinColumn(name = "contextId", unique = true)
    public Context getContext() {
        return this.context;
    }
 
    public void setContext(Context context) {
        this.context = context;
    }*/
 
	/*
    @Type(type = "uuid-char")
    // JPA : note usage of updatable & insertable, this allows us to have a column double so we can access the ID instead of the linked object.
    @Column(name = "contextId", updatable = false, insertable = false)
    public UUID getContextId() {
        return contextId;
    }
 
    public void setContextId(UUID contextId) {
        this.contextId = contextId;
    }*/
 
 
 
    @Column(name = "login", nullable = false, length = 200)
    public String getLogin() {
        return this.login;
    }
 
    public void setLogin(String login) {
        this.login = login;
    }
 
    @Column(name = "password", nullable = false, length = 73)
    public String getPassword() {
        return this.password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
 
    @Column(name = "admin", nullable = false, length = 1)
    // Hibernate type Char(1) values 'Y' or 'N'
    @Type(type = "yes_no")
    public boolean isAdmin() {
        return this.admin;
    }
 
    public void setAdmin(boolean admin) {
        this.admin = admin;
    }
 
    @Column(name = "active", nullable = false, length = 1)
    @Type(type = "yes_no")
    public boolean isActive() {
        return active;
    }
 
    public void setActive(boolean active) {
        this.active = active;
    }
 
    @Column(name = "firstname", nullable = false, length = 200)
    public String getFirstname() {
        return this.firstname;
    }
 
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
 
    @Column(name = "lastname", nullable = false, length = 200)
    public String getLastname() {
        return this.lastname;
    }
 
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
 
    @Column(name = "email", nullable = false)
    public String getEmail() {
        return this.email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
	// transient value meaning this won't be saved in the database, in some implementations, it also means it won't be serialized.
    /*@Transient
    public boolean isLinkedToBerater() {
        return (this.getBerater() != null);
    }*/
 
 
}

DAO Interface

Now we could use a DAO interface

package be.mentoringsystems.applicationname.dao;
 
import be.mentoringsystems.applicationname.model.db.Login;
import java.util.List;
 
/**
 *
 * @author anthonyarents
 */
public interface LoginDAO {
    void saveLogin(final Login login);
    void deleteLogin(final Login login);
    Login getLoginById(final Integer loginId);
    Login getLoginByLogin(final String login);
    Login getLoginByLogin(final String loginName, final boolean active);
    Login getLoginByLoginWithoutReferences(final String login);
    Login getLoginByLoginWithoutReferences(final String login, final boolean active);
    Login getLoginByEmail(final String email);
    List<Login> getAllLogins();
    List<Login> getAllLoginsBySearch(final String search, final int start, final int limit);
    Integer getAllLoginsCountBySearch(final String search);
}

DAO Implementation

A DAO implementation

package be.mentoringsystems.applicationname.dao.hibernate;
 
import be.mentoringsystems.applicationname.dao.LoginDAO;
import be.mentoringsystems.applicationname.model.db.Login;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
 
/**
 *
 * @author anthonyarents
 */
public final class HibernateLoginDAO extends HibernateDaoSupport implements LoginDAO {
 
    public void saveLogin(final Login login) {
        // save or update handles the checks to see if the object exists in the database
        getHibernateTemplate().saveOrUpdate(login);
    }
 
    public void deleteLogin(final Login login) {
        // normal delete, a "dummydelete" option is to add a delete flag to login & use save
        getHibernateTemplate().delete(login);
    }
 
    public Login getLoginById(final Integer loginId) {
        final HibernateTemplate template = getHibernateTemplate();
        // Hibernate: select by Id
        Login login = template.get(Login.class, loginId);
        // Hibernate: reuse hibernatetemplate (good for performance) & initialize only the lazy collections you need
        //template.initialize(login.getLoginAttributs());
        return login;
    }
 
    public Login getLoginByEmail(final String loginEmail) {
        final HibernateTemplate template = getHibernateTemplate();
        // criteria queries
        final DetachedCriteria criteria = DetachedCriteria.forClass(Login.class);
        // Restrictions = where clause
        criteria.add(Restrictions.eq("email", loginEmail));
        criteria.add(Restrictions.eq("active", true));
        // Order (sorting)
        criteria.addOrder(Order.desc("createdOn"));
        final List<Login> result = template.findByCriteria(criteria);
 
        if(result.isEmpty()) {
            return null;
        } else {
            final Login login = result.get(0);
            //template.initialize(login.getBerater());
            //template.initialize(login.getLoginAttributs());
            //template.initialize(login.getContext());
            return login;
        }
    }
 
    public Login getLoginByLoginWithoutReferences(final String loginName, final boolean active) {
        final HibernateTemplate template = getHibernateTemplate();
        final DetachedCriteria criteria = DetachedCriteria.forClass(Login.class);
        criteria.add(Restrictions.eq("login", loginName));
        if(active) {
            criteria.add(Restrictions.eq("active", active));
        }
        criteria.addOrder(Order.desc("createdOn"));
        final List<Login> result = template.findByCriteria(criteria);
 
        if(result.isEmpty()) {
            return null;
        } else {
            final Login login = result.get(0);
            //template.initialize(login.getLoginAttributs());
            //template.initialize(login.getContext());
            //template.initialize(login.getContext().getContextAttributs());
            return login;
        }
    }
 
    public Login getLoginByLoginWithoutReferences(final String loginName) {
        return getLoginByLoginWithoutReferences(loginName, true);
    }
 
    public Login getLoginByLogin(final String loginName, final boolean active) {
        final HibernateTemplate template = getHibernateTemplate();
        final DetachedCriteria criteria = DetachedCriteria.forClass(Login.class);
        criteria.add(Restrictions.eq("login", loginName));
        if(active) {
            criteria.add(Restrictions.eq("active", active));
        }
        criteria.addOrder(Order.desc("createdOn"));
        final List<Login> result = template.findByCriteria(criteria);
 
        if(result.isEmpty()) {
            return null;
        } else {
            final Login login = result.get(0);
            //template.initialize(login.getBerater());
            /*if(login.getBerater() != null) {
                template.initialize(login.getBerater().getBeratersForVorgesetzterId());
                for(BeraterVorgesetzter beraterVorgesetzter : login.getBerater().getBeratersForBeraterId()) {
                    template.initialize(beraterVorgesetzter.getBerater());
                    template.initialize(beraterVorgesetzter.getBerater().getEfpId());
                }
            }*/
            //template.initialize(login.getLoginAttributs());
            //template.initialize(login.getContext());
            //template.initialize(login.getContext().getContextAttributs());
            return login;
        }
    }
 
    public Login getLoginByLogin(final String loginName) {
        return getLoginByLogin(loginName, true);
    }
 
    public List<Login> getAllLogins() {
        final HibernateTemplate template = getHibernateTemplate();
        final List<Login> result = template.loadAll(Login.class);
        for(Login login : result) {
            /*if(login.getBerater() != null) {
                template.initialize(login.getBerater());
            }*/
            //template.initialize(login.getLoginAttributs());
            //template.initialize(login.getContext());
        }
        return result;
    }
 
    public Integer getAllLoginsCountBySearch(final String search) {
        final DetachedCriteria criteria = DetachedCriteria.forClass(Login.class);
        if(search != null) {
            criteria.add(Restrictions.or(Restrictions.like("login", "%" + search + "%"), Restrictions.like("lastname", "%" + search + "%")));
        }
        criteria.setProjection(Projections.rowCount());
        final List<Long> result = getHibernateTemplate().findByCriteria(criteria);
        return result.get(0).intValue();
    }
 
    public List<Login> getAllLoginsBySearch(final String search, final int start, final int limit) {
        final HibernateTemplate template = getHibernateTemplate();
        final DetachedCriteria criteria = DetachedCriteria.forClass(Login.class);
        criteria.addOrder(Order.asc("createdOn"));
        if(search != null) {
            criteria.add(Restrictions.or(Restrictions.like("login", "%" + search + "%"), Restrictions.like("lastname", "%" + search + "%")));
        }
        final List<Login> result = template.findByCriteria(criteria, start, limit);
 
        for(Login login : result) {
            /*if(login.getBerater() != null) {
                template.initialize(login.getBerater());
            }
            template.initialize(login.getLoginAttributs());
            template.initialize(login.getContext());*/
        }
        return result;
    }
}

Advanced hibernate criteria queries exist, If you need examples contact me :-).

Service Interface

package be.mentoringsystems.applicationname.service;
 
import be.mentoringsystems.applicationname.model.db.Login;
import java.util.List;
 
/**
 *
 * @author anthonyarents
 */
public interface LoginService {
    void saveLogin(final Login login);
    void deleteLogin(final Login login);
    Login getLoginById(final Integer loginId);
    Login getLoginByLogin(final String login);
    Login getLoginByLogin(final String loginName, final boolean active);
    Login getLoginByLoginWithoutReferences(final String login);
    Login getLoginByLoginWithoutReferences(final String login, final boolean active);
    Login getLoginByEmail(final String email);
    List<Login> getAllLogins();
    List<Login> getAllLoginsBySearch(final String search, final int start, final int limit);
    Integer getAllLoginsCountBySearch(final String search);
}

Service Implementation

package be.mentoringsystems.applicationname.service.impl;
 
import be.mentoringsystems.applicationname.dao.LoginDAO;
import be.mentoringsystems.applicationname.model.db.Login;
import be.mentoringsystems.applicationname.service.LoginService;
import java.util.ArrayList;
import java.util.List;
// always use this logger
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
 
/**
 *
 * @author anthonyarents
 */
// Spring: using spring Transactional annotation to manage transactions, 
// supports = don't need to be in a transaction but can be part of one
@Transactional(propagation = Propagation.SUPPORTS)
public final class LoginServiceImpl implements LoginService {
 
    private transient LoginDAO loginDAO;
    private static final Logger LOGGER = Logger.getLogger(LoginServiceImpl.class);
 
// required = need to be in a transaction, basicly, you want to change/delete/insert the object
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveLogin(final Login login) {
        loginDAO.saveLogin(login);
    }
 
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteLogin(final Login login) {
        loginDAO.deleteLogin(login);
    }
 
    public Login getLoginById(final Integer loginId) {
        return loginDAO.getLoginById(loginId);
    }
 
    public Login getLoginByLogin(final String login) {
        return loginDAO.getLoginByLogin(login);
    }
 
    public Login getLoginByLoginWithoutReferences(final String login) {
        return loginDAO.getLoginByLoginWithoutReferences(login);
    }
 
    public Login getLoginByLogin(final String login, final boolean active) {
        return loginDAO.getLoginByLogin(login, active);
    }
 
    public Login getLoginByLoginWithoutReferences(final String login, final boolean active) {
        return loginDAO.getLoginByLoginWithoutReferences(login, active);
    }
 
    public Login getLoginByEmail(final String email) {
        return loginDAO.getLoginByEmail(email);
    }
 
    public List<Login> getAllLogins() {
        return loginDAO.getAllLogins();
    }
 
    public List<Login> getAllLoginsBySearch(final String search, final int start, final int limit) {
        return loginDAO.getAllLoginsBySearch(search, start, limit);
    }
 
    public Integer getAllLoginsCountBySearch(final String search) {
        return loginDAO.getAllLoginsCountBySearch(search);
    }
 
    public void setLoginDAO(final LoginDAO loginDAO) {
        this.loginDAO = loginDAO;
    }
}

Presentation (controllers)

Do not use DAO classes here!
Method signature : public ModelAndView methodname(HttpServletRequest hsr, HttpServlerResponse hsr1)
Use of MappingJacksonJsonView to return a json Object (mapping happens automatically).

package be.mentoringsystems.applicationname.presentation;
 
import be.mentoringsystems.applicationname.model.db.Login;
import be.mentoringsystems.applicationname.service.LoginService;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import org.springframework.web.servlet.view.json.MappingJacksonJsonView;
 
/**
 *
 * @author anthonyarents
 */
public final class LoginController extends MultiActionController {
 
    private static final String SUCCESS = "success";
    private transient LoginService loginService;
    private static final Logger LOGGER = Logger.getLogger(LoginController.class);
 
    public ModelAndView getLogin(final HttpServletRequest hsr, final HttpServletResponse hsr1) {
        final MappingJacksonJsonView view = new MappingJacksonJsonView();
        view.addStaticAttribute(SUCCESS, false);
        final Login login = loginService.getLoginByLogin(hsr.getRemoteUser()); // use spring security in the future, hsr.getRemoteUser gives you the loginname but isn't always accurate
        if (login != null) {
 
            final Map<String, Object> userMap = new HashMap<String, Object>();
 
            userMap.put("id", login.getId());
            userMap.put("admin", login.isAdmin());
            userMap.put("login", login.getLogin());
            userMap.put("firstname", login.getFirstname());
            userMap.put("lastname", login.getLastname());
            userMap.put("email", login.getEmail());
 
            view.addStaticAttribute("data", userMap);
            view.addStaticAttribute(SUCCESS, true);
        }
        return new ModelAndView(view);
    }
 
    public ModelAndView getAllLogins(final HttpServletRequest hsr, final HttpServletResponse hsr1) {
        final MappingJacksonJsonView view = new MappingJacksonJsonView();
        view.addStaticAttribute(SUCCESS, false);
 
        //UUID contextId = HelperMethods.getUUID(hsr.getParameter("contextId"));
        //final Context context = contextService.getContextById(contextId);
 
        //if (securityService.hasAdminAccess(context)) {
            final List<Login> logins = loginService.getAllLogins();
            view.addStaticAttribute(SUCCESS, true);
            view.addStaticAttribute("hits", logins.size());
            view.addStaticAttribute("data", logins);
        //}
        return new ModelAndView(view);
    }
 
    public ModelAndView getAllLoginsBySearch(final HttpServletRequest hsr, final HttpServletResponse hsr1) {
        int start = 0;
        int limit = 20;
 
        if (hsr.getParameter("start") != null && hsr.getParameter("start").length() != 0) {
            start = Integer.parseInt(hsr.getParameter("start"));
        }
        if (hsr.getParameter("limit") != null && hsr.getParameter("limit").length() != 0) {
            limit = Integer.parseInt(hsr.getParameter("limit"));
        }
        final String search = hsr.getParameter("search");
 
        //UUID contextId = HelperMethods.getUUID(hsr.getParameter("contextId"));
        //final Context context = contextService.getContextById(contextId);
 
        final MappingJacksonJsonView view = new MappingJacksonJsonView();
        view.addStaticAttribute(SUCCESS, false);
 
        //if (securityService.hasAdminAccess(context)) {
            final List<Login> logins = loginService.getAllLoginsBySearch(search, start, limit);
            view.addStaticAttribute(SUCCESS, true);
            view.addStaticAttribute("hits", loginService.getAllLoginsCountBySearch(search));
            view.addStaticAttribute("data", logins);
        //}
        return new ModelAndView(view);
    }
 
    public void setLoginService(final LoginService loginService) {
        this.loginService = loginService;
    }
}

Further configuration

applicationname-database.xml

add applicationname-database.xml in Other Sources/src/main/resources/

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
">
 
    <bean id="defaultDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="password" value="root" />
        <property name="username" value="root" />
        <property name="defaultCatalog" value="dbname" />
        <property name="url" value="jdbc:mysql://localhost:3306/?useUnicode=true&amp;characterEncoding=UTF-8" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="maxActive" value="20"/>
        <property name="maxIdle" value="17"/>
        <property name="maxWait" value="10000"/>
        <property name="removeAbandoned" value="true" />
        <property name="testOnBorrow" value="true"/>
        <property name="validationQuery" value="SELECT 1;"/>
    </bean>
 
    <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="defaultDataSource"/>
        <property name="annotatedPackages">
            <list>
                <value>be.mentoringsystems.applicationname.model.db</value>
            </list>
        </property>
        <property name="packagesToScan">
            <list>
                <value>be.mentoringsystems.applicationname.model.db</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.use_sql_comments">false</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.jdbc.factory_class">net.bull.javamelody.HibernateBatcherFactory</prop>
                <prop key="hibernate.connection.useUnicode">true</prop>
                <prop key="hibernate.connection.characterEncoding">utf8</prop>
                <prop key="hibernate.connection.charSet">utf8</prop>
            </props>
        </property>
    </bean>
 
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>
 
    <bean id="loginDAO" class="be.mentoringsystems.applicationname.dao.hibernate.HibernateLoginDAO">
        <property name="sessionFactory" ref="mySessionFactory" />
    </bean>
 
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

applicationname-services.xml

add applicationname-services.xml in Other Sources/src/main/resources/

<?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-3.0.xsd">
 
    <bean id="loginService" class="be.mentoringsystems.applicationname.service.impl.LoginServiceImpl">
        <property name="loginDAO" ref="loginDAO" />
    </bean>
 
</beans>

applicationname-servlet.xml

Add applicationname-servlet.xml to /WEB-INF/
This file is picked up by the dispatcher servlet of spring so is essentially in a different scope (it can access everything defined in spring context)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" xmlns:aop="http://www.springframework.org/schema/aop">
 
     <!--mvc:resources mapping="/static/image/**" location="/static/image/" cache-period="2678400"/-->
    <mvc:resources mapping="/static/**" location="/static/" cache-period="604800"/>
 
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
 
 
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="300000000"/>
    </bean>
 
    <bean id="loginController" class="de.jcpis.analyse.presentation.LoginController">
        <property name="methodNameResolver" ref="paramResolver" />
        <property name="loginService" ref="loginService" />
    </bean>
 
    <bean id="urlFileViewer" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"></bean>
 
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="order" value="1000" />
        <property name="mappings">
            <props>
                <prop key="/login.html">loginController</prop>
                <prop key="/login.json">loginController</prop>
            </props>
        </property>
    </bean>
 
 
</beans>

JSP Pages

Add login.jsp to /WEB-INF/jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Login</title>
        <link type="text/css" rel="stylesheet" href="static/styles/login.css" />
    </head>
    <body class="loginPage">
<div id="page">
<div id="login">
    <div id="logincontent">
	    <h1 id="login-title">Login</h1>
        <form action="j_spring_security_check" method="post" id="login-form">
 
                <div>
                    <label for="username">Username :</label>
                    <input type='text' id="username" tabindex="1" name='j_username' />
                </div>
                <div>
                    <label for="password">Password :</label>
                    <input id="password" tabindex="2" type='password' name='j_password' />
                </div>
                <div class="submitbtn">
		    <input type="submit" tabindex="4" value="Login" class="loginButton" />
                </div>
        </form>
</div>
    </body>
</html>

Static resources (javascript, css, ...)

Don'y use html pages, use jsp like above. simply place the resource in /static/ or any subfolder there

Spring Security

Some overrides are needed to make things work the way we want them to :

Authentication provider

Spring Security needs some convincing to use our own models

package be.mentoringsystems.applicationname.security;
 
import be.mentoringsystems.applicationname.model.db.Login;
import be.mentoringsystems.applicationname.service.LoginService;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
 
/**
 * Implementation of AuthenticationProvider with support for our login service.
 *
 * @author anthonyarents
 */
@Transactional(propagation = Propagation.SUPPORTS)
public final class CustomAuthenticationProvider implements AuthenticationProvider {
 
    private transient LoginService loginService;
 
    public void setLoginService(final LoginService loginService) {
        this.loginService = loginService;
    }
 
    /**
     * This method is executed by spring security, it will authenticate a user
     * (check if username & password are correct).
     *
     * @param authentication authentication object supplied by spring security
     * @return UsernamePasswordAuthenticationToken (if login worked)
     */
    public Authentication authenticate(final Authentication authentication)
        final Login user = loginService.loginAsUser(authentication.getPrincipal().toString(), authentication.getCredentials().toString());
 
        final List<GrantedAuthorityImpl> authorities = getAuthorities(user);
 
        // don't give the password, it would be unprotected !
        final User userDetails = new User(authentication.getPrincipal().toString(), "", true, true, true, true, authorities);
        return new UsernamePasswordAuthenticationToken(userDetails, userDetails, authorities);
    }
 
    // This method can be used to add new roles based on login flags
    public List<GrantedAuthorityImpl> getAuthorities(final Login login) {
        final List<GrantedAuthorityImpl> authorities = new ArrayList<GrantedAuthorityImpl>();
        if (login.isAdmin()) {
            authorities.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
        }
        authorities.add(new GrantedAuthorityImpl("ROLE_USER"));
        return authorities;
    }
 
    /**
     * This method is used by spring security to determine if spring security
     * can use this class to authenticate a UsernamePasswordAuthenticationToken.
     *
     * @param type class of authenticationtoken
     * @return boolean
     */
    public boolean supports(final Class<? extends Object> type) {
        boolean result = false;
        if (type == UsernamePasswordAuthenticationToken.class) {
            result = true;
        }
        return result;
    }
}

UserDetailsService

Spring Security doesn't use authentication provider for everything.

package be.mentoringsystems.applicationname.security;
 
import be.mentoringsystems.applicationname.model.db.Login;
import be.mentoringsystems.applicationname.service.LoginService;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
 
/**
 *
 * @author anthonyarents
 */
public class UserDetailsServiceImpl implements UserDetailsService {
    private transient LoginService loginService;
    private static final Logger LOGGER = Logger.getLogger(UserDetailsServiceImpl.class);
 
    public void setLoginService(final LoginService loginService) {
        this.loginService = loginService;
    }
 
    @Override
    public UserDetails loadUserByUsername(String string) throws UsernameNotFoundException, DataAccessException {
        // get the user we want to switch to
        Login login = loginService.getLoginByLogin(string);
 
        // check if we are allowed to see the user (contexts!)
        /*Login admin = securityService.getLoginWithBerater();
        if(admin.isAdmin() && !securityService.hasAdminAccess(admin, login.getContext())) {
            throw new AccessDeniedException("Admin " + admin.getLogin() + " is not allowed to log in as " + login.getLogin() + " due to context differences");
        }
        Berater berater = beraterService.getBeraterById(login.getBeraterId());
        if(!securityService.hasAccess(admin, berater)) {
            throw new AccessDeniedException("User " + admin.getLogin() + " is not allowed to log in as " + login.getLogin() + ".");
        }*/
 
        return new User(login.getLogin(), login.getLogin(), true, true, true, true, getAuthorities(login));
    }
 
    public List<GrantedAuthorityImpl> getAuthorities(final Login login) {
        final List<GrantedAuthorityImpl> authorities = new ArrayList<GrantedAuthorityImpl>();
        if (login.isAdmin()) {
            authorities.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
        }
        authorities.add(new GrantedAuthorityImpl("ROLE_USER"));
        return authorities;
    }
 
}

Json fixes

We want a json message telling us we need to login when we do an AJAX request. else spring will redirect to the loginpage & our application will break without telling why. (not needed when polling the server)

Custom Access Denied Handler

package be.mentoringsystems.security;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper;
 
/**
 *
 * @author anthonyarents
 */
public class CustomAccessDeniedHandler extends AccessDeniedHandlerImpl {
 
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        final String jsonHeader = request.getHeader("X-Requested-With");
 
        if (jsonHeader != null) {
            response.setStatus(SaveContextOnUpdateOrErrorResponseWrapper.SC_UNAUTHORIZED);
            response.setHeader("Location", null);
            response.setContentType("application/json;charset=UTF-8");
            response.getOutputStream().print("{\"success\" : false, \"data\" : [], \"error\" : \"LOGIN REQUIRED\"}");
        } else {
            super.handle(request, response, accessDeniedException);
        }
    }
}

Custom Authentication Entry Point

package be.mentoringsystems.applicationname.security;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper;
 
/**
 *
 * @author anthonyarents
 */
public class CustomAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
 
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        final String jsonHeader = request.getHeader("X-Requested-With");
 
        if (jsonHeader != null) {
            response.setStatus(SaveContextOnUpdateOrErrorResponseWrapper.SC_UNAUTHORIZED);
            response.setHeader("Location", null);
            response.setContentType("application/json;charset=UTF-8");
            response.getOutputStream().print("{\"success\" : false, \"data\" : [], \"error\" : \"LOGIN REQUIRED\"}");
        } else {
            super.commence(request, response, authException);
        }
    }
 
}

applicationname-security.xml

add applicationname-security.xml in Other Sources/src/main/resources/

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:security="http://www.springframework.org/schema/security"
  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/security
           http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    <security:http auto-config="true" lowercase-comparisons="true" entry-point-ref="myCustomAuthenticationEntryPoint">
        <security:anonymous username="ANONYMOUS" />
        <security:access-denied-handler ref="myCustomAccessDeniedHandler"/>
        <security:intercept-url pattern="/static/**" filters="none" />
        <security:intercept-url pattern="/ws/**" filters="none" />
        <security:intercept-url pattern="/login.html" filters="none" />
        <security:intercept-url pattern="/j_spring_security_switch_user" access="ROLE_ADMIN" />
        <!-- useful if we need app.html to also be available for anonymous users -->
        <!--security:intercept-url pattern="/app.html" access="ROLE_ANONYMOUS, ROLE_USER" /-->
        <security:intercept-url pattern="/*" access="ROLE_USER" />
	<security:form-login login-page='/login.html' authentication-failure-url="/login.html" default-target-url="/app.html" always-use-default-target="true" />
        <security:session-management>
        </security:session-management>
        <security:custom-filter position="SWITCH_USER_FILTER" ref="switchUserFilter"/>
        <security:logout />
    </security:http>
 
    <security:global-method-security secured-annotations="enabled" />
 
    <security:authentication-manager>
        <security:authentication-provider ref="myAuthenticationProvider"/>
    </security:authentication-manager>
 
    <!-- authentication provider used by spring security to authenticate a request -->
    <bean id="myAuthenticationProvider" class="be.mentoringsystems.applicationname.security.CustomAuthenticationProvider">
        <property name="loginService" ref="loginService" />
    </bean>
 
    <bean id="switchUserFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
        <property name="userDetailsService" ref="myUserDetailsService" />
        <property name="switchUserUrl" value="/j_spring_security_switch_user" />
        <property name="exitUserUrl" value="/j_spring_security_exit_user" />
        <property name="targetUrl" value="/app.html" />
     </bean>
 
    <bean id="myUserDetailsService" class="be.mentoringsystems.applicationname.security.UserDetailsServiceImpl">
        <property name="loginService" ref="loginService" />
    </bean>
 
    <!-- special custom filter to avoid redirects during json requests -->
    <bean id="myCustomAuthenticationEntryPoint" class="be.mentoringsystems.applicationname.security.CustomAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/login.html" />
    </bean>
 
    <bean id="myCustomAccessDeniedHandler" class="be.mentoringsystems.applicationname.security.CustomAccessDeniedHandler">
        <property name="errorPage" value="/login.html" />
    </bean>
 
</beans>