What is Spring Boot?

Spring Boot is an opinionated view on the Spring framework and third party libraries so a developer can get started with their project with minimum fuss. One of the goals of Spring Boot is to provide next to minimum configuration for a project.

Dependencies

I will be using

  • Maven
  • Spring Data JPA
  • Embedded H2 database
  • RestAssured for API Live tests

User Entity

This will be our domain for this tutorial a simple User object.

  • @Id, denotes the primary key in SQL
  • @GeneratedValue, autogenerates an id for us, instead of setting it on every save
@Entity
public class User {

    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private String firstName;
    private String lastName;

    // getters/setters omitted
}

User Repository (with some Spring Data magic)

Using Spring Data JPA and the PaginatedRepository interface we get CRUD operations plus pagination of result sets out of the box.

public interface UserRepository extends PagingAndSortingRepository<User, Long> {

}

User Controller

A basic CRUD Rest controller for our domain

  • GET /api/users -> get all users
  • GET /api/users/{userId} -> get specific user
  • PUT /api/users/{userId} -> update a user (this operation is indempotent)
  • POST /api/users -> inserts a user in the db
@RestController
@RequestMapping(value = "/api/users")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @RequestMapping(method = RequestMethod.GET)
    public Page<User> getUsers(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{userId}")
    public User getUser(@PathVariable Long userId) {
        return userRepository.findOne(userId);
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{userId}")
    public User updateUser(@PathVariable Long userId, @RequestBody User updatedUser, 
                           HttpServletResponse response) {
        User user = userRepository.findOne(userId);
        if (user == null) {
            response.setStatus(404);
            return null;
        }

        user.setFirstName(updatedUser.getFirstName());
        user.setLastName(updatedUser.getLastName());
        user.setUsername(updatedUser.getUsername());
        return userRepository.save(user);
    }

    @RequestMapping(method = RequestMethod.POST)
    public User insertUser(@RequestBody User updatedUser) {
        return userRepository.save(updatedUser);
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{userId}")
    public void deleteUser(@PathVariable Long userId) {
        userRepository.delete(userId);
    }

}

User Controller Live Test

And because we like testing a lot :) here is a Live Test for our API.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
public class UserControllerIntegrationTest {

	private User aUser;

	/**
	 * Insert a user before every test
	 */
	@Before
	public void beforeHookActions() {
		aUser = insertUser("Yet", "Another", "dev");
		Assert.notNull(aUser);
	}

	@Test
	public void test_GetUser() {
		User getUser = get("/api/users/{0}", aUser.getId())
                  .as(User.class);

		Assert.notNull(getUser);
		Assert.isTrue(
              aUser.getId().equals(getUser.getId()));
	}

	@Test
	public void test_GetUsers() {
		Map<String, String> requestParams = new HashMap<>();
		requestParams.put("page", "0");
		requestParams.put("size", "2");

		String response = 
           get("/api/users?page={page}&size={size}", requestParams)
						.asString();

		Assert.isTrue(response.contains(aUser.getFirstName()));
		Assert.isTrue(response.contains(aUser.getLastName()));
		Assert.isTrue(response.contains(aUser.getUsername()));
	}

	@Test
	public void test_PutUser() {
		User updateDto = new User();
		updateDto.setUsername("Just");
		updateDto.setFirstName("Update");
		updateDto.setLastName("Me");

		User updatedUser = updateUser(aUser.getId(), updateDto);

		Assert.notNull(updatedUser);
		Assert.isTrue(
           updatedUser.getFirstName().equals(
             updateDto.getFirstName()));
		Assert.isTrue(
           updatedUser.getLastName().equals(
             updateDto.getLastName()));
		Assert.isTrue(
           updatedUser.getUsername().equals(
             updateDto.getUsername()));
	}

	private User insertUser(String firstName, 
                            String lastName, 
                            String username) {
		User aUser = new User();
		aUser.setFirstName(firstName);
		aUser.setLastName(lastName);
		aUser.setUsername(username);

		return with().body(aUser)
            .contentType(ContentType.JSON)
            .post("/api/users")
            .andReturn()
            .as(User.class);
	}

	private User updateUser(Long userId, 
                            User updateDto) {
		return with()
				.body(updateDto)
				.contentType(ContentType.JSON)
				.put("/api/users/{0}", userId)
				.andReturn()
				.as(User.class);
	}

}

Conclusion

Spring Boot makes it so easy to create an API and of course test it. Many concepts from Spring were left out in this small tutorial for the shake of simplicity. In another post I will cover validation and security.

If you want you can download the code from https://github.com/ssouris/spring-tutorials/tree/master/introduction-to-spring-boot and play around.

Thanks for reading.