In this tutorial, you will understand the overview of Spring Boot starters, its importance, and examples.
With Exponential increase in the number of Libraries and their dependencies, dependency management was becoming a complex task and was required a good amount of technical expertise to handle it correctly. Though dependency management is a critical aspect of almost all complex projects. Handling all of these dependencies manually is a cumbersome process.
Spring Boot Starters were build to address this exact problem for manual dependency management. With String boot starter templates, you can get a lot of help in identifying the correct dependencies to use in the project if you want to use any popular library into your project.
Spring boot comes with more than 50+ different Starter modules, which will provide ready to use integration libraries for many different frameworks.
Popular templates and their transitive dependencies
Below are some very frequently use spring starters and what dependencies they bring along, for information only.
STARTER | DEPENDENCIES |
---|---|
spring-boot-starter | spring-boot, spring-context, spring-beans |
spring-boot-starter-jersey | jersey-container-servlet-core, jersey-container-servlet, jersey-server |
spring-boot-starter-actuator | spring-boot-actuator, micrometer-core |
spring-boot-starter-aop | spring-aop, aspectjrt, aspectjweaver |
spring-boot-starter-data-rest | spring-hateoas, spring-data-rest-webmvc |
spring-boot-starter-hateoas | spring-hateoas |
spring-boot-starter-logging | logback-classic, jcl-over-slf4j, jul-to-slf4j |
spring-boot-starter-log4j2 | log4j2, log4j-slf4j-impl |
spring-boot-starter-security | spring-security-web, spring-security-config |
spring-boot-starter-test | spring-test, spring-boot,junit,mockito, hamcrest-library, assertj, jsonassert, json-path |
spring-boot-starter-web-services | spring-ws-core |
Check out the actual List of all Starters here.
Web Starter
Let’s create e REST Service, we can use libraries for developing like Spring MVC, Tomcat Jackson, etc.- These are a lot of libraries for Single application.
Spring Boot starters help to reduce the number of dependencies to be added manually. Just adding single dependency will work to start developing on the application
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Now, creating a Simple controller for manipulating the data.
@RestController
public class BookController {
private List<Book> bookList = new ArrayList<>();
{
bookList.add(new Book(10001l,"Book1", "Author1"));
bookList.add(new Book(10002l,"Book2", "Author2"));
bookList.add(new Book(10003l,"Book3", "Author3"));
bookList.add(new Book(10004l,"Book4", "Author4"));
}
@RequestMapping("/book/all")
public List<Book> findAll() {
return bookList;
}
@RequestMapping(value = "/book", method = RequestMethod.POST)
public Book addEntity(Book book) {
bookList.add(book);
return book;
}
@RequestMapping("/book/findby/{id}")
public Book findById(@PathVariable Long id) {
return bookList.stream().
filter(book -> book.getId().equals(id)).
findFirst().get();
}
}
As for the Simplicity for understanding, We have created a simple controller without any use of a database.
Book is a simple bean with Getters and Setters.
@Entity
public class Book {
@Id
@GeneratedValue
private Long id;
private String title;
private String author;
//Getters and Setters
// Contructors
}
We have created a REST application with quite a minimal configuration. That’s it. with the application running, check the http://localhost:8081/book/all
and it is working. We have configured port 8081 in the application. If not set default will be 8080.
Data JPA Starter
Almost all applications have some sort of Persistence. Now Instead of defining all dependencies manually, let’s go and use the starter instead.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Notice that out of the box we have automatic support for at least the following databases: H2, Derby, and Hsqldb. In our example, we’ll use H2.
Now let’s create the Repository for Book Entity – BookRepository.
public interface BookRepository extends JpaRepository<Book, Long> {
}
Now we will write the Unit Test case with Junit to test the BookRepository.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootTutorialApplication.class)
public class BookRepositoryJPATest {
@Autowired
private BookRepository bookRepository;
@Test
public void givenBookRepository_whenSaveAndRetreiveBook_thenOK() {
Book book = bookRepository.save(new Book(1005l,"Book5","Author5"));
Book findBook = bookRepository.findById(book.getId()).get();
Assert.assertNotNull(findBook);
Assert.assertEquals(book.getAuthor(),findBook.getAuthor());
}
}
If you notice, we haven’t provided any database-specific details in the configuration. Spring Boot will do auto Configuration by defaults, but of course, all these details (database vendor, URL Connection, Credentials etc) can still be configured if necessary.
Test Starter
For testing, we usually use the following set of libraries: Spring Test, JUnit, Hamcrest, and Mockito. We can include all of these libraries manually, but the Spring Boot starter can be used to automatically include these libraries in the following way:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
As you notice, we haven’t specified the version number information to any of the dependencies. Spring Boot will figure out the version to use for the application base on the spring-boot-starter artifact version.
Now, Let’s Test the Controller. There are two ways to test the controller:
- Using the mock environment
- Using the embedded Servlet container (like Tomcat or Jetty)
In this example we’ll use a mock environment:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootTutorialApplication.class)
@WebAppConfiguration
public class SpringBootApplicationIntegrationTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setupMockMvc()
{
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void givenRequestIsMade_andMeetsAllGivenConditions_thenCorrect() throws Exception
{
MediaType mediaType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
mockMvc.perform(MockMvcRequestBuilders.get("/book/all"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(mediaType));
}
}
The above Test is calling endpoint /book/all
and verifies the JSON response. The important part here is @WebAppConfiguration annotation and MockMVC are part of the spring-test module, @Before is a JUnit annotation. These all are available by importing just one test starter dependency.
Mail Starter
A very common task in an enterprise application is to send mails. Spring Boot provides mail dependency and can be defined this way.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
Now we can directly use the JavaMailSender, so let’s write some tests.
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp</artifactId>
<version>3.1.7</version>
<scope>test</scope>
</dependency>
For simple testing, we will use the Simple SMTP server.
The latest version of Wiser can be found on Maven central repository.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootTutorialApplication.class)
public class SpringBootMailTest {
@Autowired
private JavaMailSender javaMailSender;
private Wiser wiser;
private String userTo = "usermail1@localhost";
private String userFrom = "usermail2@localhost";
private String subject = "Test subject text";
private String textMail = "Text subject mail text";
@Before
public void setUp() throws Exception {
final int TESTING_PORT = 25;
wiser = new Wiser(TESTING_PORT);
wiser.start();
}
@After
public void breakDown() throws Exception {
wiser.stop();
}
@Test
public void forgivenMail_ifSendAndReceived_thenCorrect() throws Exception {
SimpleMailMessage message = composeEmailMessage();
javaMailSender.send(message);
List<WiserMessage> messages = wiser.getMessages();
WiserMessage wiserMessage = messages.get(0);
Assert.assertEquals(userFrom, wiserMessage.getEnvelopeSender());
Assert.assertEquals(userTo, wiserMessage.getEnvelopeReceiver());
Assert.assertEquals(subject, getSubject(wiserMessage));
Assert.assertEquals(textMail, getMessage(wiserMessage));
}
private String getMessage(WiserMessage wiserMessage)
throws MessagingException, IOException {
return wiserMessage.getMimeMessage().getContent().toString().trim();
}
private String getSubject(WiserMessage wiserMessage) throws MessagingException {
return wiserMessage.getMimeMessage().getSubject();
}
private SimpleMailMessage composeEmailMessage() {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(userTo);
mailMessage.setReplyTo(userFrom);
mailMessage.setFrom(userFrom);
mailMessage.setSubject(subject);
mailMessage.setText(textMail);
return mailMessage;
}
}
The @Before and @After methods are in charge of starting and stopping the mail server.
Just like any other defaults in Boot, the email settings for the JavaMailSender can be customized in application.properties:
spring.mail.host=localhost
spring.mail.port=25
spring.mail.properties.mail.smtp.auth=false
So we configured the mail server on localhost:25 and we didn’t require authentication.
Conclusion
In this tutorial, we have given the overview of Spring Boot starters, a list of important starter templates, importance and examples to use the starter template.
The actual list of starters can be found here. Source code for the examples can be found here.
Check out more Spring Boot tutorial.
Pingback: Spring Boot with a Custom Parent - Daily Code Buffer
Pingback: Building a Spring Boot application using IntelliJ IDEA - Daily Code Buffer