Spring

Developing a RESTful Web Service Using Spring Boot 1.4

Posted on

spring_mvc_rest

 

 

 

In this article, we will see the full example of developing an application using Spring boot 1.4.3 Release version. Along with MVC RESTFul example to accomplish a CURD operation.

Before we kick off in example details, we would give you some insight about Spring.boot

What is Spring Boot ?

It is a framework for developing a stand-alone application, Its provide defaults for code and annotation configuration that help us to quickly start new Spring project.

Spring Boot is nothing but a top up on existing Spring Framework with embedded Server ( Jetty + Tomcat ). The goal of Spring Boot Framework is to minimize the development and Testing ( JUnit & Integration ) time and provide production ready features like a metrics, health, logs and externalized configuration.

Features

  • Create stand-alone Spring applications
  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
  • Provide opinionated ‘starter’ POMs to simplify your Maven configuration
  • Automatically configure Spring whenever possible
  • Provide production-ready features such as metrics, health checks and externalized configuration
  • Absolutely no code generation and no requirement for XML configuration.

Advantages of Spring Boot:

  • It is very easy to develop Spring Based applications with Java or Groovy.
  • It reduces lots of development time and increases productivity.
  • It avoids writing lots of boilerplate Code, Annotations and XML Configuration.
  • It is very easy to integrate Spring Boot Application with its Spring Ecosystem like Spring JDBC, Spring ORM, Spring Data, Spring Security etc.
  • It follows “Opinionated Defaults Configuration” Approach to reduce Developer effort
  • It provides Embedded HTTP servers like Tomcat, Jetty etc. to develop and test our web applications very easily.
  • It provides CLI (Command Line Interface) tool to develop and test Spring Boot(Java or Groovy) Applications from command prompt very easily and quickly.
  • It provides lots of plugins to develop and test Spring Boot Applications very easily using Build Tools like Maven and Gradle
  • It provides lots of plugins to work with embedded and in-memory Databases very easily.

Let start with Spring Boot Example Step by Step :-

It’s is recommended to start spring.boot application using dependency management system like Maven or Gradle. Here we use Maven to build a Spring Boot application. Below are dependencies in pom.xml which can be created manually or created by SPRING INITIALIZR – recommended to use it to develop a simple Spring Boot Application.

pom.xml


<?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>com.spring.boot.example</groupId>
    <artifactId>Spring_Boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <!--http://start.spring.io/-->
    <name>spring_boot</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Create a RESTFul Controller that handle CURD operation using endpoints. Spring 4.3 introduced new annotations which serve the same purpose as @RequestMapping having predefined ‘method’ (HTTP verb) value. These annotations are actually themselves annotated with @RequestMapping with the related value of ‘method’ element.

Followings are those annotations:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

DevOpsController.java

package com.spring.example.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by MYPC on 1/9/2017.
 */
@RestController
public class DevOpsController {

    @GetMapping
    public ResponseEntity<?> sayHello() {
        return ResponseEntity.status(HttpStatus.OK).body("Welcome to my first Sprint boot example");
    }

    @PutMapping
    public ResponseEntity<?> putMethod(@RequestBody String payload) {
        System.out.println(" Put Method Call :-> Payload " + payload);
        return ResponseEntity.ok("OK");
    }

    @PostMapping
    public ResponseEntity<?> postMethod(@RequestBody String payload) {
        System.out.println(" POST Method Call :-> Payload " + payload);
        return ResponseEntity.ok("OK");
    }

    @DeleteMapping
    public ResponseEntity<?> deleteMethod(@RequestBody String payload) {
        System.out.println(" DELETE Method Call :-> Payload " + payload);
        return ResponseEntity.ok("OK");
    }

    @GetMapping(path = "/list")
    public ResponseEntity<?> getList() {
        List list = new ArrayList<>();
        list.add("One");
        list.add("Two");
        list.add("Three");
        list.add("Four");
        return ResponseEntity.status(HttpStatus.OK).body(list);
    }
}

And Main Application class to start Spring-Boot application along with Server.


package com.spring.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

/**
 * list
 * Created by AJAY KUMAR on 1/9/2017.
 */
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.spring.example.controller")
public class SpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApplication.class, args);
    }
}


 

Run SpringBootApplication.java as normal java program, It will start embedded Tomcat on port no 8080. Below are output’s snapshot.
springboot-rest

Inversion of control and Dependency Injection Patterns

Posted on Updated on

Inversion of control  and Dependency Injection : –

Inversion of control is a generic principle, while Dependency injection realises this principle as design pattern for object graph construction (i.e. configuration controls how the objects are referencing each other, rather than the object itself controlling how to get the reference to another object).

Inversion of Control  implies change the flow of control in the program. In traditional standalone application we have Main method that control the flow to third party libraries ( if third party libraries exist) but through inversion of controls, control gets transferred from third party library code to our code as we are taking the service of third party library

 

Don’t call us, we’ll call you”.

Let have an example here:-  

When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

Some Key Points about IOC :- 

  • It’s about getting freedom ( no dependencies at all )
  • Loose coupling – decouple
  • high cohensive
  • easy to test and mock the real object as well
  • reuseabilty

The Dependency Inversion Principle (DIP) states that higher level classes and lower level class does’t interact directly but instead it’s working on some abstraction modules where both classes get the flexibility of increasing the functionalities.

– High level modules should not depend upon low level modules. Both should depend upon abstractions.
– Abstractions should not depend upon details. Details should depend upon abstractions.

 

Injecting a prototype/Session bean into a singleton bean

Posted on Updated on

spring-logo

 

 

 

In Spring, most of the beans we work with are Singletons. If a singleton bean is wired with yet another singleton bean, there is absolutely no problem. But if it is wired with a bean which is of different scope, say prototype, how does it work? Here is the example:
RequestProcessor.Java


public class RequestProcessor {

    private RequestValidator validator;

    public void handleRequest(String requestId){
        validator.validate(requestId);
        // Process the request and update
    }

    public RequestValidator getValidator() {
        return validator;
    }

    public void setValidator(RequestValidator validator) {
        this.validator= validator;
    }

}

RequestValidator.Java


public class RequestValidator {

    private List errorMessages = new ArrayList();

    public RequestValidator() {
        System.out.println("Validator instance created!");
    }

    // Validates the request and populates error messages
    public void validate(String requestId){

    }

    public List getErrorMessages() {
        return errorMessages;
    }

}

And here is the spring configuration:


<bean id="requestProcessor" class="com.pramati.spring.RequestProcessor">
<property name="validator" ref="validator"/>
</bean>

<bean id="validator" scope="prototype" class="com.pramati.spring.RequestValidator"/>

With this configuration, it is expected that when ever I fetch requestProcessor from application context, it will be wired with a new validator as we declared the validator bean is of prototype scope. But this does not happen.
When the application context gets initialized, it sees that requestProcessor is a singleton bean and initializes it to the context after wiring it with all the dependencies set. So from then onwards when we request context for requestProcessor, it return the same bean every time. To solve this issue, we have 2 approaches:

1.Lookup Method injection: For this, we have to declare the beans as follows:


<bean id="requestProcessor" class="com.pramati.spring.RequestProcessor">
 <lookup-method name="getValidator" bean="validator"/>
</bean>

<bean id="validator" scope="prototype" class="com.pramati.spring.RequestValidator"/>

The Spring Framework implements method injection by using CGLIB library to generate dynamically a subclass that overrides the method. So for the method to be overridden, we have to define that method in the class and either provide a dummy implementation for it or make it abstract. Making a method abstract implies that class also has to be made abstract which will make it difficult to unit test. So providing a dummy implementation is a better choice.
Whenever we define a bean with lookup methods, Spring creates a subclass of the bean and overrides those methods which are marked as lookup-methods. And this subclassed bean gets registered into the context. The subclass delegates all the non-lookup methods to the original class. For the lookup methods, it overrides the implementation. So in our example, when getValidator() is called, it returns a new validator instance.
We can roughly imagine our new subclass(registered in container) like this:


requestProcessor = new RequestProcessor(){
    public RequestValidator getValidator(){
        return context.getBean("validator");
    }
};

We could have directly fetched the bean from application context in RequestProcessor itself. But this would mean that the class is directly coupled to Spring framework. To do this in a cleaner way, we can use lookup injection. This puts all the spring related stuff at one place.

2. Scoped Proxies: This can be implemented as:


<bean id="requestProcessor" class="com.pramati.spring.RequestProcessor">
<property name="validator" ref="validator"/>
</bean>

<bean id="validator" scope="prototype" class="com.pramati.spring.RequestValidator">
<!-- This instructs the container to proxy the current bean-->
<aop:scoped-proxy/>
</bean>

Remember, in the case of look up method injection, proxy is created for singleton bean. But in case of scoped proxies, proxy is created for prototype bean and wired into the singleton bean during the process of registering the singleton bean in the context. The proxy thus created understands the scope and returns instances based on the requirements of the scope. So in our case, requestProcessor holds a reference to proxy in place of validator.
And in case of lookup method injection, when requestProcessor gets loaded into the context, validator will not be initialized at all. And when we call the look up method, it returns the prototype bean. But instead of calling the method, if you try to directly access the prototype bean(assuming it is accessible), it gives a Nullpointer Exception as it didn’t get initialized(We are not wiring it using property tag of bean)
In case of this, we can also configure how a proxy can be created. It can be done in 2 ways:-

  1. CGLIB library which directly subclasses the object. This is the default option of Spring. For this, we must have CGLIB library our class path.
  2. Java Dynamic Proxies. For this to be activated, we have to call:

<aop:scoped-proxy proxy-target-class="false"/>

Here in this case, we don’t need any additional libraries in our class path. But the scoped bean must implement at least one interface and it has to be referred through the same interface at all places in order to get itself wired.

Few points to note:
1. Both method injection and scoped proxies work not only for prototype beans. This works more generic. Whenever a bean of different scope is injected into a singleton bean, we can use any of these techniques to ensure that we get a corresponding scope object.
2. Note that in the proxy, the method returning the prototype bean is overridden to return a new instance for every single call.
Suppose we want to display the error messages that we have got after validation:


requestProcessor.getValidator().validate();
for(String message: requestProcessor.getValidator().getErrorMessages()){
logger.log(LogLevel.ERROR, message);
}

This code seems to print the error messages we have got after validation process. But this will never print any error messages even if there are many validation failures. This happens because requestProcessor.getValidator() returns a new validator instance every time it is called. So for this to work, the code has to be modified as:


RequestValidator validator = requestProcessor.getValidator();
validator.validate();
for(String message: validator.getErrorMessages()){
logger.log(LogLevel.ERROR, message);
}

This happens only in case of prototype beans but works perfectly in case of other non-singleton scopes(request, session, global-session).

The singleton scope
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.

The session scope
With the above bean definition in place, the Spring container will create a brand new instance of the bean , for the lifetime of a single HTTP Session.
According to Spring framework reference, a different approach needs to be followed in cases where a class which “lives longer”(singleton bean in this case) needs to be injected with another class having a comparatively shorter life-span(session-scoped bean). The approach is different for prototype & singleton scope though.
In your XML, what we want is that the singletonBean instance should be instantiated only once, and it should be injected with sessionBean. But since sessionBean is session-scoped(which means it should be re-instantiated for every session), the configuration is ambiguous(as the dependencies are set at instantiation time and the session scoped value can change later also).
So instead of injecting with that class, it’s injected with a proxy that exposes the exact same public interface as sessionBean. The container injects this proxy object into the singletonBean bean, which is unaware that this sessionBean reference is a proxy. It’s specified by writing this tag in the sessionBean:


<aop:scoped-proxy/>

XML Configuration:


<bean name="singletonBean" class="somepkg.SingletonBean">
<property name="someProperty" ref="sessionBean"/>
</bean>

<bean name="sessionBean" class="somepkg.SessionBean" scope="session">
<aop:scoped-proxy/>
</bean>

When a singletonBean instance invokes a method on the dependency-injected sessionBean object, it actually is invoking a method on the proxy. The proxy then fetches the real sessionBean object from (in this case) the HTTP Session, and delegates the method invocation onto the retrieved real sessionBean object.

Singleton beans with prototype-bean dependencies

Lookup Method Injection

When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.
However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.


<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
<!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="command"/>
</bean>

Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. The lookup typically involves a prototype bean as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to generate dynamically a subclass that overrides the method.

This Topic is copied from this site.

Spring4 + Hibernate 4 + JSON Example with XML Configuration

Posted on Updated on

spring_mvc_rest

 

 

 

 

 

In this article, we will show you how to produce JSON as a Http response.

Technologies used:

  1. JDK 1.6
  2. Spring 4.0.3.RELEASE
  3. Hibernate 4.3.4.Final
  4. Jackson 2.4.1
  5. Eclipse 3.6
  6. Maven 3

Project hierarchy in Eclipse :-

Spring4HibernateJSONExample-project-hierarchy

 

 

 

 

 

 

 

 

 

 

 

 

Following REST Services to be Exposed:-

REST service URI Methods Parameter Description
/API/enquiry GET None Fetch out all record of enquiry
/API/enquiry/{enquiry_id} GET enquiry_id Fetch out a specified record of enquiry Table base on {enquiry_id}
/API/enquiry POST Send Enquiry Object in JSON format Add a record
/API/enquiry/{enquiry_id} DELETE enquiry_id Delete a specified record from Enquiry Table.
/API/enquiry PUT Send Enquiry Object in JSON format Update existing record

pom.xml :-


<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/maven-v4_0_0.xsd">

<groupId>com.spring.itexpert</groupId>
<modelVersion>4.0.0</modelVersion>
<artifactId>Spring4HibernateJSONExample</artifactId>
<name>Spring4HibernateJSONExample</name>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<description>
Root Project For Spring + Hibernate + JSON Application
</description>
<properties>

<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<cglib.version>2.2.2</cglib.version>
<!-- Spring -->
<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
<hibernate.version>4.3.4.Final</hibernate.version>

<jackson-version>2.4.1</jackson-version>
</properties>

<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring JDBC Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring core & mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- CGLib for @Configuration -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Servlet API Support -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warSourceDirectory>src/main/web</warSourceDirectory>
<warName>Spring4HibernateJSONExample</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>

<finalName>Spring4HibernateJSONExample</finalName>
</build>
</project>

Spring-servlet.xml:-


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">

<context:annotation-config />
<mvc:annotation-driven />
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.databaseurl}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>

<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:component-scan base-package="com.spring.itexpert" />

</beans>

web.xml


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">

<display-name>Web Application</display-name>
<welcome-file-list>
<welcome-file>/WEB-INF/jsp/index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>

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>
<mapping class="com.spring.itexpert.hibernate.model.Enquiry" />
</session-factory>
</hibernate-configuration>

jdbc.properties:-


jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=jdbc:mysql://localhost:3306/myDB
jdbc.username=root
jdbc.password=root

EnquiryController.Java  :


package com.spring.itexpert.controller;

import java.security.Principal;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.spring.itexpert.dao.EnquiryRepository;
import com.spring.itexpert.hibernate.model.Enquiry;


@Controller
@RequestMapping("/API/enquiry")
public class EnquiryController {

	@Autowired
	private EnquiryRepository enquiryRepository;
	
	@ResponseBody
	@ResponseStatus(value=HttpStatus.OK)
	@RequestMapping(method=RequestMethod.GET)
	public List getListOfEnquiry(){
		List enquiries = enquiryRepository.getListOfEnquriry();
		return enquiries;
	}
	
	@ResponseBody
	@ResponseStatus(value=HttpStatus.OK)
	@RequestMapping(value="/{enquiry_id}",method=RequestMethod.GET)
	public Enquiry getEnquiry(@PathVariable("enquiry_id") Long enquiry_id){
		System.out.println(enquiry_id);
		return enquiryRepository.getEnquiry(enquiry_id) ;
	}
	
	
	@ResponseBody
	@ResponseStatus(value=HttpStatus.OK)
	@RequestMapping(method=RequestMethod.POST)
	public void getSaveEnquiry(Principal principal, @RequestBody Enquiry e){
		enquiryRepository.save(e);;
	}
	
	@ResponseBody
	@ResponseStatus(value=HttpStatus.OK)
	@RequestMapping(value="/{enquiry_id}",method=RequestMethod.DELETE)
	public  void deleteEnquiry(@PathVariable("enquiry_id") Long enquiry_id, Principal principal){
		enquiryRepository.delete(enquiry_id);
	}
	
	@ResponseStatus(value=HttpStatus.OK)
	@RequestMapping(method=RequestMethod.PUT)
	public void editEnquiry(@RequestBody Enquiry e,Principal principal){
		System.out.println(e);
		enquiryRepository.update(e);
	}
		
}


EnquiryRepository.Java


package com.spring.itexpert.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.spring.itexpert.hibernate.model.Enquiry;


@Repository
@Transactional
public class EnquiryRepository {

	@Autowired
	private SessionFactory sessionFactory;

	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	public List getListOfEnquriry() {
		List list = getSession().createCriteria(Enquiry.class).list();
		return list;
	}
	public List getListOfEnquriry(Integer maxPageSize,Integer maxRecord) {
		List list = getSession().createCriteria(Enquiry.class)
				.setMaxResults(maxRecord)
				.setFirstResult(maxPageSize)
				.list();
		return list;
	}
	
	public void update(Enquiry e){
		getSession().merge(e);
	}
	
	public void save(Enquiry e){
		getSession().merge(e);
	}
	
	public void delete(Long enquiry_id){
		Enquiry e = (Enquiry)getSession().get(Enquiry.class, enquiry_id);
		getSession().delete(e);
		
	}
	
	public Enquiry getEnquiry(long id){
		Enquiry e = (Enquiry)getSession().get(Enquiry.class, id);
		System.out.println(e.toString());
		return e != null? e:new Enquiry();
	}
	
}


Enquiry.Java


package com.spring.itexpert.hibernate.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Type;

@Entity
@Table(name = "enquiry")
public class Enquiry {

	@Id
	@GeneratedValue
	private long id;
	private String name;
	private String course;
	private String status;
	private String preferences;
	private String location;
	private String place;
	private String remarks;
	private String email;

	private String source;
	private String mobile;
	@Column
	@Temporal(TemporalType.TIMESTAMP)
	@Type(type="timestamp")
	private Date enquiry_date;
	
	@Column
	@Temporal(TemporalType.TIMESTAMP)
	@Type(type="timestamp")
	private Date updated_date;
	
	
	public Enquiry(){}
	
	public Enquiry(String studentname, String course, String status,
			String preference, String remarks, String email, String source,
			String mobile,Date enquiry_date) {
		this.name = studentname;
		this.course = course;
		this.status = status;
		this.preferences = preference;
		this.remarks = remarks;
		this.email = email;
		this.source = source;
		this.mobile = mobile;
		this.enquiry_date = enquiry_date;
	}

	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setStudentname(String studentname) {
		this.name = studentname;
	}
	public String getCourse() {
		return course;
	}
	public void setCourse(String course) {
		this.course = course;
	}
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}
	public String getPreferences() {
		return preferences;
	}
	public void setPreference(String preference) {
		this.preferences = preference;
	}
	public String getRemarks() {
		return remarks;
	}
	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getSource() {
		return source;
	}
	public void setSource(String source) {
		this.source = source;
	}
	public String getMobile() {
		return mobile;
	}
	public void setMobile(String mobile) {
		this.mobile = mobile;
	}

	

	public Date getEnquiry_date() {
		return enquiry_date;
	}

	public void setEnquiry_date(Date enquiry_date) {
		this.enquiry_date = enquiry_date;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setPreferences(String preferences) {
		this.preferences = preferences;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	public String getPlace() {
		return place;
	}

	public void setPlace(String place) {
		this.place = place;
	}

	public Date getUpdated_date() {
		return updated_date;
	}

	public void setUpdated_date(Date updated_date) {
		this.updated_date = updated_date;
	}

	@Override
	public String toString() {
		return String
				.format("Enquiry [id=%s, name=%s, course=%s, status=%s, preferences=%s, location=%s, place=%s, remarks=%s, email=%s, source=%s, mobile=%s, enquiry_date=%s, updated_date=%s]",
						id, name, course, status, preferences, location, place,
						remarks, email, source, mobile, enquiry_date,
						updated_date);
	}

	
}


Spring MVC + JSON = 406 Not Acceptable + characteristics not acceptable according to the request “accept” headers ()

Posted on Updated on

This is the  very common mistake that typically happened during the configuration Spring + JSON. Recently we faced such issues with Spring 4 + Hibernate configuration so by digging some blogs and own effort make this issues fixed.

below are some steps that need to be changed in configuration file so we can get rid of “Response Error 406 :-characteristics not acceptable according to the request “accept” headers ()

Get rid of this issues by adding **@EnableWebMvc** in Controller class.

@Controller
@RequestMapping("/API/course")
@EnableWebMvc
public class CourseController {
@Autowired
private com.item.DAO.CourseRepository courseRepository;

@ResponseStatus(value=HttpStatus.OK)
@RequestMapping(method=RequestMethod.GET)
public @ResponseBody List<Course> getListOfCourse(){
List<Course> courses = courseRepository.getListOfCourse();
return courses ;
}

or add following lines in xml configuration file if XML configuration is being used in your project.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven />
<bean>

and add following dependencies in your pom.xml file:-


<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.1</version>
</dependency>

See complate example here.

We hope this will help you out, Thanks !!

Spring Security Custom FilterChainProxy using Java Annotation Configuration

Posted on Updated on

Spring 3

Hi Friends, Today we came with some interesting topics about Spring Security custom filterChainProxy with Java annotation configuration. As most of you know that after spring 4.0.X, we could do Spring configuration with annotation no more usages of XML configuration.

As my last project work, I wanted to use Java annotation configuration that completely relied on annotation so I started reading blogs and Spring official documentation then now I am able to make it possible using Annotation Configuration.

Here, below snippet code example I also provided XML configuration which is a mirror of Annotations base Configuration file. In this snippet code example, three login windows are required for USER, RECRUITER and ADMIN login so accordingly it is configured.

Custom Implemented Classes:-

  • LoginSuccessDispatcherHandler : – This class dispatch the page after successful authentication to target page i.e if LoginType is ROLE_USER then redirect to user dashboard or if LoginType is ROLE_RECRUITE then redirect to recruiter dashboard or  if LoginType is ROLE_ADMIN then redirect to admin dashboard.
  • UserAuthenticationProvider :- This class implemented from AbstractUserDetailsAuthenticationProvider  that validate token and return a valid User Object.

Annotation base configuration here:-


package com.itexperts.spring.config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

import javax.servlet.ServletException;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.intercept.RunAsManager;
import org.springframework.security.access.intercept.RunAsManagerImpl;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.ReflectionSaltSource;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import com.itexperts.spring.bean.UserAuth;
import com.itexperts.spring.security.LoginSuccessDispatcherHandler;
import com.itexperts.spring.security.UserAuthenticationProvider;

@Configuration
@EnableWebSecurity
public class AppSecurityConfig  {

	@Bean
	public AuthenticationManager getAuthenticationManager() {
		AuthenticationManager authenticationManager = new ProviderManager(
				Arrays.asList(getAuthenticationProvider()));
		return authenticationManager;
	}

	@Bean
	public AuthenticationProvider getAuthenticationProvider() {
		UserAuthenticationProvider userAuthenticationProvider = new UserAuthenticationProvider();
		return userAuthenticationProvider;
	}
	
	@Bean
    public SaltSource saltSource() throws Exception {
        ReflectionSaltSource saltSource = new ReflectionSaltSource();
        saltSource.setUserPropertyToUse("salt");
    saltSource.afterPropertiesSet();
    return saltSource;
}

@Bean(name="springSecurityFilterChain")
public FilterChainProxy getFilterChainProxy() throws ServletException, Exception {
	List listOfFilterChains = new ArrayList();
	listOfFilterChains.add(new DefaultSecurityFilterChain(
			new AntPathRequestMatcher("/home**")));
	listOfFilterChains.add(new DefaultSecurityFilterChain(
			new AntPathRequestMatcher("/resources/**")));
	listOfFilterChains.add(new DefaultSecurityFilterChain(
			new AntPathRequestMatcher("/**"),
			securityContextPersistenceFilter(), logoutFilter(),
			usernamePasswordAuthenticationFilter(),
			exceptionTranslationFilter(), filterSecurityInterceptor()));
	return new FilterChainProxy(listOfFilterChains);
}

@Bean
public SecurityContextPersistenceFilter securityContextPersistenceFilter() {
	return new SecurityContextPersistenceFilter(
			new HttpSessionSecurityContextRepository());
}

@Bean
public ExceptionTranslationFilter exceptionTranslationFilter() {
	ExceptionTranslationFilter exceptionTranslationFilter = new ExceptionTranslationFilter(
			new LoginUrlAuthenticationEntryPoint("/home"));
	AccessDeniedHandlerImpl accessDeniedHandlerImpl = new AccessDeniedHandlerImpl();
	accessDeniedHandlerImpl.setErrorPage("/exception");
	exceptionTranslationFilter
			.setAccessDeniedHandler(accessDeniedHandlerImpl);
	exceptionTranslationFilter.afterPropertiesSet();
	return exceptionTranslationFilter;
}


@Bean
public AbstractAuthenticationProcessingFilter usernamePasswordAuthenticationFilter()
		throws Exception {
	AbstractAuthenticationProcessingFilter usernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilter();
	usernamePasswordAuthenticationFilter
			.setAuthenticationManager(getAuthenticationManager());
	// super(new AntPathRequestMatcher("/login", "POST"));->
	//usernamePasswordAuthenticationFilter.setFilterProcessesUrl("/login");
	usernamePasswordAuthenticationFilter.setAllowSessionCreation(true);

	AuthenticationSuccessHandler successHandler = new LoginSuccessDispatcherHandler();
	usernamePasswordAuthenticationFilter
			.setAuthenticationSuccessHandler(successHandler);
	usernamePasswordAuthenticationFilter
			.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler(
					"/home?error=true"));
	usernamePasswordAuthenticationFilter.afterPropertiesSet();

	return usernamePasswordAuthenticationFilter;

}

@Bean
public LogoutFilter logoutFilter() throws ServletException {
	List handlers = new ArrayList();
	handlers.add(new CookieClearingLogoutHandler("JSESSIONID"));
	handlers.add(new SecurityContextLogoutHandler());
	LogoutFilter logoutFilter = new LogoutFilter("/logout",
			handlers.toArray(new LogoutHandler[] {}));
	logoutFilter.afterPropertiesSet();
	return logoutFilter;
}

 @Bean
 public FilterSecurityInterceptor filterSecurityInterceptor()
            throws Exception {
        FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
        filterSecurityInterceptor
                .setAuthenticationManager(getAuthenticationManager());
        filterSecurityInterceptor
                .setAccessDecisionManager(accessDecisionManager());
        filterSecurityInterceptor.setRunAsManager(runAsManager());
        LinkedHashMap<RequestMatcher, Collection> requestMap = new LinkedHashMap<RequestMatcher, Collection>();
      
        requestMap.put(new AntPathRequestMatcher("/user/**"), 
        		SecurityConfig.createList("hasRole('"+UserAuth.ROLE_CANDIDATE.name()+"')"));
        requestMap.put(new AntPathRequestMatcher("/recruiter/**"), 
        		SecurityConfig.createList("hasRole('"+UserAuth.ROLE_RECRUITER.name()+"')"));
        requestMap.put(new AntPathRequestMatcher("/admin/**"), 
        		SecurityConfig.createList("hasRole('"+UserAuth.ROLE_ADMIN.name()+"')"));
        FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource = new ExpressionBasedFilterInvocationSecurityMetadataSource(
                requestMap, new DefaultWebSecurityExpressionHandler());
        filterSecurityInterceptor
                .setSecurityMetadataSource(filterInvocationSecurityMetadataSource);
        filterSecurityInterceptor.afterPropertiesSet();

        return filterSecurityInterceptor;
    }
 
 public AffirmativeBased accessDecisionManager() throws Exception {
        List<AccessDecisionVoter<? extends Object>> voters = new ArrayList<AccessDecisionVoter<? extends Object>>();
        voters.add(new WebExpressionVoter());
        RoleVoter voter = new RoleVoter();
        voter.setRolePrefix("ROLE_");
        voters.add(voter);
        voters.add(new AuthenticatedVoter());
        AffirmativeBased affirmativeBased = new AffirmativeBased(voters);
        affirmativeBased.setAllowIfAllAbstainDecisions(false);
        affirmativeBased.afterPropertiesSet();

        return affirmativeBased;
    }

    @Bean
    public RunAsManager runAsManager() throws Exception {
        RunAsManagerImpl runAsManager = new RunAsManagerImpl();
        runAsManager.setKey("ROLE_ADMIN");
	        runAsManager.afterPropertiesSet();
	        return runAsManager;
	    }
}

XML configuration here :-


<?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.1.xsd">

 <alias name="filterChainProxy" alias="springSecurityFilterChain"/>
 
 <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
 
 <security:filter-chain-map path-type="ant">
 
 
 <security:filter-chain pattern="/home/**" filters="none" />
 <security:filter-chain pattern="/resources/**" filters="none" />
 
 <security:filter-chain pattern="/**" filters="concurrentSessionFilter,securityContextPersistenceFilter,logoutFilter,authenticationFilter,sessionManagementFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
 </security:filter-chain-map>
 </bean>
 
 <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
 <property name="providers">
 <list>
 <ref local="userAuthenticationProvider" />
 </list>
 </property>
 </bean>
 
 <bean id="userAuthenticationProvider" class="com.itexperts.spring.security.UserAuthenticationProvider">
 </bean>

 <bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
 <property name="securityContextRepository" ref="securityContextRepository" />
 </bean>
 
 <bean id="securityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />

 <bean id="concurrentSessionFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
 <property name="expiredUrl" value="/home?errorCode=24" />
 <property name="sessionRegistry" ref="sessionRegistry" />
 </bean>

 

 <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
 
 <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
 <constructor-arg value="/logout" />
 <!-- URL redirected to after logout -->
 <constructor-arg>
 <list>
 <bean
 class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
 </bean>
 </list>
 </constructor-arg>
 </bean>

 <bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
 <property name="authenticationManager" ref="authenticationManager" />
 <!--<property name="filterProcessesUrl" value="/login" />-->
 <property name="authenticationFailureHandler" ref="authenticationFailureHandler"/>
 <property name="authenticationSuccessHandler" ref="authenticationSuccessHandler"/>
 <property name="sessionAuthenticationStrategy" ref="sas" />
 </bean>

 <bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
 <property name="authenticationEntryPoint" ref="authenticationEntryPoint" />
 </bean>

 
 <bean id="authenticationEntryPoint" class="com.search.job.authentication.manager.AjaxAwareAuthenticationEntryPoint">
 <property name="loginFormUrl" value="/home" />
 </bean>
 
 <bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
 <property name="errorPage" value="/exception" />
 </bean>

 <bean id="authenticationSuccessHandler" class="com.itexperts.spring.security.LoginSuccessDispatcherHandler">
 </bean>

 <bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
 <constructor-arg name="sessionRegistry" ref="sessionRegistry" />
 <property name="maximumSessions" value="1" />
 </bean>
 

 <bean id="filterSecurityInterceptor"
 class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
 <property name="authenticationManager">
 <ref bean="authenticationManager" />
 </property>
 <property name="accessDecisionManager">
 <bean class="org.springframework.security.access.vote.AffirmativeBased">
 <property name="decisionVoters">
 <list>
 <bean class="org.springframework.security.access.vote.RoleVoter">
 <property name="rolePrefix" value="ROLE_" />
 </bean>
 <bean
 class="org.springframework.security.access.vote.AuthenticatedVoter">
 </bean>

 </list>
 </property>
 </bean>
 </property>
 <property name="securityMetadataSource">
 <security:filter-security-metadata-source>
 <security:intercept-url pattern="/profile/**" access="ROLE_CANDIADTE"></security:intercept-url>
 <security:intercept-url pattern="/recruiter/**" access="ROLE_RECRUITER"></security:intercept-url>
 <security:intercept-url pattern="/admin/**" access="ROLE_ADMIN"></security:intercept-url>
 </security:filter-security-metadata-source>
 </property>
 </bean>
 
 <bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
 <constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
 <property name="sessionAuthenticationStrategy" ref="sas" />
 </bean>
 <bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/> 
</beans>


Finally, we need to register all Servlets and Filter and other in web.xml, Since we are using Annotation base configuration so that we do it following way:-


package com.itexperts.spring.dispatcher;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.itexperts.spring.config.AppConfig;
import com.itexperts.spring.config.AppSecurityConfig;
import com.itexperts.spring.config.ServletContextConfig;

public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		
		return new Class[]{AppConfig.class,AppSecurityConfig.class};
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class[]{ServletContextConfig.class};
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
	
	@Override
    public void onStartup(ServletContext servletContext) 
            throws ServletException {
        servletContext
            .addFilter("springSecurityFilterChain", 
                       new DelegatingFilterProxy("springSecurityFilterChain"))
            .addMappingForUrlPatterns(null, false, "/*");

        super.onStartup(servletContext);
    }

}

LoginSuccessDispatcherHandler.Java


package com.itexperts.spring.security;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import com.itexperts.spring.bean.UserAuth;

public class LoginSuccessDispatcherHandler implements
		AuthenticationSuccessHandler {

	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException {
		handle(request, response, authentication);
		clearAuthenticationAttributes(request);
	}

	protected void handle(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException {
		String targetUrl = determineTargetUrl(authentication);

		if (response.isCommitted()) {
			return;
		}

		redirectStrategy.sendRedirect(request, response, targetUrl);
	}

	protected String determineTargetUrl(Authentication authentication) {

		Collection<? extends GrantedAuthority> authorities = authentication
				.getAuthorities();
		String targetURL = "";
		for (GrantedAuthority auth : authorities) {
			if (auth.getAuthority().equals(UserAuth.ROLE_CANDIDATE.name())) {
				targetURL = "/user/candidate";
				break;
			} else if (auth.getAuthority().equals(
					UserAuth.ROLE_RECRUITER.name())) {
				targetURL = "/recruiter";
				break;
			} else if (auth.getAuthority().equals(UserAuth.ROLE_ADMIN.name())) {
				targetURL = "/admin";
				break;
			} else {
				break;
			}
		}
		if ("".equals(targetURL)) {
			throw new IllegalStateException();
		}
		return targetURL;

	}

	protected void clearAuthenticationAttributes(HttpServletRequest request) {
		HttpSession session = request.getSession(false);
		if (session == null) {
			return;
		}
		session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
	}

	public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
		this.redirectStrategy = redirectStrategy;
	}

	protected RedirectStrategy getRedirectStrategy() {
		return redirectStrategy;
	}

}


UserAuthenticationProvider.Java


package com.itexperts.spring.security;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;

import com.itexperts.spring.bean.LoginModel;
import com.itexperts.spring.repo.UserRepository;

public class UserAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

	@Autowired
	private UserRepository userRepository;
	
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken token)
			throws AuthenticationException {
	}

	@Override
	protected UserDetails retrieveUser(String str,
			UsernamePasswordAuthenticationToken token)
			throws AuthenticationException {
		LoginModel loginModel = userRepository.login(token.getPrincipal(),token.getCredentials());
		if( loginModel == null ){
			throw new BadCredentialsException("Invalid Username and Password");
		}
		Collection grantedAuthorities = new ArrayList();
		GrantedAuthority roleType = new SimpleGrantedAuthority(loginModel.getUsertype());
		grantedAuthorities.add(roleType);
		return new User(loginModel.getUsername(), loginModel.getPassword(),true, true, true, true, grantedAuthorities);
	}

}


How to develop multi modules Project in Maven

Posted on Updated on

maven

 

 

A multi modules project consists a set of modules where each module works / configures as a project to logical group of sub-project that work together to build a complete project. As usually a large or complex project containing multiple modules in which individual or a team work together to accomplish the goal of software development.

Typically, a root or parent pom.xml file to be configured all sub-modules in such a way that during the maven build, it provide a complete packaging (JAR,WAR,EAR) in target folder even if it could be packaged in form of ZIP or GZIP format in your target folder. During this section we will demonstrate how to configure it.

There are many way to configure maven project either using IDE or manually but we did it manually by creating project folder then set-up pom.xml file inside build folder and other related sub-modules inside project folder, finally import it with IDE ( Eclipse ) by maven project.

In this section, we created three sub-modules project receptively :-

  • interface :  interface module contain resource bundles and web folder ( ideally it represent a web project containing all jsp/html/js/xml as well as web.xml file)
  • web :  web module contain all action file, helper  and resources bundles.
  • service :  Service module contain all business logic including DAO, Bean, Service and Component class and their implementation.

build :  This folder contains only parent pom.xml, in order to build project navigate inside this folder using command and then run following command:-

  • mvn eclipse:clean eclipse:eclipse” ( generate classpath with all dependencies )
  • followed by “mvn clean install” ( clean target folder and compile, build and packaging project in form of JAR,WAR or EAR )

Maven Project hierarchy in Eclipse maven import:-

 

 

 

 

 

 

Project hierarchy in Eclipse :-

pom-project-h2

 

Parent root pom.xml under build folder:-

<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/maven-v4_0_0.xsd">

<groupId>com.search.job</groupId>
<artifactId>build</artifactId>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<name>Build</name>
<version>1.0-SNAPSHOT</version>
<description>
Root Project For Search Job
</description>

<!--Core Modules-->
<modules>
<module>../service</module>
<module>../web</module>
<module>../interface</module>
</modules>


<!-- Build Configration Settings -->
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>

<properties>
<version.activiti>5.14</version.activiti>

<version.commons-io>1.3.2</version.commons-io>
<version.commons.configuration>1.6</version.commons.configuration>
 ....
 ....
</properties>
</project>

Service Pom.xml file :-


<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/maven-v4_0_0.xsd">
 <parent>
 <artifactId>build</artifactId>
 <groupId>com.search.job</groupId>
 <version>1.0-SNAPSHOT</version>
 <relativePath>../build/pom.xml</relativePath>
 </parent>
 <modelVersion>4.0.0</modelVersion>
 <artifactId>service</artifactId>
 <name>service</name>
 <packaging>jar</packaging>
 <dependencies>
  <!-- maven dependencies -->
 <dependency>
  
</dependency>

 </dependencies>
</project>

Web Project pom.xml:


<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/maven-v4_0_0.xsd">
<parent>
<artifactId>build</artifactId>
<groupId>com.search.job</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../build/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>web</artifactId>
<name>web</name>
<packaging>jar</packaging>
<dependencies>
 <!-- maven dependencies -->
<dependency>

</dependency>
</dependencies>
</project>

Interface Project pom.xml

 

<?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/maven-v4_0_0.xsd">

<parent>
<artifactId>build</artifactId>
<groupId>com.search.job</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../build/pom.xml</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>
<artifactId>interface</artifactId>
<name>Search Job INterface</name>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<dependencies>

 <!-- maven dependencies -->
<dependency>

</dependency>

</dependencies>

<build>
<!-- Final package (JAR,WAR,EAR ) name to be SearchJob -->
<finalName>SearchJob</finalName>
</build>
</project>