четверг, 26 сентября 2013 г.

Integration and unit testing with JUnit and Spring Framework

     Testing is the important part of software development. But very often it turns to some kind of challenge. In this article we will use Spring Framework because it provide excellent support for integration and unit testing. 
     Unit testing is used to test a some unit or module in the application in isolation, but integration testing of the application also very important. They help to see different behavior when integrated with other modules in the application. 
     Continuing the previous article, here I’ll show a way to test a service layer with Spring, JUnit, HSQLDB and Maven. First of all, let’s remember the necessary configuration files. Here they are: spring-beans-test.xml, servlet-context-test.xml, persistence-test.xml, all these files are in the src/test/resources package. The description for each file can be found in my previous post. 
     Now we’re ready to write a unit test that will check all the methods of the UserService service.
     Well, a few lines of code speaks more than a thousand words from me...
/**
 * Unit test for the client service layer.
 * 
 * @author Dmitry Nikolaenko
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { 
        "/spring-beans-test.xml", 
        "/servlet-context-test.xml" })
public class UserServiceTest {
    @Autowired
    private UserService userService;
    
    @Test
    public void createTest() {
        User user = userService.create(createTestUser());
        
        Assert.assertNotNull(user);
        Assert.assertNotNull(user.getId());
        Assert.assertEquals("Tom", user.getName());
    }
    
    @Test
    public void deleteTest() {
        User user = userService.create(createTestUser());
        userService.delete(user.getId());
        User deletedUser = userService.find(user.getId());
        
        Assert.assertNull(deletedUser);
    }
    
    @Test
    public void updateTest() {
        User user = userService.create(createTestUser());
        user.setName("Bob");
        userService.update(user);
        User foundUser = userService.find(user.getId());
        
        Assert.assertNotNull(foundUser);
        Assert.assertEquals("Bob", foundUser.getName());
    }
    
    @Test
    public void findTest() {
        User user = userService.create(createTestUser());
        User foundUser = userService.find(user.getId());
        
        Assert.assertNotNull(foundUser);
        Assert.assertNotNull(foundUser.getId());
        Assert.assertEquals("Tom", foundUser.getName());
    }
    
    @Test
    public void getAllTest() {
        userService.create(createTestUser());
        List<User> users = userService.getAll();
        
        Assert.assertNotNull(users);
        Assert.assertFalse(users.isEmpty());
    }
    
    @Test
    public void countTest() {
        userService.create(createTestUser());
        long before = userService.count();
        userService.create(createTestUser());
        long after = userService.count();
        
        Assert.assertEquals(before, after - 1);
    }
    
    /**
     * Create a test user.
     */
    private User createTestUser() {
        User user = new User();
        user.setAge(30);
        user.setName("Tom");
        
        return user;
    }
}
     UserServiceTest annotated as @RunWith(SpringJUnit4ClassRunner.class). Class provides functionality of the Spring TestContext Framework to standard JUnit. It means that Spring JUnit runner allows you to set up Spring ApplicationContext for tests and use dependency injection. 
     @ContextConfiguration(locations = { "/spring-beans-test.xml", "/servlet-context-test.xml" }) tells the path where is located application context to load for test
     @Autowired allow autowired by Spring's dependency injection facilities.
     The source code of our integration test looks as follows.
/**
 * Integration test.
 * 
 * @author Dmitry Nikolaenko
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { 
        "/spring-beans-test.xml", 
        "/servlet-context-test.xml" })
public class UserRestServiceTest {
    private static final String REST_APP_URL = "http://localhost:8080/RESTfulWebApp/rest/users";
    private RestTemplate restTemplate = new RestTemplate();
            
    @Test
    public void addUserTest() {
        // create a new resource by POSTing the given object to the URI template, 
        // and returns the representation found in the response. 
        User createdUser = restTemplate.postForObject(REST_APP_URL, createUser(), User.class);
        
        Assert.assertNotNull(createdUser);
        Assert.assertEquals("Tom", createdUser.getName());
        Assert.assertNotNull(createdUser.getId());
    }
    
    @Test
    public void findUserTest() {
        User createdUser = restTemplate.postForObject(REST_APP_URL, createUser(), User.class);
        
        // retrieve a representation by doing a GET on the specified URL, 
        // the response is converted and returned. 
        User userFound = restTemplate.getForObject(createRestAppUrl(createdUser), User.class);
        Assert.assertNotNull(userFound);
        Assert.assertEquals("Tom", userFound.getName());
        Assert.assertNotNull(userFound.getId());
    }
    
    @Test
    public void updateUserTest() {
        User createdUser = restTemplate.postForObject(REST_APP_URL, createUser(), User.class);
        
        createdUser.setName("Bob");
        // update a resource by PUTing the given user to the URI
        restTemplate.put(createRestAppUrl(createdUser), createdUser);
        User userFound = restTemplate.getForObject(createRestAppUrl(createdUser), User.class);
        
        Assert.assertNotNull(userFound);
        Assert.assertEquals("Bob", userFound.getName());
    }
    
    @Test
    public void loadUsersTest() {
        restTemplate.postForObject(REST_APP_URL, createUser(), User.class);
        Users users = (Users) restTemplate.getForObject(REST_APP_URL, Users.class);
        
        Assert.assertNotNull(users);
        Assert.assertNotNull(users.getUsers());
        Assert.assertFalse(users.getUsers().isEmpty());
    }
    
    @Test
    public void deleteUserTest() {
        // just create new user
        User createdUser = restTemplate.postForObject(REST_APP_URL, createUser(), User.class);
        
        // testing...
        Assert.assertNotNull(createdUser);
        Assert.assertEquals("Tom", createdUser.getName());
        Assert.assertNotNull(createdUser.getId());
        
        // try to find it and then testing...
        User userFound = restTemplate.getForObject(createRestAppUrl(createdUser), User.class);
        Assert.assertNotNull(userFound);
        Assert.assertEquals("Tom", userFound.getName());
        Assert.assertNotNull(userFound.getId());
        
        // delele it
        restTemplate.delete(createRestAppUrl(userFound));
        
        // and finally try to find again, but we lost him forever
        User deletedUser = restTemplate.getForObject(createRestAppUrl(createdUser), User.class);
        Assert.assertNull(deletedUser);
    }
    
    /**
     * Create a test user.
     */
    private User createUser() {
        User user = new User();
        user.setAge(30);
        user.setName("Tom");
        
        return user;
    }
    
    /**
     * Construct REST URL for testing.
     * 
     * @param user for testing
     */
    private String createRestAppUrl(User user) {
        return REST_APP_URL.concat("/").concat(user.getId().toString());
    }
}
     Now you can test functionality with Curl.
http://localhost:8080/RESTfulWebApp/rest/users - get all users (GET) http://localhost:8080/RESTfulWebApp/rest/users - create user (POST) http://localhost:8080/RESTfulWebApp/rest/users/5 - find user by id = 5 (GET) http://localhost:8080/RESTfulWebApp/rest/users/5 - update user with id = 5 (PUT) http://localhost:8080/RESTfulWebApp/rest/users/5 - delete user with id = 5 (DELETE)
     Source code of the project available on Github.

RESTful application with Spring, Hibernate and JPA

     This is a first part of the article where we’ll build a RESTful application with Spring, Hibernate and JPA. For this application we’ll also use Maven for build, HSQLDB(in memory mode) as database to persist the data, Jetty as a server and JUnit as a standalone testing tool. In the second part, it will be another article we’ll see how to test a service layer through unit and integration tests. 
     The goal of the article is to create a RESTful user manager application which will allow create, delete, update, find, getAll or just get a count of users etc.
The Data Access Layer. Generic DAO Pattern
     Very often developers forget about beauty of code, about OOP and using code duplication and copy-and-paste wherever it possible. It may cause a daily nightmares and logical contradictions. DRY-principle(Don’t Repeat Yourself) reduces duplication and very helpful for this situation but it also leads to high coupling and reduced readability. But here we’ll look at slightly different pattern that will help us to save our time and nerves. DAO pattern provides an architectural foundation, type safety and avoid code duplication. Here you find an official information about DAO by Oracle
     Let’s see to the Generic Dao structure of the project.
GenericDao interface can be used for a single specified type domain object. A single instance implementing this interface can be used only for the type of domain object specified in the type parameters.
public interface GenericDao<T extends Serializable> {
    /**
     * Returns the total number of results
     */
    public long count();
    
    /**
     * Create and save new object in DB.
     */
    public T create(T t);
    
    /**
     * Remove the entity with the specified type and id from the datastore.
     */
    public void delete(Object id);
    
    /**
     * Get the entity with the specified type and id from the datastore.
     * 
     * @param id of the entity.
     * @return If none is found, return null.
     */
    public T find(Object id);
    
    /**
     * Get a list of all the objects of the specified type.
     */
    public List<T> getAll();
    
    /**
     * Update object in DB.
     */
    public T update(T t);
}
     GenericDaoImpl abstract class is an implementation of generic DAO with Hibernate. This class offers CRUD method for a generic type T. It should be used only through concrete DAO implementations. Here you can see a Spring @PersistenceContext annotation to inject the entity manager associated with a specific persistence unit. Also an interesting field - Class<T> type, it’s a parametrized type of a class(entity/model) and we use it in EntityManager’s method via reflection.
/**
 * Implementation of Generic DAO. 
 * 
 * @author Dmitry Nikolaenko
 *
 * @param <T> The type of the domain object for which this instance is to be used.
 */
public abstract class GenericDaoImpl<T extends Serializable> implements GenericDao<T> {
    private static final Logger logger = Logger.getLogger(GenericDaoImpl.class);
    
    // parametrized type of a concrete class
    private Class<T> type;
    
    /**
     * Represents a JPA connection to the object database, we can uses 
     * it for CRUD operations (for interacting with the persistence context)
     */
    @PersistenceContext
    protected EntityManager manager;
    
    @SuppressWarnings("unchecked")
    public GenericDaoImpl() {
        Type t = getClass().getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType) t;
        type = (Class<T>) pt.getActualTypeArguments()[0];
    }
    
    @Override
    public long count() {
        String entity = type.getSimpleName();
        final StringBuilder queryString = 
                new StringBuilder("select count(ent) from ".concat(entity).concat(" ent"));
        // create an instance of Query for executing a Java Persistence query language statement
        final Query query = manager.createQuery(queryString.toString());
        // execute a SELECT query that returns a single untyped result
        return (Long) query.getSingleResult();
    }
    
    @Override
    public T find(final Object id) {
        return manager.find(type, id);
    }
    
    @Override
    public T create(T t) {
        manager.persist(t);
        return t;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public List<T> getAll() {
        Query query = manager.createQuery("from ".concat(type.getName()));
        return query.getResultList();
    }
    
    @Override
    public T update(T t) {
        return manager.merge(t);
    }
    
    @Override
    public void delete(Object id) {
        manager.remove(manager.getReference(type, id));
    }
}
     Before we create the next DAO layer we should bind it with some entity. User class represents a JPA entity which is used by Hibernate and it annotated with JAXB annotations so we can use it via REST. Class Users is a wrapper for the users class and it also contain JAXB annotations.
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@Entity
@Table(name = "user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer id;
    private String name;
    private Integer age;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}
     Using Hibernate with Spring, standard JPA annotations work very well.
@Entity - specifies that the class is an entity, we tell Hibernate that this class represent an object that we can persist.
@Table(name = "user") - specifies the primary table for the annotated entity.
@GeneratedValue(strategy = GenerationType.SEQUENCE) - provides for the specification of generation strategies for the values of primary keys. GenerationType.SEQUENCE - Indicates that the persistence provider must assign primary keys for the entity using a database sequence.
     Class Users is a wrapper for the users class and it also contain JAXB annotations.
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Users {
    private List<User> users;

    @XmlElement(name = "user")
    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}
     Now we’re ready to use our abstraction DAO layer in concrete DAO implementation. Time to create an entity interface that extend GenericDao and it’s implementation. UserDao without additional methods but we can add them if needed.
/**
 * Interface for specific User entity because we should tell which entity is acceptable. 
 * 
 * @author Dmitry Nikolaenko
 *
 */
public interface UserDao extends GenericDao<User> {
}
     UserDaoImpl extends generic DAO implementation and implement UserDao interface. @Repository annotation indicates that an annotated class is a "Repository", originally defined by Domain-Driven Design as "a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects". Also we can use @Component annotation instead.
/**
 * Implementation of Generic DAO.
 * 
 * @author Dmitry Nikolaenko
 */
@Repository
public class UserDaoImpl extends GenericDaoImpl<User> implements UserDao {
}
The Service Layer
/**
 * Service for User entity.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public interface UserService {
    public User create(User user);
    public void delete(Integer id);
    public User update(User user);
    public User find(Integer id);
    public List<User> getAll();
    public Long count();
}
     All of the method are transactional, thanks to the @Transactional annotation. @Autowired marks a method as to be autowired by Spring's dependency injection facilities and we inject a user dao implementation.
/**
 * Implementation of the UsersService.
 * 
 * @author Dmitry Nikolaenko
 *
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    @Transactional(readOnly = false)
    public User create(User user) {
        return userDao.create(user);
    }

    @Override
    @Transactional(readOnly = false)
    public void delete(Integer id) {
        userDao.delete(id);
    }

    @Override
    @Transactional(readOnly = false)
    public User update(User user) {
        return userDao.update(user);
    }

    @Override
    @Transactional(readOnly = false)
    public User find(Integer id) {
        return userDao.find(id);
    }

    @Override
    @Transactional(readOnly = true)
    public List<User> getAll() {
        return userDao.getAll();
    }

    @Override
    @Transactional(readOnly = true)
    public Long count() {
        return userDao.count();
    }
}
      Well, build a RESTful using Spring Framework.
     Configure servlet dispatcher to handle our request in web.xml. And hand this Servlet to handle incoming requests starting with "/rest/*". We use the ContextConfigLocation init parameter to change the location for the main config XML file for the Spring Application Context that is loaded by the DispatcherServlet.
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
    <display-name>Restful Web Application</display-name>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring-beans.xml</param-value>
    </context-param>

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath*:log4j.properties</param-value>
    </context-param>
    
    <!-- Processes application requests -->
    <servlet>
        <servlet-name>servlet-context</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>servlet-context</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
</web-app>
     Configure the datasource and persistence unit via Spring and using Hibernate as the JPA provider. The spring-beans.xml file contains different spring mappings such as transaction manager, entity manager factory bean, data source etc. 
 - dataSource bean - java datasource used to connect to contact manager database, we should provide driver class name, username, password etc
 - entityManagerFactory bean - the LocalContainerEntityManagerFactoryBean gives full control over EntityManagerFactory configuration. LocalContainerEntityManagerFactoryBean will create a PersistenceUnitInfo based on the persistence.xml file. This is really great JPA option, allowing for flexible local configuration within the application. It supports links to an existing JDBC DataSource, supports both local and global transactions.
 - transactionManager bean - Transaction manager for EntityManagerFactory
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- Configure the JDBC datasource -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
        <property name="url" value="jdbc:hsqldb:mem:testdb" />
        <property name="username" value="sa" />
        <property name="password" value="" />
    </bean>
    
    <!-- Configure the entity manager -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
        <property name="persistenceUnitName" value="spring-persistenceUnit" />
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- Transaction manager for EntityManagerFactory -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    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">
    
    <persistence-unit name="spring-persistenceUnit">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.dmitrynikol.model.User</class>
        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="create" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>
     Create a servlet context file servlet-context.xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <!-- Enabling Spring beans auto-discovery,  
         scans the classpath of this application for annotation to deploy the bean.
         It help us to find class annotated with @Controller, 
         @Service, @Configuration etc annotation. -->
    <context:component-scan base-package="com.dmitrynikol" />
    
    <!-- Enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Enabling Spring MVC configuration through annotations. 
         Configures the @Controller programming model -->
    <mvc:annotation-driven />
</beans>
     UserRestService represent a class that will be manipulated by different HTTP methods. The class has been annotated with the @Controller annotation, it means that this is Spring MVC controller able to handling web requests. @RequestMapping annotation mapping web requests onto our REST class that handles path "/users". All methods has been annotated also with @RequestMapping annotation for handling different requests. 
     For example, @RequestMapping(method = RequestMethod.POST) will be invoked on the post request. We annotate returning Java object with @ResponseBody annotation which indicates that a method return value should be bound to the web response body.
/**
 * Represent a class that will be manipulated by different HTTP methods.
 * 
 * @author Dmitry Nikolaenko
 *
 */
@Controller
@RequestMapping("/users")
public class UserRestService {
    @Autowired
    private UserService userService;
    
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public Users loadUsers() {
        Users users = new Users();
        users.setUsers(userService.getAll());
        return users;
    }
    
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseBody
    public User updateUser(@PathVariable(value = "id") Integer id, @RequestBody User user) {
        return userService.update(user);
    }
    
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public User addUser(@RequestBody User user) {
        return userService.create(user);
    }
    
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public void deleteUser(@PathVariable(value = "id") Integer id) {
        userService.delete(id);
    }
    
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    public User findUser(@PathVariable(value = "id") Integer id) {
        return userService.find(id);
    }
}
     Here is a link to the Maven POM file to build the above project.
     At this point, we’ve got a final RESTful application, the next thing to do is write a unit and integration test for service layer. But I'll describe this in the next article.
     The code for this and the next article is available on Github.

понедельник, 23 сентября 2013 г.

Testing RESTful web services

     In my previous article I’ve introduced RESTful web services with JAX-RS library called Jersey, JAXB and Maven. This post show you how to test it with Jersey Test Framework. Let's look at the tools that can help us with that. 
     For testing your RESTful web services with a different request methods, you need a tool that allows you to specify which method to use. So, let’s see to the next popular HTTP client tools.
 - Curl(it’s a command line tool for transferring data via URL). Curl helps you easy to change the HTTP verb that you are using. HTTP GET is the default verb used by curl.
# See all the users in the system on third page 
> curl -X GET http://localhost:8080/RESTfulApp/rest/user/all?page=3
# Create and save new user 
> curl -X POST http://localhost:8080/RESTfulApp/rest/user/create
# Get the information of the user 
> curl -X GET http://localhost:8080/RESTfulApp/rest/user/id/12345
# Update user information 
> curl -X PUT http://localhost:8080/RESTfulApp/rest/user/id/12345
# Delete user
> curl -X DELETE http://localhost:8080/RESTfulApp/rest/user/id/12345
 - RESTClient(a debugger for RESTful web services for verifying the APIs output)
     And very often to make sure that everything works correctly writing unit and integration tests. For that purposes let’s look to the next candidates:
 - REST-assured(Java DSL for easy testing a REST services)
 - Jersey Test Framework(allow to run tests on different lightweight containers, like Embedded glassfish, grizzly web server and lightweight HTTP server)
     Let's try to increase the quality and productivity of the application using Jersey Test Framework.
     First we are adding necessary dependencies to the pom.xml file:
  <dependencies>
    .....
    <dependency>
      <groupId>com.sun.jersey.jersey-test-framework</groupId>
      <artifactId>jersey-test-framework-core</artifactId>
      <version>1.9</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey.jersey-test-framework</groupId>
      <artifactId>jersey-test-framework-external</artifactId>
      <version>1.9</version>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    .....
  </dependencies>
     Well, our UserServiceTest extends JerseyTest class and override the configure() method, where you supply the same information that you provide in web.xml file. WebResources is defined an encapsulation of a Web resource capable of building requests to send to the Web resource and processing responses returned from the Web resource.
/**
 * Integration test for UserService service.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class UserServiceTest extends JerseyTest {
    private final WebResource webResource = client().resource("http://localhost:8080/RESTfulApp/rest");

    @Override
    protected AppDescriptor configure() {
        return new WebAppDescriptor.Builder().build();
    }
    
    @Test
    public void testGetStub() {
        String result = webResource.path("/user/stub").get(String.class);
        Assert.assertEquals("stub", result);
    }
    
    @Test
    public void testCreateUser() throws JSONException {
        final User testUser = new User("123", "Tom", "Jenkins", "tom.jenkins@gmail.com");
        final ClientResponse response = webResource.path("/user/create").
                type(MediaType.APPLICATION_JSON).
                accept(MediaType.APPLICATION_JSON).
                post(ClientResponse.class, testUser);
        final User user = response.getEntity(new GenericType<User>(){});
        
        Assert.assertEquals("123", user.getId());
        Assert.assertEquals("Tom", user.getFirstName());
        Assert.assertEquals("Jenkins", user.getLastName());
        Assert.assertEquals("tom.jenkins@gmail.com", user.getEmail());
        // check HTTP status code
        Assert.assertEquals(200, response.getStatus());
    }
    
    @Test
    public void testDeleteUser() {
        final ClientResponse response = webResource.path("/user/id/12345").
                type(MediaType.APPLICATION_JSON).delete(ClientResponse.class);
        Assert.assertEquals(200, response.getStatus());
    }
    
    @Test
    public void testUpdateUser() {
        User testUser = new User("12345", "Tom", "Jenkins", "tom.jenkins@gmail.com");
        final ClientResponse response = webResource.path("/user/id/12345").
                type(MediaType.APPLICATION_JSON).
                accept(MediaType.APPLICATION_JSON).
                put(ClientResponse.class, testUser);
        final User user = response.getEntity(new GenericType<User>(){});
        
        Assert.assertEquals("12345", user.getId());
        Assert.assertEquals("Tom", user.getFirstName());
        Assert.assertEquals("Jenkins", user.getLastName());
        Assert.assertEquals("tom.jenkins@gmail.com", user.getEmail());
    }
    
    @Test
    public void testGetAllUsers1() throws JSONException {
        final ClientResponse response = webResource.path("/user/all").
                accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
        final JSONArray resultArray = response.getEntity(JSONArray.class);
        Assert.assertEquals(200, response.getStatus());
    }
    
    /**
     * Jersey using JAXB for the marshalling/unmarshalling process, 
     * and JAXB JSON processor is not standard.
     * So, I chose Jackson instead of JAXB.
     * 
     * @throws JSONException
     */
    @Test
    public void testGetAllUsers2() throws JSONException {
        ClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getClasses().add(JacksonJsonProvider.class);
        Client client = Client.create(clientConfig);
        final List<User> result = client.resource("http://localhost:8080/RESTfulApp/rest/user/all").
                get(new GenericType<List<User>>(){});
        
        final User user = result.get(0);
        Assert.assertEquals("1", user.getId());
        Assert.assertEquals("Tom", user.getFirstName());
        Assert.assertEquals("Jenkins", user.getLastName());
        Assert.assertEquals("tom.jenkins@gmail.com", user.getEmail());
        Assert.assertFalse(result.isEmpty());
    }
    
    @Test
    public void testGetUserById1() throws JSONException {
        JSONObject json = webResource.path("/user/id/12345").get(JSONObject.class);
        Assert.assertEquals("12345", json.get("id"));
        Assert.assertEquals("Max", json.get("firstName"));
        Assert.assertEquals("Liano", json.get("lastName"));
        Assert.assertEquals("maxliano@gmail.com", json.get("email"));
    }
    
    @Test
    public void testGetUserById2() throws JSONException {
        final ClientResponse response = webResource.path("/user/id/12345").
                accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
        // GenericType<Type> restore and map into User.java class
        final User user = response.getEntity(new GenericType<User>(){});
        
        Assert.assertEquals("12345", user.getId());
        Assert.assertEquals("Max", user.getFirstName());
        Assert.assertEquals("Liano", user.getLastName());
        Assert.assertEquals("maxliano@gmail.com", user.getEmail());
        // check HTTP status code
        Assert.assertEquals(200, response.getStatus());
    }
}
     The result of the tests will be displayed in the JUnit view and as we see we get a green bar.
    The complete source code to this example is available on Github. Have fun with the code!

Building RESTful web services with JAX-RS(Jersey)

     In this article I will focuses on explaining the REST architecture and we will build a simple RESTfull application with JAX-RS library called Jersey.
     Representational State Transfer or REST is a simple way to organize interactions between independent system. It can be used wherever HTTP can. One of the idea of the REST that application should have specific purposes, like retrieving, adding, deleting or updating data(HTTP service request). And actions should be performed no more than one at a time.
 - POST - create a new resource(resource is contained in the body of the POST request)
 - GET - retrieves a resource from the server
 - PUT - updates the state of a known resource
 - DELETE - deletes a resource on the server
      Here’re some HTTP response codes which are often used with REST.
 - 200 ok - indicates that request was successful
 - 201 created - request was successful and a resource was created
 - 400 bad request - request was malformed
 - 401 unauthorized - must perform authentication before accessing the resource
 - 404 not found - resource could not be found
 - 500 internal server error
     First, create a standard web project from maven archetype:
      mvn archetype:generate -DgroupId=com.dmitrynikol.rest -DartifactId=RESTfulApp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
Now run a command to add dependencies in project, eclipse can resolve them, we just convert maven based Java project into to support Eclipse IDE.
     mvn eclipse:eclipse -Dwtpversion=2.0
After that you will see two new files “.classpath” and “.project”. And now you can easily import a project into your Eclipse workspace. So, now we have a maven web stub project.
     Now, let’s make sure that we have all dependencies that we need in Maven pom.xml file.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dmitrynikol.rest</groupId>
  <artifactId>RESTfulApp</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>RESTfulApp Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  <dependencies>
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-server</artifactId>
      <version>1.9</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>1.9</version>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey.jersey-test-framework</groupId>
      <artifactId>jersey-test-framework-core</artifactId>
      <version>1.9</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey.jersey-test-framework</groupId>
      <artifactId>jersey-test-framework-external</artifactId>
      <version>1.9</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <build>
    <finalName>RESTfulApp</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <configuration>
          <downloadSources>true</downloadSources>
          <downloadJavadocs>true</downloadJavadocs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
     POJO class User object that mapping to JSON via JAXB with @XmlRootElement annotation.
/**
 * A typical User entity. 
 * XmlRootElement annotation enable JAXB to convert to and from JSON  
 * 
 * @author Dmitry Nikolaenko
 *
 */
@XmlRootElement
public class User {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    
    public User(){}
    
    public User(String id, String firstName, String lastName, String email) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }
    
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}
     Time to create UserService class, that represent a Jersey resources as an POJO and will be manipulated by different HTTP methods. Service class contains many annotations to create different behaviours.
And Jersey provides a set of Java annotations that can be used to define the web service structure.
 - @Path - configure the URL pattern the class will handle
 - @Post, @GET, @PUT and @DELETE - method will answer to the HTTP POST, GET, PUT and DELETE request
 - @Produces - specifies the MIME type of the response that is returned to the client
 - @Consumes - specifies the content type that the service will accept as input
 - @QueryParam - mark a field that will be extracted from the URL in a GET request
 - @DefaultValue - mark the value that will be used by default
 - @PathParam - mark a field that will be extracted from a field in the URL path
/**
 * UserService represent a Jersey resources that will be 
 * manipulated by different HTTP methods.
 * 
 * @author Dmitry Nikolaenko
 *
 */
@Path("/user")
public class UserService {
     /**
     * Method handling HTTP GET requests, returned object will be
     * sent to the client as "text/plain" media type.
     * 
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/stub")
    public String getStub() {
        return "stub";
    }
    
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/all")
    public Response getAllUsers(@QueryParam("page") @DefaultValue("1") final String page) {
        // # See all the users in the system 
        // > curl -X GET http://localhost:8080/RESTfulApp/rest/user/all?page=3
        List<User> users = new ArrayList<User>();
        final User user1 = new User("1", "Tom", "Jenkins", "tom.jenkins@gmail.com");
        final User user2 = new User("2", "Red", "Balloon", "red.balloon@gmail.com");
        users.add(user1);
        users.add(user2);
        return Response.ok(users).build();
    }
    
    @POST
    @Path("/create")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createUser(final User user) throws URISyntaxException {
        // # Create and save new user
        // > curl -X POST http://localhost:8080/RESTfulApp/rest/user/create
        return Response.ok(user).build();
    }
    
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/id/{id}")
    public Response getUserById(@PathParam("id") final String id) throws URISyntaxException {
        // # Get the information of the user
        // > curl -X GET http://localhost:8080/RESTfulApp/rest/user/id/12345
        final User user = new User("12345", "Max", "Liano", "maxliano@gmail.com");
        return Response.ok(user).build();
    }
    
    // POST is used create a new resource, PUT method updates the state of a known resource. 
    @PUT
    @Path("/id/{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response updateUser(@PathParam("id") final String id, final User user)  
     throws URISyntaxException {
        // # Update user information
        // > curl -X PUT http://localhost:8080/RESTfulApp/rest/user/id/12345
        return Response.ok(user).build();
    }
    
    @DELETE
    @Path("/id/{id}")
    public Response deleteUser(@PathParam("id") final String id) throws URISyntaxException {
        // create a new ResponseBuilder with an OK status and appropriate a Response instance
        // Delete user
        // > curl -X DELETE http://localhost:8080/RESTfulApp/rest/user/id/12345
        return Response.ok().entity("User with ".concat(id).concat(" is deleted successfully")).build();
    }
}
     And don’t forget to add com.sun.jersey.api.json.POJOMappingFeature to web.xml file that integrate JSON with Jersey. It will make Jersey support JSON/object mapping.
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    
    <display-name>Restful Web Application</display-name>
    
    <servlet>
        <servlet-name>Jersey REST Servlet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
             <param-name>com.sun.jersey.config.property.packages</param-name>
             <param-value>com.dmitrynikol.services</param-value>
        </init-param>
        <!-- integrate JSON with Jersey. It will make Jersey support JSON/object mapping -->
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>Jersey REST Servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>
     That’s all. Now we’re ready to start the rest service with tomcat instance via command - mvn tomcat:run The complete source code to this example is available on Github. Have fun with the code!

воскресенье, 22 сентября 2013 г.

Testing services with DBUnit and HyperSQL

     Let’s assume that you have a tests that use database and you want to set up the database to be sure about the state before each test run. Otherwise we will get a headaches to maintain a lot of test manually(different configuration and database contents), because we want that out test always run successful. We need a testing tool that provides easy way to initialise database and create/restore consistent state for our test. DBUnit will help us with that. It’s a great integration tool that can export and import your database data to and from XML datasets.
     This post shows how easily can be used DBUnit and HSQL to write database tests and testing your persistence layer services. So, getting started. Suppose that we have a service UserService that returns User objects from the database. And we want to test services method to make sure that everything is working properly.
     Well, the plan is to initialize the database before execute test, execute the database schema and read the DBUnit xml file. And then build the IDataSet that represents a collections of tables.
jdbcConnection = DriverManager.getConnection("jdbc:hsqldb:mem:hsql://localhost/test;user=sa");
dbConnection = new DatabaseConnection(jdbcConnection, "create_database.sql");
dbConnection.getConfig().setProperty(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
.....
IDataSet  dataSet = new XmlDataSet(getClass().getResourceAsStream("hsqldb_users.dbunit.xml"));
     The create_database.sql schema file look like this.
create table if not exist users (
    id varchar(30) not null,
    first_name varchar(50) not null,
    last_name varchar(50) not null,
    email varchar(30),
    primary key (id)
);
     And here is a simple dataset xml file.
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <table name="users">
        <column>id</column>
        <column>first_name</column>
        <column>last_name</column>
        <column>email</column>
        <row>
            <value>123</value>
            <value>Tom</value>
            <value>Jenkins</value>
            <value>tom.jenkins@gmail.com</value>
        </row>
        <row>
            <value>456</value>
            <value>Red</value>
            <value>Balloon</value>
            <value>red.balloon@gmail.com</value>
        </row>
        <row>
            <value>789</value>
            <value>Max</value>
            <value>Liano</value>
            <value>maxliano@gmail.com</value>
        </row>
    </table>
</dataset>
     Now, we are ready to test our service methods. We can get the necessary data table as an ITable object from IDataSet.
@Test
public void testFindUserByid() throws Exception {
    final ITable users = getDataSet().getTable("users");
    
    String firstName = users.getValue(0, "first_name").toString(); // Tom
    String lastName = users.getValue(0, "last_name").toString(); // Jenkins
    String email = users.getValue(0, "email").toString(); // tom.jenkins@gmail.com
    
    User user = userService.findUserByid("123");
    
    Assert.assertEquals(firstName, user.getFirstName());
    Assert.assertEquals(lastName, user.getLastName());
    Assert.assertEquals(email, user.getEmail());
}

@Test
public void testFindUserByEmail() throws Exception {
     final ITable users = getDataSet().getTable("users");
     
     String id = users.getValue(0, "id").toString(); // 123
     String firstName = users.getValue(0, "first_name").toString(); // Tom
     String lastName = users.getValue(0, "last_name").toString(); // Jenkins
     
     User user = userService.findUserByEmail("tom.jenkins@gmail.com");
     
     Assert.assertEquals(id, user.getId());
     Assert.assertEquals(firstName, user.getFirstName());
     Assert.assertEquals(lastName, user.getLastName());
}
     And here is a Maven pom.xml file with necessary dependencies.
<dependencies>
    .....
    <dependency>
      <groupId>org.dbunit</groupId>
      <artifactId>dbunit</artifactId>
      <version>2.4.9</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.3.0</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    .....
</dependencies>
     Finally, the complete DbUnitDatabaseTest file with @Before and @After methods which will be called before and after test accordingly and other important pieces of code.
import java.sql.Connection;
import java.sql.DriverManager;

import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.XmlDataSet;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Example database test with DBUnit and HSQLDB.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class DbUnitDatabaseTest {
    private Connection jdbcConnection;
    private IDatabaseConnection dbConnection;
    private IDataSet dataSet;
    
    @Before
    public void setUp() throws Exception {
        Thread.sleep(1000L);
        Class.forName("org.hsqldb.jdbcDriver");
        jdbcConnection = DriverManager.getConnection("jdbc:hsqldb:mem:hsql://localhost/test;user=sa");
        dbConnection = new DatabaseConnection(jdbcConnection, "create_database.sql");
        dbConnection.getConfig().setProperty(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true);
    }

    @After
    public void tearDown() throws Exception {
        dbConnection.close();
        jdbcConnection.close();
    }
    
    private IDataSet getDataSet() throws Exception {
     if (dataSet == null) {
      dataSet = new XmlDataSet(getClass().getResourceAsStream("hsqldb_users.dbunit.xml"));
     }
     return dataSet;
    }

    @Test
    public void testFindUserByid() throws Exception {
        final ITable users = getDataSet().getTable("users");
        
        String firstName = users.getValue(0, "first_name").toString(); // Tom
        String lastName = users.getValue(0, "last_name").toString(); // Jenkins
        String email = users.getValue(0, "email").toString(); // tom.jenkins@gmail.com
        
        User user = userService.findUserByid("123");
        
        Assert.assertEquals(firstName, user.getFirstName());
        Assert.assertEquals(lastName, user.getLastName());
        Assert.assertEquals(email, user.getEmail());
    }
    
    @Test
    public void testFindUserByEmail() throws Exception {
         final ITable users = getDataSet().getTable("users");
      
         String id = users.getValue(0, "id").toString(); // 123
         String firstName = users.getValue(0, "first_name").toString(); // Tom
         String lastName = users.getValue(0, "last_name").toString(); // Jenkins
         
         User user = userService.findUserByEmail("tom.jenkins@gmail.com");
         
         Assert.assertEquals(id, user.getId());
         Assert.assertEquals(firstName, user.getFirstName());
         Assert.assertEquals(lastName, user.getLastName());
    }
}
     Also example can be found on Github with all additional files. So, keep calm and write code :)

суббота, 14 сентября 2013 г.

Pagination and sorting using JSP and Servlets

     This article explains how to build application with pagination and data sorting using only JSP and Servlets. I will describe details about pagination engine, the best practice for database connection, what is Data Transfer Object (DAO) and Transfer Object, how to write servlet and bind it with JSP. Only one jstl.jar you need for project and it should be placed on the WEB-INF/lib directory.
     In this example we will display a list of product’s details like name and price that is bind with appropriate group. Left panel contains a list of group, right panel contains a list of product of the selected group. Near the name of each group display a products count. Some of group can be empty, other contains a thousand of products. Thats why we should display not more that 10 products on the page.
     It’s necessary to show the current page and navigation elements for moving to the next and previous page. Also we will add sorting for products column in ascending and descending order. If the user clicks on the header column(product name or price) the first time that column should be sorted in ascending order and if the action is repeated on the same header column then the column should be sorted in descending order.
     A little bit about pagination and what method we will choose? In our case pagination means that large document will be breaking into separate pages for viewing. Basically it’s a way of making a website with a lot of data more user-friendly and manageable.
     There are different ways of pagination. First way, not very good as for me, based on getting all records at once. Later when user needs result, some part of data can be retrieved from the cache instead of querying the database to fetch the next set of results. The negative side of this approach is that the data becomes stale. And also fetching a lot of data from database requires many resources(CPU and memory). Nobody likes a slow website, faster is always better. And the second way more interesting approach. We get a range of records every time we need and display it to the user, just limit the result of data that we need to display. This approaches solves a lot of problems. And we will build application that way.
     This example uses two tables Group and Product. Here is the link to the mysql database dump file. Well, let’s write a transfer object classes that will encapsulates our business data.
/**
 * A typical Group entity.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class Group {
    private int groupId;
    private String groupName;
    private int productCountOfGroup;
    
    public int getGroupId() {
        return groupId;
    }
    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }
    public String getGroupName() {
        return groupName;
    }
    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }
    public int getProductCountOfGroup() {
        return productCountOfGroup;
    }
    public void setProductCountOfGroup(int productCountOfGroup) {
        this.productCountOfGroup = productCountOfGroup;
    }
}
/**
 * A typical Product entity.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class Product {
    private int productId;
    private String productName;
    private int groupId;
    private int productPrice;
    
    public int getProductId() {
        return productId;
    }
    public void setProductId(int productId) {
        this.productId = productId;
    }
    public String getProductName() {
        return productName;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }
    public int getGroupId() {
        return groupId;
    }
    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }
    public int getProductPrice() {
        return productPrice;
    }
    public void setProductPrice(int productPrice) {
        this.productPrice = productPrice;
    }
}
     Connection factory help us to make connection to the database. And of course it’s a singleton.
/**
 * The factory used to create an instance of Connection.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class ConnectionFactory {
    String url = "jdbc:mysql://localhost/store";
    String user = "root";
    String password = "root";
    String driverClass = "com.mysql.jdbc.Driver";
    
    private static ConnectionFactory instance = null;

    private ConnectionFactory() {
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * Gets the singleton instance of the factory.
     * 
     * @return the singleton instance
     */
    public static ConnectionFactory getInstance() {
        if (instance == null) {
            instance = new ConnectionFactory();
        }
        return instance;
    }

    /**
     * Creates a new Connection.
     * 
     * @return the new Connection
     * @throws SQLException if an error occurs during creating a connection
     * @throws ClassNotFoundException if an error occurs during creating a connection
     */
    public Connection getConnection() throws SQLException, ClassNotFoundException {
        Connection connection = DriverManager.getConnection(url, user, password);
        return connection;
    }
}
Data Access Object or DAO encapsulates database operations.
/**
 * DAO for the Group entity.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class GroupDAO {
    private Connection connection;
    private Statement stmt;
    
    public GroupDAO() {}
    
    /**
     * Method return all group in alphabetical order.
     * Entity of the group contains a number of the products and an unique ID.
     * 
     * @return list of groups
     */
    public List<Group> viewAllGroup() {
     String query = "SELECT group_name, p_group.group_id, COUNT(product_id) as product_group_count " +
           "FROM product RIGHT JOIN p_group ON product.group_id=p_group.group_id " +
           "GROUP BY group_name";
     List<Group> list = new ArrayList<Group>();
        Group group;
        try {
            connection = ConnectionFactory.getInstance().getConnection();
            stmt = connection.createStatement();

            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {
                group = new Group();

                group.setGroupName(rs.getString("group_name"));
                group.setGroupId(rs.getInt("group_id"));
                group.setProductCountOfGroup(rs.getInt("product_group_count"));

                list.add(group);
            }
            rs.close();

        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null)
                    stmt.close();
                if (connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return list;
    }
}
/**
 * DAO for the Product entity.
 * 
 * @author Dmitry Nikolaenko
 *
 */
public class ProductDAO {
    private Connection connection;
    private Statement statement;
    private int productCount;
 
    public ProductDAO() { }
 
    /**
     * Query used to return the products of group.
     * The method allows to get sorted list of products by 
     * name or price in one direction or opposite.
     * 
     * @param group the group of concrete products
     * @param offset value allow to retrieve just a portion of the rows
     * @param recordsOnPage the amount of data per request
     * @param sorting the way of the data sort
     * @param sortingType possible sorting way, for now it's sort by name or price
     * @return list of products
     */
    public List<Product> viewAllProducts(int group, int offset, int recordsOnPage, 
      Sorting sorting, SortingType sortingType) {
     StringBuilder queryBuilder = new StringBuilder();
     queryBuilder.append("SELECT SQL_CALC_FOUND_ROWS * FROM product ");
     if (group > 0) {
      queryBuilder.append("where group_id=").append(group);
     }
     if (!Sorting.DEFAULT.equals(sorting)) {
      queryBuilder.append(" ORDER BY ").append("product_").
       append(sortingType.getValue()).append(" ").append(sorting.getType());
     } 
     queryBuilder.append(" limit ").append(offset).append(", ").append(recordsOnPage);
     
        List<Product> list = new ArrayList<Product>();
        Product product = null;
        try {
            connection = ConnectionFactory.getInstance().getConnection();
            statement = connection.createStatement();

            ResultSet rs = statement.executeQuery(queryBuilder.toString());
            while (rs.next()) {
                product = new Product();
                product.setProductName(rs.getString("product_name"));
                product.setProductPrice(rs.getInt("product_price"));

                list.add(product);
            }
            rs.close();

            rs = statement.executeQuery("SELECT FOUND_ROWS()");
            if (rs.next()) {
                this.productCount = rs.getInt(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (statement != null)
                    statement.close();
                if (connection != null)
                    connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    /**
     * Return the total count of products for a certain group.
     */
    public int getProductCount() {
        return productCount;
    }
}   
     Servlet processes different request parameters like group of products, current page, desc/asc sorting. Also we are storing a lot of attributes in the request scope and then forwarding request to a JSP. Here is the code of Servlet.
/**
 * Servlet implementation class ProductServlet.
 * 
 * @author Dmitry Nikolaenko
 *
 */
@WebServlet("/ProductServlet")
public class ProductServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
    
    private Sorting sortedPriceColumn = Sorting.ASC;
    private Sorting sortedNameColumn = Sorting.ASC;
    private Sorting activeSortingWay = Sorting.ASC;
    private SortingType activeSortingType = SortingType.NAME;
    
    public ProductServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        int activeGroupId = 0;
        int currentPage = 1;
        int recordsOnPage = 10;
        
        if (request.getParameter("group") != null) {
         activeGroupId = Integer.parseInt(request.getParameter("group"));
        }
        if (request.getParameter("page") != null) {
            currentPage = Integer.parseInt(request.getParameter("page"));
        }
        
        if (request.getParameter("desc") != null) {
         activeSortingWay = Sorting.DESC;
        } else if (request.getParameter("asc") != null) {
         activeSortingWay = Sorting.ASC;
        } 
        else {
         activeSortingWay = Sorting.DEFAULT;
        }
        
        // reverse sort direction logic, for now it's only two possible way - sort by name or price
        String sortParam = request.getParameter(activeSortingWay.getType().toLowerCase());
        if (sortParam != null) {
         activeSortingType = SortingType.safeValueOf(sortParam);
         // verification for change the sorting of product name or product price 
         if (SortingType.NAME.equals(activeSortingType)) {
          // check for the correct change sort direction
          if (sortedNameColumn.equals(activeSortingWay)) {
           sortedNameColumn = Sorting.reverse(sortedNameColumn);
          }
         } else if (SortingType.PRICE.equals(activeSortingType)) {
          // check for the correct change sort direction
          if (sortedPriceColumn.equals(activeSortingWay)) {
           sortedPriceColumn = Sorting.reverse(sortedPriceColumn);
          }
         }
        }
        
        GroupDAO groupDao = new GroupDAO();
        List<Group> groups = groupDao.viewAllGroup();
        request.setAttribute("groupList", groups);
        
        ProductDAO dao = new ProductDAO();
        List<Product> list = dao.viewAllProducts(activeGroupId, (currentPage-1) * recordsOnPage, 
          recordsOnPage, activeSortingWay, activeSortingType);
        int productCount = dao.getProductCount();
        int numberOfPages = (int) Math.ceil(productCount * 1.0 / recordsOnPage);
        
        request.setAttribute("productList", list);
        request.setAttribute("numberOfPages", numberOfPages);
        request.setAttribute("currentPage", currentPage);
        request.setAttribute("activeGroupId", activeGroupId);
        request.setAttribute("productCount", productCount);
        
        request.setAttribute("activeSortingWay", activeSortingWay.getType().toLowerCase());
        request.setAttribute("activeSortingType", activeSortingType.getValue());
        
        request.setAttribute("sortedPriceColumn", sortedPriceColumn.getType().toLowerCase());
        request.setAttribute("sortedNameColumn", sortedNameColumn.getType().toLowerCase());
        
        RequestDispatcher view = request.getRequestDispatcher("displayProduct.jsp");
        view.forward(request, response);
    }
}
     Only one JSP page that retrieves the attributes from request and display the result. Easier to nowhere! :)
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Group and products</title>
<style type="text/css">
  #div0{display:table-cell;width:50%;}
  #div1{float:left;text-align:center;display:table-cell;background-color:#9C8DEB}
  #div2{float:left;text-align:center;display:table-cell;background-color:#41EC88}
  #div3{width:361px; overflow:auto;background-color:yellow;}
</style>
</head>
<body>
    <div id="div0">
        <div id="div1">
            <table border="1" cellpadding="0" cellspacing="0">
                <tr>
                    <th>GROUP_NAME</th>
                </tr>
                <c:forEach var="group" items="${groupList}">
                    <tr>
                        <td><a href="product.do?page=1&group=${group.groupId}">
                                ${group.groupName} (${group.productCountOfGroup})
                        </a></td>
                    </tr>
                </c:forEach>
            </table>
        </div>
        <div id="div2">
            <table border="1" cellpadding="4" cellspacing="0">
                <tr>
                 <th><a href="product.do?page=1&group=${activeGroupId}&${sortedNameColumn}=name">
                     PRODUCT_NAME
                    </a></th>
                    <th><a href="product.do?page=1&group=${activeGroupId}&${sortedPriceColumn}=price">
                     PRODUCT_PRICE
                    </a></th>
                </tr>
         
                <c:forEach var="product" items="${productList}">
                    <tr>
                        <td>${product.productName}</td>
                        <td>${product.productPrice}</td>
                    </tr>
                </c:forEach>
            </table>
        </div>
    </div>
 
  <div> 
   <c:if test="${numberOfPages > 1}">
       <div style="float: left;">
              <!--For displaying previous link except for the 1st page -->
                <c:if test="${currentPage != 1}">
                    <td><a href="product.do?page=${currentPage - 1}&group=${activeGroupId}
                            &${activeSortingWay}=${activeSortingType}">Previous</a></td>
                </c:if>
            </div>
      
       <div id="div3" style="float: left;"> 
                <%--For displaying Page numbers.
                The when condition does not display a link for the current page--%>
                <table border="1" cellpadding="3" cellspacing="0">
                    <tr>
                        <c:forEach begin="1" end="${numberOfPages}" var="i">
                            <c:choose>
                                <c:when test="${currentPage eq i}">
                                    <td>${i}</td>
                                </c:when>
                                <c:otherwise>
                                    <td><a href="product.do?page=${i}&group=${activeGroupId}
                                            &${activeSortingWay}=${activeSortingType}">${i}</a></td>
                                </c:otherwise>
                            </c:choose>
                        </c:forEach>
                    </tr>
                </table>
            </div>
         
         <div style="float: left;">
                <%--For displaying Next link except for the last page --%>
                <c:if test="${currentPage lt numberOfPages}">
                    <td><a href="product.do?page=${currentPage + 1}&group=${activeGroupId}
                            &${activeSortingWay}=${activeSortingType}">Next</a></td>
                </c:if>
            </div>
        </c:if>
    </div>
</body>
</html>
     In summary, here is the project structure.
     And here you can find the package with different project screenshots.
Here is the link to the source code on Github.