Creating a strong foundation for a new project using Spring Boot – Part 1

Contents

This post is divided into four parts.

  1. Getting Ready
  2. Unit testing
  3. Integration testing
  4. Launching the app

Creating a strong foundation for any new project is critical for timely delivery as well as maintainability. Frameworks like Spring Boot and tools like Gradle are meant for rapid development. However, if not utilized correctly, these can become a bottleneck and hinder your pace of development.

Let us see how can we create a solid foundation of any new project that provides you high testability as well as portability. This post, by no means, claims to be a perfect example, however, it should provide you a good enough ground to play around.

Not a standard Spring MVC app

We are not going to discuss “How to create a Spring MVC app” here. In fact, the sample app that we will develop will have minimal functionality. Our main focus will be how to set up the project so that it can be developed quickly. We will talk about organizing unit tests, integration tests, while keeping the tests independent such that they can be run on any machine without having any dependency on the infrastructure. There are other things as well which you will see later on. You might feel that we are spending a lot of time in just setting things up, without doing actual coding. But consider this as an investment which will surely pay off in the near future.

Get the code

The complete example that we are going to develop can be found on GitHub. However, I encourage to code along as you read and you should have the similar project developed at your end.

The starting point

This post assumes that you have a basic knowledge of Spring boot and Gradle. Gradle is not a mandate, the same thing can be achieved using maven as well. However, we will proceed with Gradle in this post. Even if you are new to Gradle, give it a shot. I am sure you’ll love it.

Create a new Spring boot starter project named ‘basic-layout’ (or whatever name you prefer) having the following dependencies.

  1. Web
  2. JPA
  3. MySql
  4. H2

Alternatively, click this link to get the .zip file directly from Spring IO. Extract the zip file and import the project in your favorite IDE.

Checkpoint

At this point, your project structure should look as follows.

initial-structure

Notice the gradle-wrapper.jar under directory gradle/wrapper. One of the best things is the native support of a wrapper in gradle. This allows you to build your project on any machine without installing Gradle. This comes handy when you talk about automating your builds. Hence, the mechanism to build (or execute any Gradle task) is included within your application itself. Now how cool is that!

Before moving further

Add the following dependency in your build.gradle file.

[code lang=”plain”]
testCompile (‘org.assertj:assertj-core:3.0.0’)
[/code]

Spring Boot automatically includes the assertj library, but it is an older version. Just override it by implicitly providing the latest version of assertj in the build.gradle file.

Now using the console, navigate to the project’s root directory and execute the following command.

[code language=”plain”]
gadlew build
[/code]

At this point, you should be successfully able to build the project.

The source code

First of all, make sure that your DB is running. After that, add the following entries in application.properties.

[code language=”plain”]
# ===============================
# = DATA SOURCE
# ===============================

# Set here configurations for the database connection

# Connection url for the database "test"
spring.datasource.url = jdbc:mysql://localhost:3306/test?useSSL=false

# Username and password
spring.datasource.username = root
spring.datasource.password = root

# Keep the connection alive if idle for a long time (needed in production)
#spring.datasource.testWhileIdle = true
spring.datasource.dbcp.test-while-idle=true
#spring.datasource.validationQuery = SELECT 1
spring.datasource.dbcp.validation-query=SELECT 1

# ===============================
# = JPA / HIBERNATE
# ===============================

# Use spring.jpa.properties.* for Hibernate native properties (the prefix is
# stripped before adding them to the entity manager).

# Show or not log for each sql query
spring.jpa.show-sql = true

# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
spring.jpa.hibernate.ddl-auto = update

# Naming strategy
#spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy

# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
[/code]

I have included the explanation wherever required. Make sure to modify the entries according to your DB.


Create a Model class called User as shown below.

[code language=”java”]
package org.websandbox.learning.layout.user;

//imports omitted

@Entity
@Table(name = "users")
public class User {

public User() {
}

public User(String email, String name) {
this.name = name;
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Size(min = 3, max = 20)
private String name;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
[/code]

Pretty simple.


A repository for CRUD operations. UserRepository.java

[code language=”java”]
package org.websandbox.learning.layout.user;

//imports omitted

@Repository
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {

public Optional<User> findByName(String name);

public Optional<User> findById(Long id);

public List<User> findAll();

}
[/code]


The service class UserService.java

[code language=”java”]
package org.websandbox.learning.layout.user;

//imports omitted

public interface UserService {

public Optional<User> getUserById(Long id);

public Optional<User> getUserByName(String name);

public List<User> getAllUsers();

public boolean exists(String email);

public User save(User user);
}
[/code]


The implementation of the service class UserServiceImpl.java

[code language=”java”]
package org.websandbox.learning.layout.user;

//imports omitted

@Service
@Transactional
public class UserServiceImpl implements UserService {

@Autowired
UserRepository userRepository;

@Override
public Optional<User> getUserById(Long id) {
return userRepository.findById(id);
}

@Override
public Optional<User> getUserByName(String name) {
return userRepository.findByName(name);
}

@Override
public boolean exists(String name) {
if (userRepository.findByName(name) != null) {
return true;
}
return false;
}

@Override
public User save(User user) {
return userRepository.save(user);
}

@Override
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
[/code]


Finally, the controller that will expose the APIs. UserRestController.java

[code language=”java”]
package org.websandbox.learning.layout.user;

//imports omitted

@RestController
@RequestMapping("/api")
public class UserRestController {

@Autowired
UserService userService;

@RequestMapping(value = "/users", method = RequestMethod.POST)
public ResponseEntity<User> createUser(@RequestBody User user) {
HttpStatus status = HttpStatus.CREATED;
User saved = userService.save(user);
return new ResponseEntity<>(saved, status);
}

@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getAllUsers() {
return userService.getAllUsers();
}

}
[/code]

That’s all for the source code. We will not have any new feature for this application.

Checkpoint

At this point, you should have the below user specific files created. Note that the file “BasicLayoutApplication.java” was automatically created by Spring Boot. It contains the main class.

Main source code

Let us focus on the core of this post. Continue reading Part 2.