Spring Boot MVC Application returns HTTP 404 when deployed to an external Tomcat/tc Server instance

Gustavo Ramos picture Gustavo Ramos · Jun 8, 2015 · Viewed 7.3k times · Source

I'm developing a simple application using Spring Boot plus Spring web starter. It goes very well when I'm testing with the embedded Tomcat server (JAR packaging). I need to debug some stuff so I thought it would be better to deploy it as a WAR on an external Tomcat Server (or really an external Pivotal tc Server bundled on STS).

I followed the procedures stated on Spring Boot's Documentation and when running the application I can see the logs loading my controllers, requests, etc (Yay? Nay.). Once the container is up, any requests lead to an ugly 404.

I understand Spring Boot will spawn a Servlet 3 compliant container, so a web.xml file should not be strictly required. All I have to do is point my application's entry point to a class which extends SpringBootServletInitializer. Here it is:

package com.company.ci.integration;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class GitlabWebhookProcessingApplication extends
        SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(GitlabWebhookProcessingApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder application) {
        return application.sources(GitlabWebhookProcessingApplication.class);
    }

}

I point this class on my POM file like this:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <start-class>com.chemtech.ci.integration.GitlabWebhookProcessingApplication</start-class>
        <java.version>1.7</java.version>
    </properties>

As stated on the documentation above, this should magically work and my application would be loaded and works as expected.

Ah, here goes the logs:

Servlet Mappings:

2015-06-07 20:21:16.870  INFO 3373 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2015-06-07 20:21:16.871  INFO 3373 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'errorPageFilter' to: [/*]
2015-06-07 20:21:16.872  INFO 3373 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-06-07 20:21:16.872  INFO 3373 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

Controller actions mapping:

2015-06-07 20:21:20.278  INFO 3373 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/webhooks/mergeRequestComment],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public void com.chemtech.ci.integration.controller.WebhookController.MergeRequestCommentReceiver(java.lang.String,com.chemtech.ci.integration.model.MergeRequestCommentEventRequestBody)
2015-06-07 20:21:20.282  INFO 3373 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-06-07 20:21:20.282  INFO 3373 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],methods=[],params=[],headers=[],consumes=[],produces=[text/html],custom=[]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)

It is important to emphasize this works beautifully using an executable JAR with embedded server. I'm scratching my head over this for a while and even tried to do as stated on some other SO threads:

Spring Boot - custom 404 page with standalone tomcat

http://forum.spring.io/forum/spring-projects/web/745458-spring-boot-v1-0-0-rc3-not-resolving-views-404-error (not totally related)

Am I doing something wrong here? (well, of course I am. this is a purely rhetorical question)

Any help will be much appreciated.

Thanks!

Answer

Gustavo Ramos picture Gustavo Ramos · Jun 8, 2015

Well, it's a rather embarrassing answer, but the problem was I forgot when deploying wars on tc Server / Tomcat the root context will be the WAR's name by default.

So, while http://server.ip:8080/controller/method won't work, http://server.ip:8080/war-package-name/controller/method beautifully works.

As a note to self, never trust yourself when working on a sunday night.

Thanks everyone, and hope this helps someone in the future!