Spring Boot is mighty powerful. It enables multitude of functionalities with minimal amount of code (thanks to annotation processing & sensible defaults).
Listed below are a few features I’ve been using in a new project. I am creating a pre-configured scaffold code repository, will share the same soon.
- Spring Security
- Databases / JPA / Hibernate
Spring Boot allows configuration through application.properties. We can have multiple profiles (application.properties), each for a distinct environment and a developer. Specific profile can chosen during application startup using vm argument or system property or even set it in supporting IDE like Intellij IDEA.
Dependency injection without annotations
Spring Boot recommends using constructors for injecting dependencies. If you have single constructor, all the dependencies are auto injected. No need to have @AutoWired or @Inject annotations. As a bonus, this also helps mocking dependencies in tests (without using Spring constructs).
Hot reload of code changes
Spring Boot has fantastic ability to auto-reload changes made to the code without restarting the server. If code changes are done within the method, that code snippet is auto reloaded. Though if there are changes to method parameters, or add/delete of methods/classes, then application needs to be restarted. Even this can be minimized by using this maven plugin which detects changes and restarts the application. It is faster than ‘cold’ restarts. Check out this documentation for more details.
Spring User & Roles
Spring Security requires implementing UserDetailsService, and it uses its own POJO of User (with limited variables). If you require more variables you can easily extend the User class and convert instances when required by Spring Security. Side note: In Spring Security terminology a user-role is called Authority.
With Spring Security, encrypting passwords (to be persisted in DB), is as easy as writing one line of bean configuration. BCrypt is recommended option over MD5 and other hashing algorithms.
URL based security
URL based security can be very easily setup with few lines of code using WebSecurity configurer. This helps ensure users are authenticated and authorized to access the urls.
Method level security
Individual methods of controllers/services can be restricted too.
Spring Expressions based authorization
These restrictions need not be just based on authorities. With use of Spring Expressions it can trigger any service method, access parameters, access return value, access a bean etc. This can be useful for requests which depend on data, or where authorization code is dynamic and is implemented in separate service.
Login, Logout, CORS, CSRF, CSP
All the security measures for web-based application are covered by default in Spring Boot. Here’s where Spring Boot shines with sensible defaults. I highly recommend watching videos from Spring Security lead Rob Winch.
Accessing current user
Spring can tell which user the request belongs to. This can be achieved by only using annotation @AuthenticationPrincipal with the method parameter (of type User). If @AuthenticationPrincipal is not very readable, then custom annotation can be created which does the same thing.
Spring Boot supports JSR 303 bean validation API. This is very useful in validating user inputs. It also supports additional hibernate validators, for values to be validated from database (eg: unique email)
When exceptions are not handled in Controllers, they are returned to the caller as exception stack traces. Spring Boot supports Global exception handling, where-in we can choose the message and http status to return, based on type of exceptions.
Entity to JSON conversion
Spring Boot uses Jackson to convert entity/domain objects into JSON for consumption by clients (UI). There are multiple ways to achieve this:
- Let Spring convert whole class instance (along with its nested hierarchy) into JSON
- Use annotation @JsonIgnore to hide some fields from conversion. Eg: for password field, which should not be sent to UI
- Use JSON views, to contextually convert entities based on requests
- Use separate DTO classes, and write mappers to convert entity to DTO and vice-versa. DTO pattern is controversial, but the overhead of mappers can be reduced by BeanUtils.copyProperties()
Databases / JPA / Hibernate
Spring Boot (and Spring Data JPA) allows for lot of basic functionalities with minimal code:
- @Column and @Table annotation for entity is optional, naming strategies have sensible defaults.
- Lazy fetching of nested object hierarchy
- Field validations as mentioned above
- DDL validation during startup
- Transactions with annotations @transactional and @transactional(readonly = true)
- JPA Repositories for CRUD and Paging/Sorting
- Optimistic locking with single field/annotation of @version
Flyway - Database migrations
We have ample resources for deployments and rollback of the code, but very limited tools for doing the same for database changes done during the release. Flyway is an excellent tool which does just that. Spring Boot integrates nicely with Flyway.
Check out this page for how flyway works. It is quite useful and effective for DB upgrades and rollbacks.
Check out this sample repository
Primary key for records can be generated using one of these types (IDENTITY, SEQUENCE, TABLE). Each has pros and cons. For most use cases AUTO will do Check out more details here and here The default value for @GeneratedValue is AUTO.
Java 8 date, time and duration
Earlier Joda Date (& Java 8 date) had to be converted to java.sql.Date to persist into DB. This manual conversion can be avoided by adding only a converter in configuration. Now all entities can use Java 8’s Date, Time and Duration classes and the values are stored and retrieved correctly from database.
Auditing record metadata
Auditing the metadata of creates & updates is supported out of the box.
- Using @CreatedDate and @ModifiedDate annotations on entity fields is enough for those columns to be populated each time a record is created or updated.
- Using @CreatedBy and @ModifiedBy annotations allow to insert user who created/updated the record. For this, Spring needs to know who is the auditor. This auditor can be configured with few lines of code.
- The modified-date and modified-by fields only store data related to latest update.
Auditing full records
Hibernate envers allows to audit entire row of the database each time it is updated. It can be easily used in Spring Boot by using a lightweight wrapper project called Spring-data-envers. The auditing comes extremely handy. The database can be just queried for changes instead of digging through the logs (or using log parsers). The audited records can also be accessed programmatically by extending RevisionRepository.
Hibernate can create the missing tables on application startup (based on the entity classes in the application). If Flyway DB is being used, we need to have create/update queries (DDL) in flyway SQL scripts. These queries need not be written manually. They can be generated by Hibernate on application startup. Once configured, all the DDL queries (along with constraints, indexes and joins) are dumped into the specific file from which we can copy-paste to Flyway SQL scripts file.
- @ActiveProfile: Chooses the profile to be used (for all tests in that class)
- @DirtiesContext: Resets context after every test
- @TestPropertySource: Adds extra test properties configuration
- @ComponentScan: Scan only specific package classes to speeden up the process
Spring Boot allows to test each individual layer (DAO, Controller etc) separately. Each layer has corresponding annotations (@WebMvcTest, @DataJpaTest) to be used. This helps in fast execution of tests, (initialization of layers unrelated to the tests are be avoided), also making code more succinct. Check this article for more details.
If application is configured to use authentication and authorization, users (for the requests) can be configured per test-class or per test-method. Also, user can be set with specific authorities, or an existing DB user can be used.
During JPA testing,
- @DataJpaTest can be used for testing just JPA layer
- @AutoConfigureTestDatabase can be used to auto-configure test database (requires H2 or similar DB in classpath)
- @Sql can be used to insert mock data before tests run
- @EnableJpaAuditing can be used to well, enable auditing
- @AutoConfigureTestEntityManager can be used to auto-configure entity manager for persisting entities
MockMVC and RestTemplates
The controllers can be tested using either mock-mvc or with rest templates. MockMVC as name suggests only mocks the network calls. With rest-templates, server needs to be started and network calls are made for testing.
Phew! That’s a long list, and yet it does not cover all the features Spring Boot has to offer (eg: Actuators and metrics). It amazes me that Java development has come this far. I still remember reinventing the wheel (& writing too much code for it) for every project, not to mention the testing required. This is even more amazing considering Spring Boot (& family) is completely free and open-source. Good times!
Hit me up in the comments if I missed anything or if you have any queries.