Spring Boot Live Reload UI: See Java Changes in Your Browser

You change a label in your Java view, switch to the browser, and then wait. Stop the app, start it again, reload the page, click back to the screen you were on. Repeat that all day and a lot of development time quietly goes into waiting.
A Spring Boot live reload UI setup removes those steps. You save, the app picks up the change, and the browser refreshes on its own. In this post you'll turn it on for a webforJ app, see how each kind of change reaches the page, and look at the tools around it for CSS and for editing properties while the app runs.
What you'll set up
By the end you'll have three things working together in one Spring Boot project:
- Live reload, so a saved Java change shows up in the browser without you touching it.
- The frontend watch, so stylesheet changes appear in place.
- craftforJ, so you can edit component properties in the running app.
Each part builds on the previous one, and each ends with a short recap.
How the reload works
Before any configuration, it helps to know what happens when you save. webforJ treats each kind of change differently, because a stylesheet and a Java class need different handling.
| Change | Result |
|---|---|
| Java class, no hotswap tool | The app restarts. The browser reloads when the app is ready. |
| Stylesheet or image | The page applies it in place, without a reload. |
Source under src/main/frontend | The watch rebuilds it and updates the browser. |
If you add a hotswap tool, a Java class change updates in the running app instead of restarting it, and the app state stays. The full table is on the Redeployment and Live Reload page.
Recap: a Java change restarts the app and the browser follows. A stylesheet change never needs a reload.
Spring Boot DevTools browser reload
In a Spring Boot app, the webforJ build plugin delivers the development tools to development runs. You declare no dependency for them, and they never end up in the packaged app. A project created from an archetype already has the starter and the plugin:
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-spring-boot-starter</artifactId>
</dependency>
<plugin>
<groupId>com.webforj</groupId>
<artifactId>webforj-maven-plugin</artifactId>
<version>${webforj.version}</version>
<extensions>true</extensions>
</plugin>
Now turn live reload on in application.properties:
webforj.devtools.livereload.enabled=true
server.shutdown=immediate
Start the app as usual with mvn, or ./gradlew bootRun with Gradle. Java changes apply after a compile, stylesheet and image changes apply in place, and sources under src/main/frontend rebuild through the frontend watch.
Spring Boot DevTools is optional, because live reload works without it. If you want its restart model, add its dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
With Spring DevTools present, a compiled change restarts the Spring context and the browser refreshes when the restart completes. With a hotswap tool configured as well, the tool applies the class updates and the restart stays off.
Recap: one property turns live reload on, DevTools is an optional add-on, and the build plugin keeps all of it out of your packaged app.
Hot reload for a Java web UI
The other half of the loop is the browser. With the app running, you can watch what happens when the server restarts. Applied styles stay on the page, and an indicator shows while the server is down. The page reloads when the app is ready, not before, so you never land on an error page halfway through a restart.
Several keys tune the connection between the browser and the app:
| Property | Default | Description |
|---|---|---|
webforj.devtools.livereload.enabled | false | Turns live reload on for development runs. |
webforj.devtools.livereload.websocket-port | 35730 | Port for the browser connection. |
webforj.devtools.livereload.websocket-path | /webforj-devtools-ws | Path for the browser connection. |
webforj.devtools.livereload.static-resources-enabled | true | Applies stylesheet and image changes in place instead of reloading the page. |
webforj.devtools.livereload.heartbeat-interval | 30000 | Interval in milliseconds for the connection checks that detect a restarting server. |
The defaults work for most projects, so enabled is usually the only key you set. None of these keys has any effect in a packaged app.
Recap: the browser connects to the running app, waits out a restart, and reloads once the app is ready.
Frontend watch for CSS changes
CSS is where you'll feel live reload the most. A stylesheet edit applies in place, so form data and scroll position stay exactly where they were. The same goes for an image. Sources under src/main/frontend are rebuilt by the frontend watch, which needs webforj.devtools.livereload.enabled to be on.
Run the watch goal before the goal that starts the app. An archetype project sets this as its default goal, so mvn with no arguments runs both:
mvn compile webforj:watch spring-boot:run
What the browser does depends on the output the rebuild produces:
| Output | Browser action |
|---|---|
Stylesheet, from a .css, .scss, .sass, or .less source | Applied in place. No reload, form data and scroll position stay. |
| Image | Swapped in place. No reload. |
Any other output, such as compiled .ts, .tsx, or .js | The view reloads. |
When one rebuild produces several files, the browser applies them in place only if every file qualifies. Otherwise it reloads once, so a change never applies partially. Read more on the frontend bundler page.
Recap: styles and images change in place, scripts reload the view, and mvn compile webforj:watch spring-boot:run starts it all.
