Spring Boot – more advanced (auto)configuration
In our first tutorial we showed you how to move your existing application (or set up new one) with Spring Boot. In this tutorial we want to show you how easy Spring Boot manage other parts of your application.
Starters
Starters are a set of dependency descriptors ready to be included in your application. They contain a lot of the dependencies, often with set of custom properties that allow you to add part of functionality without much effort.
Ten most popular starters on mvnrepository.com are:
We will describe some of them (and some other, not included in this table but no less interesting) more broadly in next paragraphs.
Web starter
In previous tutorial you’ve added spring-boot-starter-web for web application to easily set up it locally. This starter includes libraries like Spring MVC, Jackson and Tomcat as a default web application server. It also auto-configures things like: dispatcher servlet, error page and web JARs for managing the static dependencies. If you want, instead of Tomcat you can use another embedded web server, like Jetty or Undertow. To do that simply add:
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
<exclusions>
<exclusion>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-tomcat</artifactid>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-jetty</artifactid>
</dependency>
to your pom.xml file. Of course if you prefer Undertow just replace spring-boot-starter-jetty with spring-boot-starter-undertow.
You can also easily customize your server. To do that extend your application properties by adding for ex.:
server.port=8082
server.servlet.context-path=/
spring.mvc.servlet.path=/demo/
server.tomcat.basedir=/tmp
server.tomcat.background-processor-delay=30
server.tomcat.max-threads=2
server.tomcat.uri-encoding=UTF-8
Data JPA starter
Next starter, spring-boot-starter-data-jpa provides us wide functionalities of persisting data. It comes to us with all goods from Spring Data JPA, such as no-code repositories. Let’s assume that you’ve already used it in your project or know how to use and just presents to you how to move your data sources configuration to Spring Boot.
To do this add to your pom.xml:
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-jpa</artifactid>
</dependency>
Then, to define new data source create a bean:
@Bean
@ConfigurationProperties("demo.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
and add credentials to properties:
demo.datasource.driver-class-name = com.mysql.jdbc.Driver
demo.datasource.jdbc-url=jdbc:mysql://localhost/demo
demo.datasource.username=dbuser
demo.datasource.password=dbpass
demo.datasource.maximum-pool-size=30
You probably will need to add dependencies to data source driver, in this case:
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-java</artifactid>
</dependency>
For developing purposes you can always use in memory databases like H2. To simply add it with Spring Boot add:
demo.datasource.type=H2
demo.datasource.jdbc-url=jdbc:h2:mem:store;MODE=MYSQL;
demo.datasource.driver-class=org.h2.Driver
demo.datasource.username=sa
demo.datasource.password=
demo.datasource.generate-dll=true
to your properties and:
<dependency>
<groupid>com.h2database</groupid>
<artifactid>h2</artifactid>
</dependency>
to your pom.xml. You can always add mre than one data source to your project. To do that you will need to do two things: mark one of your bean with @Primary annotation and include data source name in your properties, because Spring Boot needs to know which property use to which data source configuration:
@Bean
@Primary
@ConfigurationProperties("demo.datasource.first")
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("demo.datasource.second")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
demo.datasource.first.driver-class-name = com.mysql.jdbc.Driver
demo.datasource.first.jdbc-url=jdbc:mysql://localhost/demo
demo.datasource.first.username=dbuser
demo.datasource.first.password=dbpass
demo.datasource.first.maximum-pool-size=30
demo.datasource.second.driver-class-name = com.mysql.jdbc.Driver
demo.datasource.second.jdbc-url=jdbc:mysql://localhost/demo2
demo.datasource.second.username=dbuser2
demo.datasource.second.password=dbpass2
demo.datasource.second.maximum-pool-size=30
Security starter
Sometimes you want to secure your web application. With help to do that comes another starter: spring-boot-starter-security. With tons of useful dependencies we are getting our endpoints secured just by adding two properties:
spring.security.user.name=admin
spring.security.user.password=admin123
After that if we want to go to one of endpoint we will see login prompt:
Of course this feature is enough if we are developing simple application, only with admin panel, etc. For other use cases we need to disable default Auto-Configuration and write our own. To do that add exclude:
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class SpringBootSecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSecurityApplication.class, args);
}
}
or property:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration
After that we can add our own configuration class:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder authBuilder) throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
authBuilder
.inMemoryAuthentication()
.withUser("user")
.password(encoder.encode("password123"))
.roles("USER")
.and()
.withUser("admin")
.password(encoder.encode("admin123"))
.roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
Another useful solutions of common problems that comes with spring-boot-starters-security are: out-of-the-box support for CORS, CSRF attack prevention, Session Fixation protection and Security Header integration (like X-Content-Type-Options integration, Cache Control, X-XSS-Protection integration and X-Frame-Options integration to help prevent Clickjacking).
Conclusion
Adding almost every starter that Spring Boot offer to us is as simple as our examples. We only need to add some dependencies, few properties and sometimes couple lines of code, but almost everything works out of the box. It’s very comfortable, especially when we want to create something that works quickly, but it’s not the only advantage of starters. Using starters we are always solving the problems in the same way as others, so our solutions are reliable and fully tested by millions of users across the world.