Archive

Archive for the ‘Solutions Log’ 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: ,

Getting Started With Git and GitHub on Mac

January 5th, 2014 No comments

I recently got a new Mac and had to go through the process of connecting to GitHub. Here is some notes that I took during this process.

We start our journey at GitHub.com. If you are new to GitHub, you would need to create an account before proceeding. Once you are logged in to GitHub, hit the “Create a New Repo” button on the top right.

1

Enter your new repo information as shown below. I have asked GitHub to create a README file and added MIT License. If you are not sure what license to use, GitHub provides a website to help you with your decision. GitHub also allows you to add a .gitignore file with predefined ignore patterns while creating a repo.

2

Once GitHub creates a repo, you will be redirected to the repo page and you can see the contents of the repo.
3

This concludes our setup on GitHub. The next step is to checkout the repo on to your Mac. Before we do that, check and make sure you have Git instlled on your Mac:
4

Since I have already installed XCode for iOS App development, Git gets installed during that process. If you don’t have Git installed, you can download it from GitHub site.

The next step is to configure Git. Open a Terminal and run the following commands:

 $git config --global user.name "Your Name"
 $git config --global user.email "Your Email Address"
 $git config --global apply.whitespace nowarn

Since we are running on Mac, let’s make sure that .DS_Store folders are ignored globally. To do this, run the following command:

  git config --global.core.excludesfile ~/.global_gitignore
  echo .DS_Store >> ~/.global_gitignore

In the past, I have used SSH Keys to connect Mac to GitHub. Moving forward, I will be using Https instead. One drawback with Https is that it would require us to enter our username and password everytime we talk to GitHub. To fix this, we will use osxkeychain credential helper to cache our username and password. Before you move forward run the following command to ensure that osxkeychain is installed.

git credential-osxkeychain
usage: git credential-osxkeychain 

Now, configure Git to use osxkeychain credential helper:

   $git config --global credentail.helper osxkeychain

We are finally ready to checkout the GitHub repo. Run the following command:

  git clone https://github.com/YOUR_USERNAME/YOUR_REPO_NAME 

If you have everything setup correctly, Git would create a folder with your repo name and checkout files. You should see a result similar to this:
5

Go to the repo and run git status. You should get message “nothing to commit, working directory clean”.

Let’s modify READEME.md file using your favourate editor. Now running git status shows that we have modified READEME.md.
6

Let’s commit README file by running the following command:

  git commit -am "Updated README"

The final step in this process is to push our changes over to GitHub by running the following command:

  git push origin master

If you are running this for the first time, you will be prompted to enter username and password. Git will cache these and will not prompt you in future. Since, I have this information cached, here is what I get:
7

Go to GitHub.com repo and see that your changes are on the repo:
8

Categories: Git, Solutions Log 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)

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");
        }

Obtaining/Redeeming App Store Promo Codes

April 26th, 2012 No comments

My new iPhone app JEE Interview Questions went on sale today.

JEE Interview Questions App

I needed to get some promo codes and thought it would be a good idea to log the process of obtaining and redeeming promo codes. Before we get any further it is important to remember that Apple only gives out fifty codes for each application. These codes are strictly for non-commercial use only and will expire in 28 days.

Obtaining Promo Codes

In order to obtain the promo code for your app, start by logging into iTunes Connect. Then hit Manage Your Applications.
Manage Apps

On the Application Details page, click the “View Details” button for the version you are interested in.
App Details

The ensuing Page click the “Promo Codes” button.
Promo Codes Link

Then, enter the number of codes you would like and hit Continue. You will be asked to accept Apple’s contract.


The next page will contain a Download button that will allow you to download the promo codes in a text file.
Download Promo Codes

Redeeming Promo Codes

To redeem a promo code, you need to launch the iTunes application on your Mac or Windows. On the top right corner of the iTunes Store, click the “Redeem” link.
Redeem Code

On the next screen, enter the promo code. You might be asked to login. Then, you will see a success screen and your app will get automatically downloaded.
Redeem Success

One way to get the app is to launch the App Store app on your iPhone. Go to Updates -> Purchased -> “Not On This iPhone” and you will see your app waiting to be installed.
JEE Interview Questions - Not Purchased

Categories: iPhone, Solutions Log Tags: , ,

Custom JSR 303 Constraints

April 24th, 2012 No comments

In my previous blog post I talked about validating Spring Web applications using JSR 303 annotations. In that post, we used the out of the box JSR 303 constraints such as @NotEmpty and @Size. These out of the box constraints should be sufficient for most cases. However, there will be situations where you want to develop custom constraints. In this post, we will look at creating a custom constraint
that validates the ISBN number of a book in our Online Bookstore Admin application.

Each JSR 303 validation constraint consists of two parts. The first part is the constraint annotation itself.

package com.inflinx.blog.bookstore.constraint;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy=IsbnValidator.class)
public @interface Isbn 
{
	String message() default "{Isbn.message}";

	Class[] groups() default {};

	Class[] payload() default {};
}

The JSR 303 specification requires each constraint annotation to define the following three attributes:

  • message – The error message that gets returned upon validation failure. Here we have defined the default value Isbn.message that acts as a resource bundle key. It is possible to just hard code a message by simply omitting the braces.
  • groups – This defines the constraint groups that this annotation needs to be associated with. Here we will use the default group.
  • Payload – This holds the additional metadata information that can be supplied by validation clients. Here we are using the default empty array.

The @Target, @Retention and @Documented annotations are needed for the annotation declaration. The @Constraint annotation declares the validator that we will be using to validate elements annotated with @Isbn constraint.

The next step in creating the custom constraint is defining the validator.

package com.inflinx.blog.bookstore.constraint;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.apache.commons.validator.routines.ISBNValidator;

public class IsbnValidator implements ConstraintValidator
{
	@Override
	public void initialize(Isbn isbn) { }

	@Override
	public boolean isValid(String value, ConstraintValidatorContext validatorContext) 
	{
		if(value == null || "".equals(value))
		{
			return true;
		}
		else
		{
			return ISBNValidator.getInstance().isValid(value);
		}
	}

}

Every constraint validator needs to implement the ConstraintValidator interface. The actual implementation of the IsbnValidator is straightforward. According to the specification, if the annotated element’s value is null or empty the validation should succeed. If you don’t want a null value, the element should be annotated with @NotNull annotation. The actual validation of the ISBN value is delegated to the Apache Validation API.

Now that we have the constraint defined, the next step is to use it in our Book Store application. To do that, we start out by creating a new property in the Book domain class and annotated it with @Isbn annotation. Here is the modified book class:

package com.inflinx.blog.bookstore.domain;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;

import com.inflinx.blog.bookstore.constraint.Isbn;

public class Book
{
	@NotEmpty
	private String name;
	
	@Size(min=1, max=50)
	private String description;
	
	@NotEmpty
	@Isbn
	private String isbn;
	
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public String getDescription()
	{
		return description;
	}
	public void setDescription(String description)
	{
		this.description = description;
	}
	
	@Override
	public String toString()
	{
		return "Name: " + name + ", Description: " + description + ", ISBN: " + isbn;
	}
}

Then we need to modify the form.jsp file to add the ISBN form field.

 		<form:form method="post" action="book.html" commandName="book">
					<table>
						<tr>
							<td>Name:</td> <td><form:input path="name" /></td> <td><form:errors path="name" /></td>
						</tr>
						<tr>
							<td>Description:</td> <td><form:textarea path="description"/></td> <td><form:errors path="description" /></td>
						</tr>
						<tr>
							<td>ISBN:</td> <td><form:input path="isbn" /></td> <td><form:errors path="isbn" /></td>
						</tr>
						</table>
					<input type="submit" value="Create" />
		</form:form>

The final step in this process is to add a new validation key/value to the messages.properties file. Here is the new messages.properties file:

NotEmpty.book.name=Name is a required field
Size.book.description=Description must be between 1 and 50 characters
Isbn.book.isbn=Please enter a valid ISBN

Now, when you submit the form with an invalid ISBN value, you will see a validation error.