How to Configure H2 Database Console in Spring WebFlux Applications
Purpose
This post demonstrates how to configure the H2 database console in Spring WebFlux applications. The standard spring.h2.console.enabled property doesn’t work with WebFlux, so we need a manual approach.
Environment
- Spring Boot 3.x
- Spring WebFlux (spring-boot-starter-webflux)
- H2 Database 2.x
- Embedded server: Netty
The Challenge
Spring WebFlux uses Netty as its embedded server, which is a reactive, non-blocking server. The H2 console servlet requires a servlet container like Tomcat, so the auto-configuration is skipped.
spring.h2.console.enabled=true ↓H2ConsoleAutoConfiguration checks: @ConditionalOnServlet? ↓Netty detected → Condition fails → Auto-configuration skipped ↓No H2 console endpoint registeredThe solution is to manually start an H2 web server using org.h2.tools.Server.
The Solution
Step 1: Create H2 Server Configuration Component
Create a component that manages the H2 server lifecycle:
package com.example.config;
import org.h2.tools.Server;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.event.ContextClosedEvent;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.context.event.EventListener;import org.springframework.stereotype.Component;
import java.sql.SQLException;
@Componentpublic class H2ServerConfig {
private Server webServer;
@Value("${h2-server.port:8081}") private Integer h2ConsolePort;
@EventListener(ContextRefreshedEvent.class) public void start() throws SQLException { this.webServer = Server.createWebServer( "-webPort", h2ConsolePort.toString(), "-tcpAllowOthers" ).start(); System.out.println("H2 Console available at: " + webServer.getURL()); }
@EventListener(ContextClosedEvent.class) public void stop() { if (this.webServer != null) { this.webServer.stop(); } }}Key parts explained:
@Component- Spring manages this bean@EventListener(ContextRefreshedEvent.class)- Starts server when application context is ready@EventListener(ContextClosedEvent.class)- Stops server on application shutdownServer.createWebServer()- Creates standalone H2 web server-webPort- Specifies the port for H2 console-tcpAllowOthers- Allows remote connections (useful for development)
Step 2: Configure Application Properties
# H2 datasource configurationspring: datasource: url: jdbc:h2:mem:testdb driverClassName: org.h2.Driver username: sa password:
# Custom H2 server port (separate from application port)h2-server: port: 8081
# Application runs on port 8080server: port: 8080I use port 8081 for H2 console to avoid conflict with the application port (8080).
Step 3: Fix H2 Dependency Scope
The H2 dependency must not have runtime scope, otherwise the Server class won’t be available:
<!-- WRONG: runtime scope blocks Server class --><dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope></dependency>
<!-- CORRECT: compile scope allows Server class --><dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <!-- No scope specified = compile scope --></dependency>How It Works
When the application starts:
1. Spring context refreshes ↓2. @EventListener triggers H2ServerConfig.start() ↓3. Server.createWebServer("-webPort", "8081", "-tcpAllowOthers") ↓4. webServer.start() launches standalone H2 web server ↓5. H2 console available at http://localhost:8081The org.h2.tools.Server class creates a completely separate web server that runs independently of Spring. It has no dependency on servlet containers.
When I start the application:
Netty started on port(s): 8080H2 Console available at: http://localhost:8081Started Application in 2.8 secondsConnecting to H2 Console
After startup, access the H2 console at http://localhost:8081:
JDBC URL: jdbc:h2:mem:testdbUsername: saPassword: (empty)You can now inspect tables, run queries, and debug your database.
Best Practices
- Use a separate port - Run H2 console on a different port (8081) from your application (8080)
- Log the URL - Print the H2 console URL at startup for easy access
- Secure for production - Don’t use
-tcpAllowOthersin production environments - Profile-based activation - Only enable H2 server in development profile:
@Component@Profile("dev") // Only active in developmentpublic class H2ServerConfig { // ... same configuration}Summary
In this post, I showed how to configure H2 database console in Spring WebFlux applications. The key point is to manually start an H2 web server using org.h2.tools.Server with Spring event listeners, since the servlet-based auto-configuration doesn’t work with Netty.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Stack Overflow: Spring boot H2 console returns 404
- 👨💻 H2 Database Server Documentation
- 👨💻 GitHub: webflux-netty-server-h2-example
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments