user8280225
user8280225

Reputation:

How to enable h2-console in spring-webmvc without spring-boot?

My application is build with spring-webmvc and spring-jdbc without spring-boot. In my application.properties I have:

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

datasource.dbname=users
datasource.script=classpath:resources/users.sql

But it does not start h2-console because I don't have spring-boot-devtools, but do I need it? So I added Server bean from org.h2.tools package like this:

// The web server is a simple standalone HTTP server that
// implements the H2 Console application.  localhost:8082
@Bean(initMethod = "start", destroyMethod = "stop")
public Server h2Server() throws SQLException {
    return Server.createWebServer();
}

And now I can access web-console at localhost:8082 and connect to jdbc:h2:mem:users, but I think this is not a solution, but a workaround, because I added the DataSource bean using the EmbeddedDatabaseBuilder like this:

@Bean
public DataSource dataSource(
        @Value("${datasource.dbname}") String dbname,
        @Value("${datasource.script}") String script) {

    return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .setName(dbname)
            .addScript(script)
            .build();
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}

Is there a spring way to enable h2-console in spring-webmvc without spring-boot? Or is this the normal way to enable it?

pom.xml:

<!-- spring -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

<!-- h2 database -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
</dependency>

<!-- servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

Upvotes: 2

Views: 3361

Answers (3)

Tuan Hoang
Tuan Hoang

Reputation: 686

First, you need to define dataSource

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .generateUniqueName(false)
            .setName("testdb")
            .setType(EmbeddedDatabaseType.H2)
            .setScriptEncoding("UTF-8")
            .ignoreFailedDrops(true)
            .addScripts("sqlscripts/schema.sql", "sqlscripts/data.sql")
            .build();
    }

Then you can implement WebApplicationInitializer and override onStartup

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.h2.server.web.WebServlet;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

public class ApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //bootstrap dispatcher servlet
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(ApplicationConfig.class); // whatever config that you want to register

        ServletRegistration.Dynamic h2ServletRegistration = servletContext.addServlet(
            "h2-console",
            new WebServlet()
        );
        h2ServletRegistration.setLoadOnStartup(1);
        h2ServletRegistration.addMapping("/console/*");
    }
}

And since you use h2ServletRegistration.addMapping("/console/*");, remember to access to h2-console via the url pattern like http://localhost:8080/<app-name>/console

My spring version is 5.3.16 and h2 is 2.1.210

Upvotes: 0

Tom Silverman
Tom Silverman

Reputation: 794

Spring Boot takes care of the h2-console servlet registration magic, but it's pretty easy to solve with vanilla spring (not spring-boot) too, using any implementation of 'WebApplicationInitializer' such as 'AbstractSecurityWebApplicationInitializer'. For example, adding the dispatcher servlet and the h2-console in a Servlet 3.0+ environments (no web.xml):

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext container) {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class, SecurityConfig.class, WebConfig.class);
        context.setServletContext(container);
        ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(context));
        servlet.setInitParameter("throwExceptionIfNoHandlerFound", "true");
        servlet.setLoadOnStartup(1);
        servlet.addMapping("/");

        ServletRegistration.Dynamic h2Console = container.addServlet("h2-console", new WebServlet());
        h2Console.setInitParameter("-webAllowOthers", "");
        h2Console.setLoadOnStartup(1);
        h2Console.addMapping("/h2/*", "/h2-console/*");
    }
}

Without spring-boot you'll need to manually configure maven (or gradle) dependencies for the entire Spring web tier, including those libraries required by Tomcat (if not embedded) and naturally, the h2 dependency:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>${h2.version}</version>
</dependency>

Upvotes: 1

gtiwari333
gtiwari333

Reputation: 25156

It appears you need to register a org.h2.server.web.WebServlet to your servlet mapping.

From the comments at WebServlet:

This servlet lets the H2 Console be used in a standard servlet container such as Tomcat or Jetty.

See also:

Upvotes: 2

Related Questions