Archive

Archive for the ‘Spring’ Category

Spring 4 Web Starter Project

January 6th, 2014 No comments

In this blog post, I will share a Spring 4 based starter project that can be used to jump start Spring based web development. The complete project is available on GitHub at: spring4-web

This starter project has the following features:

  • Completely updated to use Spring 4.0 and Servlet 3.0. You will need containers such as Tomcat 7 to use this project.
  • Fully working pom.xml file with all the required dependencies
  • Working configuration with a sample controller
  • A “catch all” global exception handler using @ControllerAdvice
  • Support for message resources
  • A sample Spring configuration file for middle tier (service/repository layers)
  • SLF4J and Logback for logging
  • Spring BOM file included in the pom so that correct versions of Spring projects are bundled

If you have generated Spring Web projects using my archetype, you will notice that this starter project is not vastly different. Here are few changes/best practices I am following this time:

  1. The config files no longer contain XSD version. So instead of using http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.0.xsd in the configuration files, I will be using http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  2. All the JSP pages are now moved to WEB-INF/views folder. Using Spring’s , I have eleminated the need to have a starter .jsp or html page under the project root.
  3. All the Spring configuration files are now located under src/main/resources/spring folder.

If you get the project running successfully, you should see a page similar to this:
Spring 4 Web Starter Project - 1

If there is an error in the application, you will see the exception page with a correlation id. I am using Apache Commons Lang’s RandomStringUtils to generate correlation ids.
Spring 4 Web Starter Project - 2

I will be using this starter project in my future blogs to demo some of Spring 4’s new features. Give this a try and let me know what you think.

Categories: Solutions Log, Spring Tags: ,

Spring MVC – Sitemesh 3 Integration

October 9th, 2012 4 comments

Sitemesh is a web page layout/decoration framework that makes it easy to create applications with consistent layout/look and feel. I have used Sitemesh 2 for years and absolutely love it. Sitemesh 3 is a complete rewrite of the framework and has huge performance benefits. A full list of the new features is listed here. In this blog I will share the steps needed for integrating Sitemesh 3 in a Spring MVC application.

1. We start by creating a Maven based web application using my Spring archetype. Here is the generated pom.xml file with dependencies:


<?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">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.inflinx.blog</groupId>
	<artifactId>sitemesh3</artifactId>
	<name>sitemesh3</name>
	<packaging>war</packaging>
	<version>1.0.0</version>
	
	<properties>
		<org.springframework-version>3.1.1.RELEASE</org.springframework-version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			 <exclusions>
		         <exclusion>
		            <groupId>commons-logging</groupId>
		            <artifactId>commons-logging</artifactId>
		         </exclusion>
      		</exclusions>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		
		<dependency>
		     <groupId>cglib</groupId>
		     <artifactId>cglib</artifactId>
		     <version>2.2.2</version>
		     <scope>compile</scope>
		</dependency>
		
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
		
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.0.0.GA</version>
			<scope>compile</scope>
		</dependency>
		
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>4.2.0.Final</version>
			<scope>compile</scope>
			<exclusions>
				<exclusion>
					<artifactId>slf4j-api</artifactId>
					<groupId>org.slf4j</groupId>
				</exclusion>
			</exclusions>
		</dependency>
	            
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<dependency>
      		<groupId>org.slf4j</groupId>
	      	<artifactId>jcl-over-slf4j</artifactId>
	      	<version>1.5.8</version>
  	 	</dependency>
   		<dependency>
      		<groupId>org.slf4j</groupId>
      		<artifactId>slf4j-api</artifactId>
      		<version>1.5.8</version>
   		</dependency>
	   <dependency>
	      <groupId>org.slf4j</groupId>
	      <artifactId>slf4j-log4j12</artifactId>
	      <version>1.5.8</version>
	   </dependency>
	
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>
			  
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>            
		
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.0</version>
	    	<scope>provided</scope>
		</dependency>				
 
	</dependencies>
    <build>
        <plugins>
        	<plugin>
			    <groupId>org.mortbay.jetty</groupId>
			    <artifactId>maven-jetty-plugin</artifactId>
			</plugin>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


2. To the web application we add the following Sitemesh 3 maven dependency:

	
		<dependency>
			<groupId>org.sitemesh</groupId>
			<artifactId>sitemesh</artifactId>
			<version>3.0-alpha-2</version>	
		</dependency>
	
	

3. We then create a Sitemesh decorator containing common layout/look and feel that all the pages should have. Create a main.jsp file under WEB-INF/decorator folder with the following contents:


<html>
  <head>
    <title><sitemesh:write property='title'/></title>
    <sitemesh:write property='head'/>
  </head>
  
  <body>
    <div style="color: red">
    	<sitemesh:write property='body'/>
    </div>
  </body>
  
</html> 

4. The next step is to let Sitemesh know about this decorator. This is done via sitemesh.xml file located under WEB-INF folder.

	<?xml version="1.0" encoding="UTF-8"?>
	<sitemesh>
 		<mapping path="/*" decorator="/WEB-INF/decorator/main.jsp"/>
	</sitemesh>

In the above configuration file, the mapping element tells Sitemesh to apply main.jsp decorator to all the pages. Other configuration options provided by Sitemesh 3 are listed here.

5. The final step in the integration is to add Sitemesh filter to web.xml.

  	<filter>
    	<filter-name>sitemesh</filter-name>
    	<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
  	</filter>

 	<filter-mapping>
    	<filter-name>sitemesh</filter-name>
    	<url-pattern>/*</url-pattern>
  	</filter-mapping>

When you run the application you should see the red font color applied due to main.jsp decorator:

Sitemesh App

Categories: SiteMesh, Spring Tags: ,

10 Minute Guide to Spring Web Services

October 5th, 2012 1 comment

Spring Web Services simplifies creation of contract-first SOAP based web services. In this blog post, I will create a hello world web service using Spring Web Services. The service will take a string as a parameter, prepends “Hello ” and returns it. Here are the steps for creating the service:

1. We start by creating a maven based web project. Spring Web Services provides an archetype that can be used to simplify creation of web service project.

2. Add Spring Web Services and its dependent jars to the project. Here is the maven dependency that you need to add:

	
	 <dependencies>
        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
    </dependencies>
	
	

3. Since we are developing contract first web service, we create a data contract that defines the input and output messages the service accepts. Create a helloworld.xsd file under WEB-INF folder with the following content:

	
	<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified"
        targetNamespace="http://blog.inflinx.com/ws/helloworld"
        xmlns:tns="http://blog.inflinx.com/ws/helloworld">

     <element name="helloworldRequest" type="string"/>

    <element name="helloworldResponse" type="string"/>
</schema>
	
	

4. The next step is to create an Endpoint that handles incoming XML messages. Here is the HelloWorldEndpoint implementing hello world service:

package com.inflinx.blog.helloworld;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

@Endpoint
public class HelloWorldEndpoint {
	
	 private static final String NAMESPACE_URI = "http://blog.inflinx.com/ws/helloworld";
	
	 private static final String REQUEST_LOCAL_NAME = "helloworldRequest";
	 
	 private static final String RESPONSE_LOCAL_NAME = "helloworldResponse";
	 
	 
	 @PayloadRoot(localPart = REQUEST_LOCAL_NAME, namespace = NAMESPACE_URI)
	 @ResponsePayload
	 public Element handleRequest(@RequestPayload Element requestElement) throws Exception {
		 
		 // Get the submitted text value
		 String text = requestElement.getChildNodes().item(0).getNodeValue();
		 
		 System.out.println("Request Pay Load: " + text);
		 
		 // Create a response Element
		 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
	     Document document = documentBuilder.newDocument();
	     Element responseElement = document.createElementNS(NAMESPACE_URI, RESPONSE_LOCAL_NAME);
	     Text responseText = document.createTextNode("Hello "+ text);
	     responseElement.appendChild(responseText);
		 
		 return responseElement;
	 }
}

As you can see, the class is annotated with @EndPoint enabling it for component scanning. The @PayloadRoot annotation tells Spring that handleRequest method can handle XML messages. The method implementation is self explanatory: we get the submitted text, create a new response element and return the text with Hello prepended.

5. The next step is to add a Spring Web Service MessageDispatcherServlet to web.xml and map all the incoming requests to it. Here is the modified web.xml file:


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">

    <display-name>Hello World Web Service</display-name>

    <servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
	
    <servlet-mapping>
        <servlet-name>spring-ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

6. The MessageDispatcherServlet is named spring-ws. Hence the servlet will look for a Spring configuration file named spring-ws-servlet.xml under WEB-INF folder. Here is the spring-ws-servlet.xml file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sws="http://www.springframework.org/schema/web-services"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<context:component-scan base-package="com.inflinx.blog.helloworld"/>
	
    <sws:annotation-driven/>

	 <sws:dynamic-wsdl id="helloworld" portTypeName="helloworld" locationUri="http://localhost:8080/hello-world">
        <sws:xsd location="/WEB-INF/helloworld.xsd"/>
    </sws:dynamic-wsdl>

</beans>

The dynamic-wsdl element generates a WSDL automatically for the web service.

7. Deploy the application to a container such as Tomcat or Glassfish. Once deployed, the WSDL can be accessed using the URL: http://localhost:8080/helloworld/helloworld.wsdl

8. Finally, using SOAP UI submit the following request:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hel="http://blog.inflinx.com/ws/helloworld">
   <soapenv:Header/>
   <soapenv:Body>
      <hel:helloworldRequest>World</hel:helloworldRequest>
   </soapenv:Body>
</soapenv:Envelope>

You should see the following response from the service:


<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <helloworldResponse xmlns="http://blog.inflinx.com/ws/helloworld">Hello World</helloworldResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Introduction to Spring Data JPA

September 15th, 2012 11 comments

The Spring Data JPA, a sub project of Spring Data is aimed at simplifying repository implementations. Repositories typically provide Create, Read, Update and Delete (CRUD) operations for domain objects. In this blog post, I will show how Spring Data JPA drastically reduces the effort needed to create repositories.

We will be using HSQLDB as the database and Hibernate as the JPA implementation provider. Here is a complete list project’s dependencies from Maven’s pom.xml file:


	<dependencies>	
		 <dependency>
			 <groupId>org.springframework.data</groupId>
	 		 <artifactId>spring-data-jpa</artifactId>
	 		 <version>1.1.0.RELEASE</version>
	 		 <exclusions>
	 		 	<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>jcl-over-slf4j</artifactId>	 		 	
	 		 	</exclusion>
	 		 	</exclusions>
		</dependency>
		
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.1</version>
		</dependency>
		
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib-nodep</artifactId>
			<version>2.1_3</version>
		</dependency>
		
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>
		
		<dependency>
			<groupId>aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.5.2a</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>3.1.2.RELEASE</version>
			<scope>test</scope>
		</dependency>
		
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>4.1.0.Final</version>
		</dependency>
		
		<dependency>
			<groupId>org.hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>2.2.8</version>
		</dependency>
		
	</dependencies>

Before we go about implementing repositories using Spring Data JPA, let’s create two domain objects Person and Address:


package com.inflinx.blog.springdata.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="PERSON")
public class Person {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="PERSON_ID")
	private Long id;

	@Column(name="FIRST_NAME")
	private String firstName;
	
	@Column(name="LAST_NAME")
	private String lastName;
	
	@Column(name="GENDER_CODE")
	private String genderCode;
		
	// Getters and Setters	
}

package com.inflinx.blog.springdata.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="ADDRESS")
public class Address {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="ADDRESS_ID")
	private int id;

	@Column(name="STREET")
	private String street;
	
	@Column(name="CITY")
	private String city;
	
	@Column(name="STATE")
	private String state;

	@Column(name="ZIPCODE")
	private int zipCode;
	
	@ManyToOne
	@JoinColumn(name="PERSON_ID")
	private Person person;
	
	// Getters and Setters
}	
	

Notice that the two domain classes have JPA annotations such as @Table and @Column that map these classes to relational tables. Also notice the Many To One relationship between Address and Person classes.

Simple JPA Repository

We now start by creating a Spring Data JPA repository for the Person class. This involves creating a repository interface as shown below. The PersonRepository interface extends the Spring Data JPA’s Repository marker interface and has one finder method. The findOne method follows Spring Data JPA’s naming convention for retrieving an entity using its ID.

package com.inflinx.blog.springdata.repository;

import org.springframework.data.repository.Repository;
import com.inflinx.blog.springdata.domain.Person;

public interface PersonRepository extends Repository < Person, Long > {
	public Person findOne(Long id);
}

Traditionally, we would also create an implementation class for this repository. However Spring Data JPA alleviates this need and provides an implementation class (proxy) automatically at runtime. For this to happen, we add the jpa:repositories bean declaration to our context file. Here is the complete context file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:repository="http://www.springframework.org/schema/data/repository"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.1.xsd
		http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
	
	<jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:schema.sql"/>
        <jdbc:script location="classpath:test-data.sql"/>
    </jdbc:embedded-database>
    
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
          p:data-source-ref="dataSource" p:persistence-xml-location="classpath:test-persistence.xml" p:jpaDialect-ref="jpaDialect">
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>  
       
	<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
	
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
          p:entity-manager-factory-ref="entityManagerFactory">
    </bean>
    
    <jpa:repositories base-package="com.inflinx.blog.springdata.repository" />
</beans>

The jdbc:embedded-database tag in the context file starts an in-memory database using HSQLDB and creates a datasource for it. The schema.sql file shown below has the DDL commands for creating the Person and Address table:

CREATE TABLE PERSON (PERSON_ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, 
					FIRST_NAME VARCHAR(256), 
					LAST_NAME VARCHAR(256), 
					GENDER_CODE VARCHAR(1));

CREATE TABLE ADDRESS(ADDRESS_ID INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, 
 					STREET VARCHAR(256), 
 					CITY VARCHAR(100), 
 					STATE VARCHAR(10), 
 					ZIPCODE INT,
 					PERSON_ID INT,
 					FOREIGN KEY (PERSON_ID) REFERENCES PERSON(PERSON_ID)); 

The test-data.sql file has the test data we will be using to test our repositories:

	INSERT INTO PERSON (FIRST_NAME, LAST_NAME, GENDER_CODE) VALUES ('John', 'Doe', 'M');
	INSERT INTO PERSON (FIRST_NAME, LAST_NAME, GENDER_CODE) VALUES ('Jane', 'Doe', 'F');
	INSERT INTO PERSON (FIRST_NAME, LAST_NAME, GENDER_CODE) VALUES ('Joe', 'Bloggs', 'M');

The entitiyManagerFactory bean uses test-persistence.xml file that has the standard JPA configuration.


<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

  <persistence-unit name="springdata" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    
    <class>com.inflinx.blog.springdata.domain.Person</class>
    <class>com.inflinx.blog.springdata.domain.Address</class>
    
    <properties>
      <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="update"/>
	  <property name="hibernate.show_sql" value="true"/>
	  <property name="hibernate.format_sql" value="true"/>
    </properties>
  </persistence-unit>
</persistence>

This completes all the setup needed for creating a Spring Data JPA repository. Now let’s create a JUnit test class to test our implementation.


package com.inflinx.blog.springdata.repository;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;

import com.inflinx.blog.springdata.domain.Person;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
@Transactional
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class PersonRepositoryTest {

	@Autowired
	private PersonRepository personRepository;
	
	@Test
	public void testPerson() {
		Person person = personRepository.findOne(1L);
		Assert.assertNotNull(person);
		System.out.println("First Name: " + person.getFirstName());
	}
	
}

Notice that we are simply injecting the PersonRepository implementation into the test. When you run the class, you should see that test has passed and “First Name: Jane” in your console.

CRUD JPA Repository

The above PersonRepository has only one finder method and might not be ideal for most real world cases. To address this, Spring Data JPA provides an aptly named CrudRepository interface that extends Repository interface and adds persistence, finder and delete methods. The table below lists some of the available CrudRepository methods:

save(S entity) Saves a given entity
save(Iterable entities) Saves all the given entities
findOne(ID id) Retrieves an entity by its id
exists(ID id) Checks if a given entity exists
findAll Returns all the entities
count Returns the number of all the entities
delete(ID id) Deletes an entity with the given id
delete(T entity) Delets a given entity

A new person repository interface that uses CrudRepository is given below.


package com.inflinx.blog.springdata.repository;

import org.springframework.data.repository.CrudRepository;

import com.inflinx.blog.springdata.domain.Person;

public interface PersonCrudRepository extends CrudRepository < Person, Long > {

}

Here is a JUnit test that tests the above repository:


package com.inflinx.blog.springdata.repository;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;

import com.inflinx.blog.springdata.domain.Person;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
@Transactional
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class PersonCrudRepositoryTest {

	@Autowired
	private PersonCrudRepository personRepository;
	
	@Test
	@Rollback(false)
	public void testCreate() {
		Person p = new Person();
		p.setFirstName("Test");
		p.setLastName("Data");
		p.setGenderCode("M");
		
		p = personRepository.save(p);
		Assert.assertNotNull(p.getId());
		System.out.println("Created Id: " + p.getId());
	}	
}

Custom Finder Methods

Spring Data JPA makes it very easy to add new finder methods to repositories. For example, let’s say we want to retrieve all persons with a given last name. Here is the modified PersonCrudRepository repository with the new finder method:

package com.inflinx.blog.springdata.repository;

import java.util.List;
import org.springframework.data.repository.CrudRepository;
import com.inflinx.blog.springdata.domain.Person;

public interface PersonCrudRepository extends CrudRepository < Person, Long > {

	public List< Person > findByLastName(String lastName);
}

The convention for these finder methods is simply findByMemberName. It is also possible to combine multiple members into one finder method. So, findByLastNameAndFirstName(String lastName, String firstName) will find all persons with the given first name and last name.

Here is the JUnit test class to test the findByLastName method:

 

	@Test
	public void testFindByLastName() {
		
		List< Person > lastNameList = personRepository.findByLastName("Doe");
		Assert.assertEquals(2, lastNameList.size());
	}

Named Queries

The out of the box CRUD methods are sufficient for most cases. However, there are times where we might want to execute custom SQL Queries to retrieve data. For example, let’s say we want to count all the persons that have a given last name. To address such situations, Spring Data JPA provides a @Query annotation. Here is the new person repository with the @Query annotated method:

package com.inflinx.blog.springdata.repository;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import com.inflinx.blog.springdata.domain.Person;

public interface PersonCrudRepository extends CrudRepository < Person, Long > {

	@Query("select count(p) from Person p where p.lastName = ?1")
	public Long getLastNameCount(String lastName);
	
}

Here is a test method for the above Query method:

	@Test
	public void testGetLastNameCount() {
		
		Long count = personRepository.getLastNameCount("Doe");
		Assert.assertEquals(2L, count.longValue());
	}

Custom Repository Implementation

For cases, where the out of the box repository implementations are not enough, Spring Data JPA makes it easy to provide custom implementations that would still integrate with the generic repository abstraction. To see this in action, let’s implement a custom Address repository. We start with a custom interface that declares the additional functionality.

package com.inflinx.blog.springdata.repository;

public interface AddressRepositoryCustom {
	
	public Long someRandomMethod();
	
}

The next step is to create a class that implements the custom functionality.

package com.inflinx.blog.springdata.repository.jpa;

import com.inflinx.blog.springdata.repository.AddressRepositoryCustom;

public class AddressRepositoryImpl implements AddressRepositoryCustom {

	public Long someRandomMethod() {
		return 143L;
	}
}

Finally, we create the AddressRepository interface that extends the custom interface as shown below:

public interface AddressRepository extends CrudRepository < Address, Long >, AddressRepositoryCustom {
	
}

Here is a test class that tests the custom method implementation:

package com.inflinx.blog.springdata.repository;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
@Transactional
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class AddressRepositoryCustomTest {
	
	@Autowired
	private AddressRepository personRepository;
	
	@Test
	public void testSomeMethod() {
		
		Assert.assertEquals(143L, personRepository.someRandomMethod().longValue());
	}
	
}

Spring Data JPA requires that you follow strict naming conventions when creating custom repository implementation (unless you provide additional configuration). For example, if the repository interface is AddressRepository, then the name of the custom interface should be AddressRepositoryCustom. If you don’t follow this convention, you will end up with errors similar to this:

Caused by: java.lang.IllegalArgumentException: Could not create query metamodel for method public abstract java.lang.Long com.inflinx.blog.springdata.repository.AddressRepositoryCustom.someRandomMethod()!
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:92)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:162)

Spring Async And Future – Report Generation Example

September 9th, 2012 9 comments

Spring 3.0 introduced the @Async annotation for executing tasks asynchronously. The asynchronous capabilities are highly useful in situations where we need to execute a long running task before allowing user input. For example, every time we open a Gmail message with attachment, Gmail performs a anti-virus scan before showing the download link to the user.

In this blog post, I will kick off a long running report asynchronously. Then I will use JQuery to periodically check if the report has been created. When the report is finally available, a link to the report is shown to the user.

We start by creating a ReportService as shown below. The generateReport method returns java.util.concurrent.Future interface. This interface allows the caller to retrieve the execution result at later time.

package com.inflinx.blog.springfuture.service;

import java.util.concurrent.Future;

import com.inflinx.blog.springfuture.domain.Report;

public interface ReportService {
	
	public Future generateReport();
	
}

The report service implementation is shown below. We simulate the “long running process” by calling the sleep method on the current thread. The method returns AsyncResult instance with the newly created Report as pass through value.


package com.inflinx.blog.springfuture.service;

import java.util.concurrent.Future;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import com.inflinx.blog.springfuture.domain.Report;

@Service("reportsService")
public class ReportServiceImpl implements ReportService {

	@Async
	public Future generateReport() {
		
		try {
			Thread.sleep(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		Report report = new Report();
		report.setName("New Report");
		report.setDescription("New Report Description");
		
		return new AsyncResult(report);
	}
	
}

We complete the service layer implementation by adding the following Spring configuration file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:task="http://www.springframework.org/schema/task"
       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
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <context:annotation-config />
    
    <context:component-scan base-package="com.inflinx.blog.springfuture.service" />
       
    <task:annotation-driven />
       
</beans>       		

Now that we have completed our service layer, let’s create an MVC Controller that uses the ReportService to create a new report. The new report is then saved in the user’s session.

package com.inflinx.blog.springfuture.web.controller;

import java.util.concurrent.Future;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.inflinx.blog.springfuture.domain.Report;
import com.inflinx.blog.springfuture.service.ReportService;

@Controller
public class HomeController 
{
	@Autowired
	@Qualifier("reportsService")
	private ReportService reportService;
	
	@RequestMapping(value="/home.html", method=RequestMethod.GET)
	public String showHome(HttpSession session) 
	{
		Future report = reportService.generateReport();
		
		session.setAttribute("report", report);
		
		return "home";
	}	
}

To this controller, we then add a method that returns the status of the report generation. The method implementation simply retrieves the Future object and invokes the isDone method to check the status of the running task.

	@RequestMapping("/reportstatus.json")
	@ResponseBody
	public String reportStatus(HttpSession session) {
		Future report = (Future)session.getAttribute("report");
		
		if(report.isDone()) {
			System.out.println("Report Generation Done");
			return "COMPLETE";
		}
		else {
			System.out.println("Still Working on Report");
			return "WORKING";
		}
	}

We then add a method to the controller that shows the generated report as shown below:


@RequestMapping(value="/report.html", method=RequestMethod.GET)
	public String showReport(HttpSession session, Model model) throws InterruptedException, ExecutionException 
	{
		Future report = (Future)session.getAttribute("report");
		
		Report r = report.get();
		model.addAttribute("report", r);
		
		return "report";
	}

The report.jsp view returned by the above method is shown below:


<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Generated Report
</h1>

 Name: ${report.name} <br />
 Description: ${report.description}

</body>
</html>

We finally tie everything in the home.jsp view that gets returned by the showHome method. In the home.jsp, we use JQuery’s setInterval method to call the reportstatus.json URL every two seconds. Once we get the “COMPLETE” response, we show the download link.


<html>
<head>
	<title>Home</title>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>

<script type="text/javascript">
	
	$(document).ready(function() {
		
		// Check The Status Every 2 Seconds
		var timer = setInterval(function() {
			
			$.ajax({
				  url: 'reportstatus.json',
				  success: function(data) {
					
					if(data === 'COMPLETE') {
						$('#reportLink').html("<a target='_target' href='report.html'>Download Report</a>");	
						clearInterval(timer);
					}
				  }
			});
			
		}, 2000);
	});
		
</script>

</head>
<body>
<h1>
  Report Generator
</h1>

<div id="reportLink">Please Wait While Your Report Is Being Generated</div>

</body>
</html>

Here is a screenshot of the application’s home.jsp page:

Here is a screenshot after the report has been generated:

The screenshot of the newly generated report:

Categories: Spring Tags: , ,

Spring Environment Profiles

August 26th, 2012 1 comment

Often time our web applications depend on properties that can change depending upon the environment (DEV/Stage/Production) the application is running. Examples of these include admin email addresses or URLs to communicate with web services. I am a big advocate of promoting the same war file across all the environments. In order to achieve that, I create separate property files and bundle them in the war file. Couple years ago, I wrote a custom Properties Holder implementation that would look at a JNDI key “Environment” and load the appropriate property file. Spring 3.1 introduces Environment Profiles that simplifies this entire process.

In this blog, I will create a web application and three property files each holding an email address that is specific to an environment. Then I will create bean profile definitions in Spring context file and activate them external to the web application.

We start by creating a Maven based web application using my Spring archetype. Here is the generated web application:
Spring MVC Maven Project

The next step is to create the following three property files in the src->main->resources folder:
Project_Dev.Properties

Project_Test.Properties

Project_Prod.Properties

Now, let’s modify the applicationContext.xml file to include the bean profiles each loading their respective property files. Here is the modified application-Context.xml file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
	
	<!-- Load the dev property files by default -->
    <util:properties id="projectProperties" location="classpath:project_dev.properties"/>
 
 	<beans profile="Test">
 		<util:properties id="projectProperties" location="classpath:project_test.properties"/>
 	</beans>
 	
 	<beans profile="Prod">
 		<util:properties id="projectProperties" location="classpath:project_prod.properties"/>
 	</beans>
       
</beans>       		

	

Notice that we are using Spring’s new 3.1 schema definitions in the context file. The context file has two profiles one for test and one for production. By default, Spring would load all the properties from the project_dev.properties file. Also observe that we have used the same id for all the util:properties beans.

We then modify the HomeController class and home.jsp file to read and display the “admin.email” property. We do that using the @Value annotation in the HomeController and add it to Model as shown below:


package com.inflinx.blog.springprofiles.web.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/home.html")
public class HomeController 
{
	@Value("#{projectProperties.adminEmail}") 
	private String adminEmail;
	
	@RequestMapping(method = RequestMethod.GET)
	public String showHome(Model model) 
	{
		model.addAttribute("adminEmail", adminEmail);
		return "home";
	}
	
}

Finally, we modify the home.jsp page to show the email property:

<%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
<%@ page session=”false” %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Admin Email: ${adminEmail}
</h1>

</body>
</html>

Deploy the application and you should see the default dev admin email in the browser:
Browser Dev Email

To activate the Test profile, add the Environment Variable spring.profiles.active with value Test. In Windows, you can do that by going to Advanced Settings -> Environment Variable -> New
Environment Variables

If you are running your Application Server from Eclipse, restart Eclipse and redeploy the app. In the logs you should be able to see that Spring has activated Test profile:
Spring Active Profiles

Upon refreshing the browser, you should see the new admin email:
Test Admin Email

Categories: Maven, Spring Tags:

Integrating CAPTCHA Into Spring MVC Web Applications

May 25th, 2012 3 comments

Integrating CAPTCHA in an application involves two simple steps:

  1. Display CAPTCHA Widget
  2. Validate CAPTCHA Reponse

In this blog post, I will be using Google’s reCAPTCHA. Before we can start using reCAPTCHA, we need to sign up for API keys.

Obtaining reCAPTCHA keys

1. Go to the reCAPTCHA Key Signup Page and login using your Google Account.

Enter the your domain name and hit “Create Key”. The generated keys by default are restricted to the specified domain. However, all keys will work on the localhost domain, making it easy to test during development.

Captcha Creation



Make a note of the generated public and private keys. We need both keys in order to generate CAPTCHA and verify response.

Display CAPTCHA Widget

reCAPTCHA provides a Java Library wrapper that makes CAPTCHA generation/verification easier. Maven users can get the jar file with the following dependency:

   <dependency>
		<groupId>net.tanesha.recaptcha4j</groupId>
		<artifactId>recaptcha4j</artifactId>
		<version>0.0.7</version>
	</dependency>

With the dependency added, generating the CAPTCHA Widget simply involves placing the below scriptlet in a JSP page:

	<%
		ReCaptcha captcha = ReCaptchaFactory.newReCaptcha("PUBLIC_KEY", "PRIVATE_KEY", false);
		out.print(captcha.createRecaptchaHtml(null, null));
    %>	

In the above code, we first create an instance of ReCaptcha by passing in the generated public and private key. The third parameter instructs if a noscript tag should to be placed around the generated HTML.

Since, I don’t like using Scriptlets in my JSP pages, I will create a reusable JSP tag that wraps the above code. We start out by creating a CaptchaTag class as shown below:


package com.inflinx.blog.web.tag;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import org.apache.commons.lang.StringUtils;

import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaFactory;

public class CaptchaTag extends SimpleTagSupport
{
	private String publickey;
	private String privatekey;
	private String themeName;
	
	@Override
	public void doTag() throws JspException, IOException 
	{
		ReCaptcha captcha = ReCaptchaFactory.newReCaptcha(publickey, privatekey, false);
		Properties properties = new Properties();
		
		if(StringUtils.isNotEmpty(themeName))
		{
			properties.put("theme", themeName);
		}
		
		String captchaHtml = captcha.createRecaptchaHtml(null, properties);
		getJspContext().getOut().write(captchaHtml);
	}

	public String getThemeName() {
		return themeName;
	}

	public void setThemeName(String themeName) {
		this.themeName = themeName;
	}

	public String getPublickey() {
		return publickey;
	}

	public void setPublickey(String publickey) {
		this.publickey = publickey;
	}

	public String getPrivatekey() {
		return privatekey;
	}

	public void setPrivatekey(String privatekey) {
		this.privatekey = privatekey;
	}
}

The above tag takes has three attributes: public key, private key and theme name. The theme option can be used to control the reCAPTCHA widget’s look and feel. Possible values include: “red”, “white”, “blackglass” or “clean”. The default is the red.

To complete the implementation of the tag, lets create a captcha.tld file under WEB-INF/tlds folder with the following contents:

<taglib xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1">
     
    <tlibversion>1.0</tlibversion>
    <jspversion>2.1</jspversion>
    <shortname>CaptcahTags</shortname>
    <uri>http://blog.inflinx.com</uri>
    <info>Captcha Tags</info>
 
    <tag>
        <name>captcha</name>
        <tagclass>com.inflinx.blog.web.tag.CaptchaTag</tagclass>
        <bodycontent>empty</bodycontent>
        <info>Generates Captcha Widget</info>
        <attribute>
             <name>publickey</name>
             <required>true</required>
			 <rtexprvalue>true</rtexprvalue> 
        </attribute>
		<attribute>
             <name>privatekey</name>
             <required>true</required>
			 <rtexprvalue>true</rtexprvalue> 
        </attribute>
		<attribute>
             <name>themeName</name>
             <required>false</required>
			 <rtexprvalue>true</rtexprvalue> 
        </attribute>
    </tag>
 
</taglib>

With all this in place, update the JSP page with the following code to display the CAPTCHA Widget:


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib prefix="captcha" uri="/WEB-INF/tlds/captcha.tld" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<html>
<head>
	<title>Home</title>
</head>
<body>

<form method="post">

	<captcha:captcha themeName="clean" publickey="YOUR_PUBLIC_KEY" privatekey="YOUR_PRIVATE_KEY"/>
	
</form>


</body>
</html>

Upon running the code, you should see a CAPTCHA similar to the image below:

Captcha In Action

Validate CAPTCHA Reponse

In order to valdiate the CAPTCHA response, we need to modify the POST method of the receiving controller as shown below:

@RequestMapping(method = RequestMethod.POST)
	public String processSubmit(HttpServletRequest request, Model model)
	{
		ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
        reCaptcha.setPrivateKey("YOUR_PRIVATE_KEY");
        
		String remoteAddr = request.getRemoteAddr();
        String challengeField = request.getParameter("recaptcha_challenge_field");
        String responseField = request.getParameter("recaptcha_response_field");
        ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(remoteAddr, challengeField, responseField);

        if(!reCaptchaResponse.isValid())
        {
        	model.addAttribute("invalidCaptcha", "Captcha Is Invalid");
        	return "home";
        }
        
        return "success";
	}

In the above code, we start by creating a ReCaptchaImpl instance and pass in the Private key. The reCaptcha widget generates two fields “recaptcha_challenge_field”, “recaptcha_response_field” that are needed to verify the response. We pass in those two fields along with the IP Address of the client to get a response.

For invalid responses, we set a model attribute to indicate the error. Now, in a Spring MVC application where you are using a command object for the form, you can add an error instance instead:

		if(!reCaptchaResponse.isValid())
        {
        	errors.reject("captcha.invalid");
        }