In this post, we’ll be looking up what does spring has to offer for developer experience.
Table of Contents
Overview
Using IDEs like Eclipse, Spring Tool Suite, Intellij Idea a typical development setup includes an application code base that gets deployed on a Web Application Server like Wildfly
or Tomcat
or even Glassfish
. The speed of development is based on the Edit, Compile, Run Cycle
and each cycle requires restarting the server for the application to load new changes. This leads to a lot of time being wasted waiting for application server to boot up.
JRebel
JRebel allows developers to skip rebuilds and redeploys during Java development and maintains the application state. This allows developers to see how code changes affect their application in real time and save a lot of time by avoiding rebuild and redeployment. It’s based on the concept of Hot Swapping but all this comes at a cost and depending on your use case, JRebel may turn into an expensive option.
Introduction to Spring Boot DevTools
Spring Boot includes an additional set of tools that can make the application development experience a little more pleasant. The spring-boot-devtools
module can be included in any project to provide additional development-time
Adding Devtools to your project
Get a File > New Project and add necessary dependencies, you can go to Spring Starter IO. and add the below dependencies:
- spring-boot-devtools
After that your pom.xml
would look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> </dependencies> |
The scope is runtime
meaning this is dynamically loaded code and is not directly referenced in program code and keeps it from being transitive. The optional
flag is set to true
prevents it from being transitively applied to other modules that use your project.
Spring Boot DevTools Features
Property Defaults
Spring-boot does a lot of auto-configurations and it basically sets up different profiles based on your environment.
It allows you to set properties based on profiles too.
Logging
Devtools would switch the log level
to debug
to provide more insights into what’s happening to the application at a given instance. e.g. putting devtools in a REST api
project will give you information about the input request,processing handler, the response and more.
spring.http.log-request-details=true
Caching
In production, it is crucial to depend on various caches (such as templating engine’s caches, caching headers for
static resources and so on) but in a development setup you’d want to disable caching so that you always see the latest changes you had performed. If caching is enabled in your dev environment, the data served to you might be old leading to time loss in clearing cache or confusion in identifying if a bug was resolved or not.
DevTools configure many of these caching settings for you in your dev environment by setting caching to false and enabling other settings that’ll give a boot to your development skills.
Cache options are usually configured by settings in your application.properties file.
– spring.freemarker.cache=false
– spring.groovy.template.cache=false
– spring.mustache.cache=false
– server.servlet.session.persistent=true
– spring.h2.console.enabled=true
– spring.resources.cache.period=0
– spring.resources.chain.cache=false
– spring.template.provider.cache=false
– spring.mvc.log-resolved-exception=true
– server.servlet.jsp.init-parameters.development=true
– spring.reactor.stacktrace-mode.enabled=true
If you don’t want property defaults to be applied you can set spring.devtools.add-properties=false
in your application.properties.
Automatic Restart
Code changes and deploy to test is a crucial part of an application development and every time the code is modified the changes need to be redeployed. Spring Boot DevTools help by providing automatic restart to your application whenever you modify a class file.
Now restarts are also an elaborate process and the server does take some time to boot up but this Automatic Restart
is not the traditional stop
and re-run
.
Under the hood, Spring DevTools uses two classloaders
:
– base: The classes which do not change.
– restart: The classes that are actively being worked on.
Whenever a restart is triggered, existing restart classloader
is discarded and recreated and is much faster than usual.
This is what makes devtools
different from tools like JRebel which uses dynamic class reloading
. At this event, a log is written with changes to your application auto-configuration.
Here is list of some common configurations which you can do.
spring.devtools.restart.log-condition-evaluation-delta=false
// Additionally set the resources to exclude from triggering an auto-restart spring.devtools.restart.exclude=static/**,public/**
// To keep defaults and add aditional exclude rules use the below instead of above
spring.devtools.restart.additional-exclude=// To add class paths to trigger an auto-restart
spring.devtools.restart.additional-paths=
// To Completly disable this feature
spring.devtools.restart.enabled=false
// To set up a file when changed (and only when) should trigger a restart
spring.devtools.restart.trigger-file=
// Add project sub modules (added as .jar) to the auto-restart
restart.include.projectcommon=/<YOUR_JAR_NAME>-[\\w\\d-\.]+\.jar
Restart functionality does not work well with objects that are de-serialized by using a standard ObjectInputStream
.If you need to deserialize data, you may need to use Spring’s ConfigurableObjectInputStream
in combination with Thread.currentThread().getContextClassLoader()
.
Live Reload
This feature is mostly related to a webapp (maybe a jsp
) where you can make changes to the HTML
, CSS
and see them change almost instantly. Very useful when trying to get that last button pixel perfect by pre-processing files (compiling SASS
or LESS
files) as needed. Another use case would be to monitor and reload the output of your APIs.
Only one instance of this can run at a time and in case multiple applications are running with this functionality, only the first one would work.
spring.devtools.livereload.enabled=false
You can install browser plug-ins for the browsers to support it. I use Chrome and this plug-in comes in handy. You can lookup similar plug-ins for your browser as well.
Global Settings
What good DevTools would be if you had to copy-paste a bunch of settings based on your dev environment to every project
you work on. DevTools has provided a nifty way to define global settings that every application using DevTools would use.
Just create a folder at $HOME/.config/spring-boot
and add a spring-boot-devtools.properties
file with all your
preferences. Other config extensions supported are yaml
and yml
In case you activate a spring profile from this global file, it wouldn’t matter. The profile set in your project would always be picked for profile-specific config files
Remote Applications
This is more of a UAT
, Pre-Prod
feature but I would Highly NOT recommend it keeping this feature active in your production systems as even though it can be useful, it causes serious security threats to your production setup. Hence it’s disabled by default. To enable it in the build plug-in add the below config
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludeDevtools>false</excludeDevtools> </configuration> </plugin> </plugins> </build> |
and now just set a password in your application.properties
for the client to interact
spring.devtools.remote.secret=
A Piece of advice would be to always use https
when using this feature. It cannot be emphasized enough on how risky this feature is in your production setup.
The remote client application is designed to be run from within your IDE. You need to run
org.springframework.boot.devtools.RemoteSpringApplication
with the same classpath as the remote project that you connect to. The application’s single required argument is the remote URL to which it connects. The remote client monitors your application classpath for changes in the same way as the local restart. Any updated resource is pushed to the remote application and (if required) triggers a restart. This can be helpful if you iterate on a feature that uses a cloud service that you do not have locally.
File System Watchers
It works by polling the class changes with a certain time interval and then waiting for a predefined quiet period to make sure there are no more changes. The changes are then uploaded to the remote application. If the latency is too high and changes take longer to upload. You can set up below properties to adjust for these cases
spring.devtools.restart.quiet-period=1s
Conclusion
You have learned about need of Spring devtools,features of Spring boot devtools such as property defaults,Automatic restart, Live reload, File system watchers etc.
That’s all about Spring boot devtools.