Skip to content

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.

Why auto-configuration fails
spring.h2.console.enabled=true
H2ConsoleAutoConfiguration checks: @ConditionalOnServlet?
Netty detected → Condition fails → Auto-configuration skipped
No H2 console endpoint registered

The 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:

H2ServerConfig.java
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;
@Component
public 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 shutdown
  • Server.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

application.yml
# H2 datasource configuration
spring:
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 8080
server:
port: 8080

I 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:

pom.xml
<!-- 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:

Startup flow
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:8081

The 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:

Console output
Netty started on port(s): 8080
H2 Console available at: http://localhost:8081
Started Application in 2.8 seconds

Connecting to H2 Console

After startup, access the H2 console at http://localhost:8081:

H2 Console Login
JDBC URL: jdbc:h2:mem:testdb
Username: sa
Password: (empty)

You can now inspect tables, run queries, and debug your database.

Best Practices

  1. Use a separate port - Run H2 console on a different port (8081) from your application (8080)
  2. Log the URL - Print the H2 console URL at startup for easy access
  3. Secure for production - Don’t use -tcpAllowOthers in production environments
  4. Profile-based activation - Only enable H2 server in development profile:
Profile-based H2 server
@Component
@Profile("dev") // Only active in development
public 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:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments