Friday, July 8, 2016

My New Book SpringBoot : Learn By Example Published Today

I am happy to announce that my new book SpringBoot : Learn By Example  got published today on Leanpub.



SpringBoot : Learn By Example

What is SpringBoot?

Spring is one of the most popular Java frameworks out there to build web and enterprise application.
Spring supports variety of configuration approaches (XML, Annotations, JavaConfig etc) and properly configuring Spring applications become a bit tedious and repetitive process. To avoid these problems Spring team introduced SpringBoot to address the complexity of configuring Spring application.

SpringBoot is an opinionated approach to configure Spring based applications. SpringBoot automatically configures the application components based on various criteria like the jars you have on classpath, beans you have already configured, properties configured etc which makes it very easy to get up and running quickly.

I strongly believe that the best way to learn or teach is by using examples. This book is filled with plenty of examples explaining the concepts  in step by step manner.

Who this book is for?

If you are looking for a fast paced guide to learn how to build Spring based applications using SpringBoot this book is for you!!.

If you are a Spring developer but haven't get your hands on SpringBoot and you feel like I know the drill, just tell me how to do it in SpringBoot way..this books is what you are looking for!!!

If you are just starting to use SpringBoot and it is working great but it all looks magical and you want to understand how SpringBoot works behind the scenes..this book will definitely be helpful to you!!

If you are a seasoned Spring developer with good grasp of Spring framework concepts and you just want a fast-paced guide to learn SpringBoot quickly..sure..this book is definitely for you!!

I see lot of people asking "What is the difference between SpringMVC and SpringBoot?", "Should I use SpringBoot or SpringMVC for my next web application?" etc etc. See Here, Here and Here . The short answer is SpringBoot is nothing but Spring only..but it helps you a lot to build Spring based applications quickly. The next question would be How?. The best way to explain it is by creating an application WITHOUT SpringBoot and show how quickly you can develop the same application WITH SpringBoot.

This book explains how normally we build Spring application without SpringBoot and shows how we can build the same application using SpringBoot in much easier way so that you can correlate the concepts and see how SpringBoot increases developer productivity.

SpringBoot does so many things behind the scenes to automatically configure the application. This book explains how SpringBoot AutoConfiguration works behind the scenes in very detailed manner and show how we can create our own AutoConfiguration as well.

What this book covers?

The SpringBoot : Learn By Example book covers the concepts that we commonly use in our Spring applications.

  • What is SpringBoot and how to get started with SpringBoot?
  • How SpringBoot AutoConfiguration Works behind the scenes using @Conditional?
  • SpringBoot goodies like Logging, ConfigurationProperties, DeveloperTools
  • Working with Databases using JdbcTemplate, MyBatis, JOOQ, Spring Data JPA
  • Working with MongoDB NoSQL database
  • Developing Web Applications using SpringMVC
    • SpringBoot Web Starter awesomeness
    • Using Thymeleaf Views
    • File Uploading
    • Validation, I18N
  • Developing RESTful Services using SpringMVC and Spring Data REST
  • Consuming SpringBoot REST API from AngularJS application
  • Securing Web applications and REST API
  • Monitoring SpringBoot applications with SpringBoot Actuator
  • Testing SpringBoot applications


To get complete list of topics covered in this book please see the below Table of Contents.


Table of Contents:

1. Introduction to SpringBoot
  • Overview of Spring framework
  • Developing Web Application using SpringMVC and JPA
  • A Quick Taste of SpringBoot

2. Getting Started with SpringBoot
  • What is SpringBoot?
  • Our First SpringBoot Application

3. SpringBoot Behind the scenes
  • Exploring the Power of @Conditional
  • How SpringBoot AutoConfiguration Works?

4. Creating Custom SpringBoot Starter
  • Create twitter4j-spring-boot-starter

5. SpringBoot Essentials
  • Logging
  • Externalizing Configuration Properties
  • Developer Tools

6. Working with JdbcTemplate
  • Using JdbcTemplate without SpringBoot
  • Using JdbcTemplate with SpringBoot
  • Initializing Database
  • How to use other Connection Pooling libraries?

7. Working with MyBatis
  • Using SpringBoot MyBatis Starter

8. Working with JOOQ
  • Using SpringBoot JOOQ Starter

9. Working with JPA
  • Introducing Spring Data JPA
  • Using Spring Data JPA with SpringBoot

10. Working with MongoDB
  • Introducing MongoDB
  • Getting Started with MongoDB using Mongo Shell
  • Talking to MongoDB using Spring Data Mongo

11. Web Applications with SpringBoot
  • Developing Web Application using SpringBoot
  • Using Tomcat, Jetty, Undertow Embedded Servlet Containers
  • Customizing SpringMVC configuration
  • SpringBoot web application as deployable war
  • SpringBoot Supporting View Templates
  • Working with Thymeleaf Forms
  • Data Validation
  • File Uploading
  • Using ResourceBundles for Internationalization (I18N)

12. Building REST API using SpringBoot
  • Introduction to RESTful WebServices
  • REST API using SpringMVC
  • REST API using Spring Data REST
  • Consuming REST API from AngularJS

13. Securing Web Applications using SpringBoot
  • Spring Security in SpringBoot Web Application
  • Method Level Security
  • Securing REST API using SpringSecurity

14. SpringBoot Actuator
  • Exploring Actuator Endpoints
  • Customizing Actuator Endpoints
  • Securing Actuator Endpoints
  • CORS support for Actuator Endpoints
  • Monitoring and management over JMX
  • Monitoring and management using a remote shell

15. Testing SpringBoot Applications
  • Testing Support in SpringBoot
  • Testing RESTful Services using RestTemplate
  • Testing Secured Controller/Service Methods
  • Testing with Mockito


Thank You Manuel Jordan

I would like to thank Manuel Jordan (@dr_pompeii) for reviewing the book and providing feedback which helped me a lot to improve the quality of the book content.

If  you wish please do me a favour by spreading the word on Twitter, Facebook, LinkedIn etc.
I hope you will enjoy the book :-)

Thursday, June 9, 2016

My Review of Sanjay Patel’s Spring Course

Spring is the most popular Java framework for building web and enterprise applications. There are plenty of official documentation, books, and Training Courses available for Spring framework on web.

I got an opportunity to review Sanjay Patel‘s Spring Course Material which is divided into 3 modules.

http://www.naturalprogrammer.com/spring-tutorial/

The total course is divided into 3 modules covering various aspects of web application development using Spring/SpringBoot framework.
  • Module I : Spring Framework 4 And Dependency Injection For Beginners
  • Module II : Spring Framework for the Real World
  • Module III : Spring Framework REST API Development

Module I: Spring Framework 4 and Dependency Injection For Beginners

This module covers the basics of Spring Dependency Injection mechanism using Annotations and JavaConfig based approach using SpringBoot.

The material is structured in such a way that the readers can follow the course and practice in a step by step manner.

The following topics are covered in this Module:
  • Quick and brief introduction to Dependency Injection using Spring
  • Loading and binding properties from properties files
  • Using environment profiles
  • Brief introduction about using @Conditional
  • Sending Email
There are plenty of Spring core feature are there which can’t be covered in a single book or video.But I think it would be great to cover the most commonly used features Scopes, like LifeCycle methods @PostConstruct and @PreDestroy etc.

Overall, this module will be good for people who already have some basic knowledge on Spring. But for complete beginners it may be overwhelming to understand all these Spring concepts along with SpringBoot.

Module II: Spring Framework for the Real World

This module covers the most of the aspects of web application development. The explanation is straight forward and to the point.

This module explains the concepts by implementing various use-cases of typical User Management such as SignIn, SignUp, Forgot Password, Reset Password etc.

This module covers:
  • Implementing Controllers, Request Parameters binding
  • Performing Validations, Customizing Error Messages
  • Creating custom validation constraints
  • Exception Handling
  • Brief introduction to Spring Data JPA and Transaction Handling
  • Implementing Security using Spring Security
    • Configuring Spring Security
    • Form based Login, Remember Me, Password Encryption
    • Spring Security JSP Tag libraries
  • A quick introduction to Asynchronous processing using @Async
  • Scheduling tasks using @Scheduled

This module gives hands-on experience on using many of the Spring web application development tasks. This module also contains creating many commonly used utilities such as getting I18N messages, getting login user details etc which comes very handy.

We can also use JSP with SpringBoot jar type packaging as described in Spring Boot With JSPs in Executable Jars(https://dzone.com/articles/spring-boot-with-jsps-in-executable-jars-1)

Module III: Spring Framework REST API Development

This module covers building REST API using SpringBoot. This module contains excellent material covering most of the aspects required for building a good REST API.

This module covers:
  • Creating REST Endpoints using @RestController
  • Exception handling via @ControllerAdvice
  • Environment specific properties using Profiles
  • Using @ConfigurationProperties to bind properties
  • How to catch constraint violation exceptions
  • How to use reCAPTCHA
  • Securing REST API
    • Customizing Spring Security to support REST API
    • Switching User
    • Handling CSRF and CORS
    • This module filled with lot of interesting material required to build a Secured REST API.

However, I feel like there are few important things which are not covered:                        
  • No mention of Serializing JPA entities
  • Dealing with bi-directional JPA Entity relation serialization issues
  • Token based Security
Throughout the course author explain the concepts in clear and to the point manner. Also, the course is backed by an application SpringLemon which contains all the code used in this course.
Overall this course looks very to me and I strongly recommend this course if you are looking for a fast paced Spring course.

Tuesday, March 15, 2016

SpringBoot : Working with JOOQ

In my previous article SpringBoot : Working with MyBatis  we have learned how to use SpringBoot MyBatis Starter to quickly get up and running with Spring and MyBatis. In this article we are going to learn about how to use SpringBoot JOOQ Starter.

JOOQ (Java Object Oriented Querying) is a persistence framework which embraces SQL.

JOOQ provides the following features:

  • Building Typesafe SQL using DSL API 
  • Typesafe database object referencing using Code Generation 
  • Easy to use API for Querying and Data fetching 
  • SQL logging and debugging etc etc 

SpringBoot provides a starter, spring-boot-starter-jooq, to be able to quickly integrate with JOOQ. 

In this article we will see how to use spring-boot-starter-jooq using step by step approach.

Step 1: Create SpringBoot Maven Project 

Create a SpringBoot maven based project and configure spring-boot-starter-jooq dependency.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                        http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sivalabs</groupId>
    <artifactId>springboot-jooq-demo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>

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

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jooq</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
</project>

We are going to use H2 in-memory database first, later we will see how to use MySQL.

Step 2: Create the database initialization scripts. 

We are going to create a simple database with 2 tables.
src/main/resources/schema.sql

DROP TABLE IF EXISTS POSTS;

CREATE TABLE POSTS (
  ID int(11) NOT NULL AUTO_INCREMENT,
  TITLE varchar(200) NOT NULL,
  CONTENT LONGTEXT DEFAULT NULL,
  CREATED_ON datetime DEFAULT NULL,
  PRIMARY KEY (ID)
);

DROP TABLE IF EXISTS COMMENTS;

CREATE TABLE COMMENTS (
  ID int(11) NOT NULL AUTO_INCREMENT,
  POST_ID int(11) NOT NULL, 
  NAME varchar(200) NOT NULL,
  EMAIL varchar(200) NOT NULL,
  CONTENT LONGTEXT DEFAULT NULL,
  CREATED_ON datetime DEFAULT NULL,
  PRIMARY KEY (ID),
  FOREIGN KEY (POST_ID) REFERENCES POSTS(ID)
);

We will populate some sample data using data.sql script.

 src/main/resources/data.sql

insert into posts(id, title, content, created_on) values(1, 'Post 1', 'This is post 1', '2016-01-03');
insert into posts(id, title, content, created_on) values(2, 'Post 2', 'This is post 2', '2016-01-05');
insert into posts(id, title, content, created_on) values(3, 'Post 3', 'This is post 3', '2016-01-07');

insert into comments(id, post_id, name, email, content, created_on) 
values(1, 1, 'User1', 'user1@gmail.com', 'This is comment 1 on post 1', '2016-01-07');

insert into comments(id, post_id, name, email, content, created_on) 
values(2, 1, 'User2', 'user2@gmail.com', 'This is comment 2 on post 1', '2016-01-07');

insert into comments(id, post_id, name, email, content, created_on) 
values(3, 2, 'User1', 'user1@gmail.com', 'This is comment 1 on post 2', '2016-01-07');

Step 3: Configure JOOQ Maven Codegen Plugin to generate database artifacts 

We will use Maven profiles to configure the jooq-codegen-maven configuration properties based on database type.

<profiles>
    <profile>
        <id>h2</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jooq</groupId>
                    <artifactId>jooq-codegen-maven</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>generate</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>com.h2database</groupId>
                            <artifactId>h2</artifactId>
                            <version>${h2.version}</version>
                        </dependency>
                    </dependencies>
                    <configuration>
                        <jdbc>
                            <driver>org.h2.Driver</driver>
                            <url>jdbc:h2:~/springbootjooq</url>
                        </jdbc>
                        <generator>
                            <name>org.jooq.util.DefaultGenerator</name>
                            <database>
                                <name>org.jooq.util.h2.H2Database</name>
                                <includes>.*</includes>
                                <excludes />
                                <inputSchema>PUBLIC</inputSchema>
                            </database>
                            <target>
                                <packageName>com.sivalabs.demo.jooq.domain</packageName>
                                <directory>gensrc/main/java</directory>
                            </target>
                        </generator>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>mysql</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jooq</groupId>
                    <artifactId>jooq-codegen-maven</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>generate</goal>
                            </goals>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>mysql</groupId>
                            <artifactId>mysql-connector-java</artifactId>
                            <version>${mysql.version}</version>
                        </dependency>
                    </dependencies>
                    <configuration>
                        <jdbc>
                            <driver>com.mysql.jdbc.Driver</driver>
                            <url>jdbc:mysql://localhost:3306/test</url>
                            <user>root</user>
                            <password>admin</password>
                        </jdbc>
                        <generator>
                            <name>org.jooq.util.DefaultGenerator</name>
                            <database>
                                <name>org.jooq.util.mysql.MySQLDatabase</name>
                                <includes>.*</includes>
                                <excludes />
                                <inputSchema>test</inputSchema>
                            </database>
                            <target>
                                <packageName>com.sivalabs.demo.jooq.domain</packageName>
                                <directory>gensrc/main/java</directory>
                            </target>
                        </generator>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

We have configured two profile (h2 and mysql) with appropriate JDBC configuration parameters.

We have specified to generate the code artifacts and place it in com.sivalabs.demo.jooq.domain package within gensrc/main/java directory.

We can run the maven build activating h2 or mysql profile as follows:
 mvn clean install -P h2 (or) mvn clean install -P mysql 

Step 4: Configure Maven build-helper-maven-plugin Plugin to add the generated source as sources folder

We will configure the build-helper-maven-plugin plugin such that maven will add the JOOQ generated code resides in gensrc/main/java directory as source folder.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>gensrc/main/java</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

Step 5: Create domain objects. 

We can use these domain object to pass data across the layer and JOOQ generated database artifacts to talk to database.

public class Post
{
    private Integer id;
    private String title;
    private String content;
    private Timestamp createdOn;
    private List<Comment> comments = new ArrayList<>();
    //setters & getters

}
public class Comment
{
    private Integer id;
    private Post post;
    private String name;
    private String email;
    private String content;
    private Timestamp createdOn;
    //setters & getters
}

Step 6: Implement the data persistence methods using JOOQ as follows.

package com.sivalabs.demo;

import static com.sivalabs.demo.jooq.domain.tables.Posts.POSTS;
import static com.sivalabs.demo.jooq.domain.tables.Comments.COMMENTS;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sivalabs.demo.entities.Comment;
import com.sivalabs.demo.entities.Post;
import com.sivalabs.demo.jooq.domain.tables.records.CommentsRecord;
import com.sivalabs.demo.jooq.domain.tables.records.PostsRecord;

@Service
@Transactional
public class BlogService
{
    @Autowired
    private DSLContext dsl;
    
    public Post createPost(Post post){
        PostsRecord postsRecord = dsl.insertInto(POSTS)
                .set(POSTS.TITLE, post.getTitle())
                .set(POSTS.CONTENT, post.getContent())
                .set(POSTS.CREATED_ON, post.getCreatedOn())
                .returning(POSTS.ID)
                .fetchOne();
            
        post.setId(postsRecord.getId());
        return post;
    }
    
    public List<Post> getAllPosts(){        
        List<Post> posts = new ArrayList<>();       
        Result<Record> result = dsl.select().from(POSTS).fetch();
        for (Record r : result) {
            posts.add(getPostEntity(r));
        }
        return posts ;
    }

    public Post getPost(Integer postId){
        Record record = dsl.select().
                                from(POSTS)
                                .where(POSTS.ID.eq(postId))
                                .fetchOne();
        if(record != null)
        {
            Post post = getPostEntity(record);
            
            Result<Record> commentRecords = dsl.select().
                                        from(COMMENTS)
                                        .where(COMMENTS.POST_ID.eq(postId))
                                        .fetch();
            
            for (Record r : commentRecords) {
                post.addComment(getCommentEntity(r));
            }
            return post;
        }
        return null;
    }
    
    
    public Comment createComment(Comment comment){
        CommentsRecord commentsRecord = dsl.insertInto(COMMENTS)
                .set(COMMENTS.POST_ID, comment.getPost().getId())
                .set(COMMENTS.NAME, comment.getName())
                .set(COMMENTS.EMAIL, comment.getEmail())
                .set(COMMENTS.CONTENT, comment.getContent())
                .set(COMMENTS.CREATED_ON, comment.getCreatedOn())
                .returning(COMMENTS.ID)
                .fetchOne();
            
        comment.setId(commentsRecord.getId());
        return comment;
    }
    
    public void deleteComment(Integer commentId){
        dsl.deleteFrom(COMMENTS)
                .where(COMMENTS.ID.equal(commentId))
                .execute();
    }
    
    private Post getPostEntity(Record r){
        Integer id = r.getValue(POSTS.ID, Integer.class);
        String title = r.getValue(POSTS.TITLE, String.class);
        String content = r.getValue(POSTS.CONTENT, String.class);
        Timestamp createdOn = r.getValue(POSTS.CREATED_ON, Timestamp.class);
        return new Post(id, title, content, createdOn);
    }
    
    private Comment getCommentEntity(Record r) {
        Integer id = r.getValue(COMMENTS.ID, Integer.class);
        Integer postId = r.getValue(COMMENTS.POST_ID, Integer.class);
        String name = r.getValue(COMMENTS.NAME, String.class);
        String email = r.getValue(COMMENTS.EMAIL, String.class);
        String content = r.getValue(COMMENTS.CONTENT, String.class);
        Timestamp createdOn = r.getValue(COMMENTS.CREATED_ON, Timestamp.class);
        return new Comment(id, postId, name, email, content, createdOn);
    }
}

Observe that we are auto-wiring DSLContext instance into our Spring Bean and using it to build the TypeSafe queries.

Step 7: Create Entry point class and JUnit test.

@SpringBootApplication
public class SpringbootJooqDemoApplication
{
    public static void main(String[] args) {
        SpringApplication.run(SpringbootJooqDemoApplication.class, args);
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SpringbootJooqDemoApplication.class)
public class SpringbootJooqDemoApplicationTests
{

    @Autowired
    private BlogService blogService;
    
    @Test
    public void findAllPosts()  {
        List<Post> posts = blogService.getAllPosts();
        assertNotNull(posts);
        assertTrue(!posts.isEmpty());
        for (Post post : posts)
        {
            System.err.println(post);
        }
    }
    
    @Test
    public void findPostById()  {
        Post post = blogService.getPost(1);
        assertNotNull(post);
        System.out.println(post);
        List<Comment> comments = post.getComments();
        System.out.println(comments);
        
    }
    
    @Test
    public void createPost() {
        Post post = new Post(0, "My new Post", 
                            "This is my new test post", 
                            new Timestamp(System.currentTimeMillis()));
        Post savedPost = blogService.createPost(post);
        Post newPost = blogService.getPost(savedPost.getId());
        assertEquals("My new Post", newPost.getTitle());
        assertEquals("This is my new test post", newPost.getContent());
    }
    
    @Test
    public void createComment() {
        Integer postId = 1;
        Comment comment = new Comment(0, postId, "User4", 
                                "user4@gmail.com", "This is my new comment on post1", 
                                new Timestamp(System.currentTimeMillis()));
        Comment savedComment = blogService.createComment(comment);
        Post post = blogService.getPost(postId);
        List<Comment> comments = post.getComments();
        assertNotNull(comments);
        for (Comment comm : comments)
        {
            if(savedComment.getId() == comm.getId()){
                assertEquals("User4", comm.getName());
                assertEquals("user4@gmail.com", comm.getEmail());
                assertEquals("This is my new comment on post1", comm.getContent());
            }
        }
        
    }
    
}

Assuming you have generated code using H2 profile, we can run the JUnit test with out any further configuration.

But if you have generated code using mysql profile then you will have to configure the following properties in application.properties.

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=admin

spring.jooq.sql-dialect=MYSQL

Note that we should use correct SqlDialect for the database otherwise you may get SQL syntax errors at runtime. 

You can find the source code of this article at my Github repository https://github.com/sivaprasadreddy/springboot-tutorials/tree/master/springboot-jooq-demo

 For more info on JOOQ you can look at http://www.jooq.org/learn/

If you want to learn more about SpringBoot take a look at my 

SpringBoot : Learn By Example book


Monday, March 14, 2016

SpringBoot : Working with MyBatis

MyBatis is a SQL Mapping framework with support for custom SQL, stored procedures and advanced mappings.

SpringBoot doesn’t provide official support for MyBatis integration, but MyBatis community built a SpringBoot starter for MyBatis. 
You can read about the SpringBoot MyBatis Starter release announcement at http://blog.mybatis.org/2015/11/mybatis-spring-boot-released.html and you can explore the source code on GitHub https://github.com/mybatis/mybatis-spring-boot.

Create a SpringBoot Maven project and add the following MyBatis Starter dependency.


<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

We will be reusing User.java, schema.sql and data.sql files created in my previous article
SpringBoot : Working with JdbcTemplate
Create MyBatis SQL Mapper interface UserMapper.java with few database operations as follows:

package com.sivalabs.demo.domain;

public interface UserMapper
{
    void insertUser(User user);
    User findUserById(Integer id);
    List<User> findAllUsers();
}

We need to create Mapper XML files to define the queries for the mapped SQL statements for the corresponding Mapper interface methods.

Create UserMapper.xml file in src/main/resources/com/sivalabs/demo/mappers/ directory as follows:

<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.sivalabs.demo.mappers.UserMapper">

    <resultMap id="UserResultMap" type="User">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="email" property="email" />
    </resultMap>

    <select id="findAllUsers" resultMap="UserResultMap">
        select id, name, email from users
    </select>

    <select id="findUserById" resultMap="UserResultMap">
        select id, name, email from users WHERE id=#{id}
    </select>

    <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        insert into users(name,email) values(#{name},#{email})
    </insert>
</mapper>

Few things to observe here are:

  • Namespace in Mapper XML should be same as Fully Qualified Name (FQN) for Mapper Interface
  • Statement id values should be same as Mapper Interface method names.
  • If the query result column names are different from bean property names we can use <resultMap> configuration to provide mapping between column names and their corresponding bean property names. 

MyBatis also provides annotation based query configurations without requiring Mapper XMLs.
We can create UserMapper.java interface and configure the mapped SQLs using annotations as follows:

public interface UserMapper
{
    @Insert("insert into users(name,email) values(#{name},#{email})")
    @SelectKey(statement="call identity()", keyProperty="id",
    before=false, resultType=Integer.class)
    void insertUser(User user);

    @Select("select id, name, email from users WHERE id=#{id}")
    User findUserById(Integer id);

    @Select("select id, name, email from users")
    List<User> findAllUsers();

}

SpringBoot MyBatis starter provides the following MyBatis configuration parameters which we can use to customize MyBatis settings.

mybatis.config = mybatis config file name
mybatis.mapperLocations = mappers file locations
mybatis.typeAliasesPackage = domain object's package
mybatis.typeHandlersPackage = handler's package
mybatis.check-config-location = check the mybatis configuration exists
mybatis.executorType = mode of execution. Default is SIMPLE

Configure the typeAliasesPackage and mapperLocations in application.properties.

mybatis.typeAliasesPackage=com.sivalabs.demo.domain
mybatis.mapperLocations=classpath*:**/mappers/*.xml

Create the entry point class SpringbootMyBatisDemoApplication.java.

@SpringBootApplication
@MapperScan("com.sivalabs.demo.mappers")
public class SpringbootMyBatisDemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SpringbootMyBatisDemoApplication.class, args);
    }
}

Observe that we have used @MapperScan("com.sivalabs.demo.mappers") annotation to specify where to look for Mapper interfaces.

Now create a JUnit test class and test our UserMapper methods.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SpringbootMyBatisDemoApplication.class)
public class SpringbootMyBatisDemoApplicationTests
{
    @Autowired
    private UserMapper userMapper;

    @Test
    public void findAllUsers() {
        List<User> users = userMapper.findAllUsers();
        assertNotNull(users);
        assertTrue(!users.isEmpty());
    }

    @Test
    public void findUserById() {
        User user = userMapper.findUserById(1);
        assertNotNull(user);
    }

    @Test
    public void createUser() {
        User user = new User(0, "Siva", "siva@gmail.com");
        userMapper.insertUser(user);
        User newUser = userMapper.findUserById(user.getId());
        assertEquals("Siva", newUser.getName());
        assertEquals("siva@gmail.com", newUser.getEmail());
    }
}

You can find the source code of the article at my GitHub repo https://github.com/sivaprasadreddy/springboot-tutorials

You can read more about MyBatis and Spring integration at http://blog.mybatis.org/p/products.html and http://www.mybatis.org/spring/.


If you want to learn more about SpringBoot take a look at my 

SpringBoot : Learn By Example book


SpringBoot : Working with JdbcTemplate

Spring provides a nice abstraction on top of JDBC API using JdbcTemplate and also provides great transaction management capabilities using annotation based approach.

First let’s take a quick look at how we generally use Spring’s JdbcTemplate (without SpringBoot) by registering DataSource, TransactionManager and JdbcTemplate beans and optionally we can register DataSourceInitializer bean to initialize our database.

@Configuration
@ComponentScan
@EnableTransactionManagement
@PropertySource(value = { "classpath:application.properties" })
public class AppConfig 
{
    @Autowired
    private Environment env;

    @Value("${init-db:false}")
    private String initDatabase;
    
    @Bean
    public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer()
    {
        return new PropertySourcesPlaceholderConfigurer();
    }    

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource)
    {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource)
    {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public DataSource dataSource()
    {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
    {
        DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();    
        dataSourceInitializer.setDataSource(dataSource);
        ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
        databasePopulator.addScript(new ClassPathResource("data.sql"));
        dataSourceInitializer.setDatabasePopulator(databasePopulator);
        dataSourceInitializer.setEnabled(Boolean.parseBoolean(initDatabase));
        return dataSourceInitializer;
    }
}

With this configuration in place, we can inject JdbcTemplate into Data Access components to interact with databases.

public class User
{
    private Integer id;
    private String name;
    private String email;

    // setters & getters
}
@Repository
public class UserRepository
{
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(readOnly=true)
    public List<User> findAll() {
        return jdbcTemplate.query("select * from users", new UserRowMapper());
    }
}
class UserRowMapper implements RowMapper<User>
{
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException 
    {
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setEmail(rs.getString("email"));

        return user;
    }
}

You might have observed that most of the times we use this similar kind of configuration in our applications.

Now let us see how to use JdbcTemplate without requiring to configure all these beans manually by using SpringBoot.

Using JdbcTemplate with SpringBoot 

By using SpringBoot we can take advantage of auto configuration feature and eliminate the need to configure beans by ourselves. 

Create a SpringBoot maven based project and add spring-boot-starter-jdbc module.

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

By adding spring-boot-starter-jdbc module, we get the following auto configuration: 


  • The spring-boot-starter-jdbc module transitively pulls tomcat-jdbc-{version}.jar which is used to configure the DataSource bean.
  • If you have not defined any DataSource bean explicitly and if you have any embedded database driver in classpath such as H2, HSQL or Derby then SpringBoot will automatically registers DataSource bean using in-memory database settings.
  • If you haven’t registered any of the following type beans then SpringBoot will register them automatically.
    PlatformTransactionManager (DataSourceTransactionManager) JdbcTemplate
    NamedParameterJdbcTemplate 
  • We can have schema.sql and data.sql files in root classpath which SpringBoot will automatically use to initialize database.

    In addition to schema.sql and data.sql, Spring Boot will load schema-${platform}.sql and data-${platform}.sql files if they are available in root classpath.
    Here platform value is the value of the property spring.datasource.platform which can be hsqldb, h2, oracle, mysql, postgresql etc.

    You can customize the default names of the scripts using the following properties:
     • spring.datasource.schema=create-db.sql
     • spring.datasource.data=seed-data.sql

    SpringBoot uses spring.datasource.initialize property value, which is true by default, to determine whether to initialize database or not. If you want to turn off the database initialization you can set spring.datasource.initialize=false

    If there are any errors in executing the scripts then application will fail to start. If you want to continue then you can set spring.datasource.continueOnError=true


Let us add H2 database driver to our pom.xml.

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

Create schema.sql in src/main/resources as follows:

CREATE TABLE users
(
    id int(11) NOT NULL AUTO_INCREMENT,
    name varchar(100) NOT NULL,
    email varchar(100) DEFAULT NULL,
    PRIMARY KEY (id)
);

Create data.sql in src/main/resources as follows:

insert into users(id, name, email) values(1,'Siva','siva@gmail.com');
insert into users(id, name, email) values(2,'Prasad','prasad@gmail.com');
insert into users(id, name, email) values(3,'Reddy','reddy@gmail.com');

Now you can inject JdbcTemplate into UserRepository as follows:

@Repository
public class UserRepository
{
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(readOnly=true)
    public List<User> findAll() {
        return jdbcTemplate.query("select * from users", 
                new UserRowMapper());
    }

    @Transactional(readOnly=true)
    public User findUserById(int id) {
        return jdbcTemplate.queryForObject(
            "select * from users where id=?",
            new Object[]{id}, new UserRowMapper());
    }

    public User create(final User user) 
    {
        final String sql = "insert into users(name,email) values(?,?)";

        KeyHolder holder = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                ps.setString(1, user.getName());
                ps.setString(2, user.getEmail());
                return ps;
            }
        }, holder);

        int newUserId = holder.getKey().intValue();
        user.setId(newUserId);
        return user;
    }
}

class UserRowMapper implements RowMapper<User>
{
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setEmail(rs.getString("email"));
        return user;
    }
}

Create the entry point SpringbootJdbcDemoApplication.java.

@SpringBootApplication
public class SpringbootJdbcDemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SpringbootJdbcDemoApplication.class, args);
    }
}

Let us create a JUnit Test class to test our UserRepository methods.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SpringbootJdbcDemoApplication.class)
public class SpringbootJdbcDemoApplicationTests
{
    @Autowired
    private UserRepository userRepository;

    @Test
    public void findAllUsers() {
        List<User> users = userRepository.findAll();
        assertNotNull(users);
        assertTrue(!users.isEmpty());
    }

    @Test
    public void findUserById() {
        User user = userRepository.findUserById(1);
        assertNotNull(user);
    }

    @Test
    public void createUser() {
        User user = new User(0, "John", "john@gmail.com");
        User savedUser = userRepository.create(user);
        User newUser = userRepository.findUserById(savedUser.getId());
        assertNotNull(newUser);
        assertEquals("John", newUser.getName());
        assertEquals("john@gmail.com", newUser.getEmail());
    }
}

By default SpringBoot features such as external properties, logging etc are available in the ApplicationContext only if you use SpringApplication. So, SpringBoot provides @SpringApplicationConfiguration annotation to configure the ApplicationContext for tests which uses SpringApplication behind the scenes

We have learned how to get started quickly with Embedded database. What if we want to use Non-Embedded databases like MySQL, Oracle or PostgreSQL etc?.

We can configure the database properties in application.properties file so that SpringBoot will use those jdbc parameters to configure DataSource bean.

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=admin

For any reason if you want to have more control and configure DataSource bean by yourself then you can configure DataSource bean in a Configuration class. If you register DataSource bean then SpringBoot will not configure DataSource automatically using AutoConfiguration.

What if you want to use another Connection Pooling library?
SpringBoot by default pulls in tomcat-jdbc-{version}.jar and uses org.apache.tomcat.jdbc.pool.DataSource to configure DataSource bean.

SpringBoot checks the availability of the following classes and uses the first one that is available in classpath.

  • org.apache.tomcat.jdbc.pool.DataSource 
  • com.zaxxer.hikari.HikariDataSource 
  • org.apache.commons.dbcp.BasicDataSource 
  • org.apache.commons.dbcp2.BasicDataSource 


For example, If you want to use HikariDataSource then you can exclude tomcat-jdbc and add HikariCP dependency as follows:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <exclusions>
        <exclusion>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jdbc</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
</dependency>

With this dependency configuration SpringBoot will use HikariCP to configure DataSource bean.

You can find the source code of the article at my GitHub repo https://github.com/sivaprasadreddy/springboot-tutorials

If you want to learn more about SpringBoot take a look at my 

SpringBoot : Learn By Example book