Search code examples
spring-bootembedded-jettyhawtio

How to run hawt.io in spring boot application with embedded tomcat


I would like to add hawt.io as an embedded component to my spring boot 'fat jar' application which has an embedded tomcat server.

How can I do this? How could I deploy the hawt.io war file?

UPDATE: I added the dependencies:

  • hawtio-web
  • hawtio-core
  • hawtio-plugin-mbean
  • hawtio-springboot to my pom

When I start the application now and open the url localhost:8080/hatio/index.html I get the login page presented. Since I don't know username and password I the added hawtio.authenticationEnabled=false to my application.properties

But - now I get a warning ' WARN 3420 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound : Request method 'POST' not supported' followed by a a null pointer exception.

References: http://hawt.io/configuration/index.html


Solution

  • I had exactly the same issue - and here is how I solved the problem.

    I found out that spring-boot doesnt support legacy web.xml configuration which is what you get when the maven-war-plugin does the overlay of the hawtio-web project on top of your own war. The resulting war contains both your web code as well as the content of the hawtio-web archive.

    See http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html

    So I started the process of configuring the servlets and filters in spring.

    First add the necesary dependencies to pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
            <version>${spring-boot-version}</version>
        </dependency>
        <dependency>
            <groupId>io.hawt</groupId>
            <artifactId>hawtio-springboot</artifactId>
            <version>${hawtio.version}</version>
        </dependency>
        <dependency>
            <groupId>io.hawt</groupId>
            <artifactId>hawtio-core</artifactId>
            <version>${hawtio.version}</version>
        </dependency>
    </dependencies>
    

    Im using these versions:

    <hawtio.version>2.0.0</hawtio.version>
    <spring-boot.version>1.2.3.RELEASE</spring-boot.version>
    

    Add a Configuration class to configure the servlets and filters:

    @Configuration
    public class HawtioConfiguration extends WebMvcConfigurerAdapter {
    
        @Override
        public void addResourceHandlers(final ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/hawtio/plugins/**").addResourceLocations("/app/", "classpath:/static/hawtio/app/");
            registry.addResourceHandler("/hawtio/**").addResourceLocations("/", "/app/", "classpath:/static/hawtio/",
                    "classpath:/static/hawtio/app/");
        }
    
        @Override
        public void addViewControllers(final ViewControllerRegistry registry) {
            registry.addViewController("/hawtio/plugin").setViewName("forward:/plugin");
            registry.addViewController("/hawtio/").setViewName("redirect:/hawtio/index.html");
        }
    
        @Bean
        public ServletRegistrationBean userServlet() {
            return new ServletRegistrationBean(new UserServlet(), "/user/*", "/hawtio/user/*");
        }
    
        @Bean
        public ServletRegistrationBean jolokiaproxy() {
            return new ServletRegistrationBean(new ProxyServlet(), "/hawtio/proxy/*");
        }
    
        @Bean
        public ServletRegistrationBean kubeservice() {
            return new ServletRegistrationBean(new ServiceServlet(), "/hawtio/service/*");
        }
    
        @Bean
        public ServletRegistrationBean kubepod() {
            return new ServletRegistrationBean(new PodServlet(), "/hawtio/pod/*");
        }
    
        @Bean
        public ServletRegistrationBean fileupload() {
            return new ServletRegistrationBean(new UploadServlet(), "/hawtio/file-upload/*");
        }
    
        @Bean
        public ServletRegistrationBean loginservlet() {
            return new ServletRegistrationBean(new LoginServlet(), "/hawtio/auth/login/*");
        }
    
        @Bean
        public ServletRegistrationBean logoutservlet() {
            return new ServletRegistrationBean(new LogoutServlet(), "/hawtio/auth/logout/*");
        }
    
        @Bean
        public ServletRegistrationBean keycloakservlet() {
            return new ServletRegistrationBean(new KeycloakServlet(), "/hawtio/keycloak/*");
        }
    
        @Bean
        public ServletRegistrationBean exportcontextservlet() {
            return new ServletRegistrationBean(new ExportContextServlet(), "/hawtio/exportContext/*");
        }
    
        @Bean
        public ServletRegistrationBean mavenSource() {
            return new ServletRegistrationBean(new JavaDocServlet(), "/hawtio/javadoc/*");
        }
    
        @Bean
        public ServletRegistrationBean contextFormatter() {
            return new ServletRegistrationBean(new ContextFormatterServlet(), "/hawtio/contextFormatter/*");
        }
    
        @Bean
        public ServletRegistrationBean gitServlet() {
            return new ServletRegistrationBean(new GitServlet(), "/hawtio/git/*");
        }
    
        @Bean
        public ServletListenerRegistrationBean hawtioContextListener() {
            return new ServletListenerRegistrationBean<>(new HawtioContextListener());
        }
    
        @Bean
        public ServletListenerRegistrationBean fileCleanerCleanup() {
            return new ServletListenerRegistrationBean<>(new FileCleanerCleanup());
        }
    
        @Bean
        public FilterRegistrationBean redirectFilter() {
            final FilterRegistrationBean filter = new FilterRegistrationBean();
            filter.setFilter(new RedirectFilter());
            filter.setUrlPatterns(Collections.singletonList("/hawtio/*"));
            return filter;
        }
    
        @Bean
        public FilterRegistrationBean sessionExpiryFilter() {
            final FilterRegistrationBean filter = new FilterRegistrationBean();
            filter.setFilter(new SessionExpiryFilter());
            filter.setUrlPatterns(Collections.singletonList("/hawtio/*"));
            return filter;
        }
    
        @Bean
        public FilterRegistrationBean cacheFilter() {
            final FilterRegistrationBean filter = new FilterRegistrationBean();
            filter.setFilter(new CacheHeadersFilter());
            filter.setUrlPatterns(Collections.singletonList("/hawtio/*"));
            return filter;
        }
    
        @Bean
        public FilterRegistrationBean CORSFilter() {
            final FilterRegistrationBean filter = new FilterRegistrationBean();
            filter.setFilter(new CORSFilter());
            filter.setUrlPatterns(Collections.singletonList("/hawtio/*"));
            return filter;
        }
    
        @Bean
        public FilterRegistrationBean XFrameOptionsFilter() {
            final FilterRegistrationBean filter = new FilterRegistrationBean();
            filter.setFilter(new XFrameOptionsFilter());
            filter.setUrlPatterns(Collections.singletonList("/hawtio/*"));
            return filter;
        }
    
        @Bean
        public FilterRegistrationBean AuthenticationFilter() {
            final FilterRegistrationBean filter = new FilterRegistrationBean();
            filter.setFilter(new AuthenticationFilter());
            filter.setUrlPatterns(Arrays.asList("/hawtio/auth/*", "/jolokia/*", "/hawtio/upload/*", "/hawtio/javadoc/*"));
            return filter;
        }
    
    }
    

    I have tested this with both jetty and tomcat - and it works with both. I have also submitted this as a patch to hawtio, but it is not released as of yet. You could compile hawtio yourself and import the HawtioConfiguration: https://github.com/hawtio/hawtio/blob/master/hawtio-springboot/src/main/java/io/hawt/springboot/HawtioConfiguration.java

    I have also updated the hawtio-sample to use the HawtioConfiguration: https://github.com/hawtio/hawtio/tree/master/hawtio-sample-springboot

    Now i can access hawtio by visiting http://localhost:8080/hawtio/index.html

    Hope this helps.

    Good luck.