Opoo Opoo - 1 month ago 18
reST (reStructuredText) Question

Spring Tomcat 404 resource not found

I'm trying to deploy an simple REST api with Spring inside a Tomcat installation, but all I'm getting are 404 resource not found when the war is deployed. It's running perfectly on localhost, but deploying is just not working. Tried every solution on stackoverflow, but almost all use configuration files instead of configuration annotations. This is my (important) code.

slember.gradle

buildscript {
ext {
springBootVersion = '1.4.1.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
apply plugin: 'idea'
apply plugin: 'war'

springBoot{
executable = true
}

war {
baseName = 'slember'
}

jar {
baseName = 'slember'
}
sourceCompatibility = 1.7
targetCompatibility = 1.7

repositories {
mavenCentral()
}


dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile 'org.hibernate:hibernate-core:5.0.9.Final'
compile("com.h2database:h2")
testCompile('org.springframework.boot:spring-boot-starter-test')
compile 'javax.servlet:javax.servlet-api:3.1.0'
compile 'org.javassist:javassist:3.15.0-GA'
compile 'mysql:mysql-connector-java:5.1.31'
compile 'commons-dbcp:commons-dbcp:1.4'
compile('org.springframework.boot:spring-boot-starter-jdbc')
compileOnly "org.projectlombok:lombok:1.16.10"
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")


}


SlemberApplication.java

@SpringBootApplication
@EntityScan(basePackageClasses = {
SlemberApplication.class
})
public class SlemberApplication {

public static AnnotationConfigApplicationContext context;

public static void main(String[] args) {

SpringApplication.run(SlemberApplication.class, args);
context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();
}
}


META-INF/MANIFEST.MF

Manifest-Version: 1.0
Main-Class: com.letscode.SlemberApplication

Answer

SpringBootServletInitializer

Your code sample only shows a main method. When deploying as a WAR, the main isn't executed. You need to extend SpringBootServletInitializer:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

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

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

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

BTW, why do you use AnnotationConfigApplicationContext to register AppConfig instead of letting Spring Boot picking it up ? Either :

  • AppConfig is in the same package (or below) of your SlemberApplication: it's loaded by default;
  • move SlemberApplication so that it is higher (in the packages) than all your @Configuration/@Component classes (and then the previous point would apply);
  • or you add @ComponentScan to specify AppConfig's package.

You could use something like this:

@ComponentScan(basePackageClasses={AppConfig.class, SlemberApplication.class})
@SpringBootApplication
public class SlemberApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        super.configure(builder);
    }
    public static void main(String[] args) {
        new SpringApplicationBuilder().build().run(SlemberApplication.class, args);
    }
}