loganasherjones
loganasherjones

Reputation: 1062

Tomcat Not reading Spring-Boot Application Properties

I'm fairly new to spring/java and have been checking out spring-boot for a project I have at work. I've been following guides and finally have a (semi) working web app MVC + JPA for data access. Everything works when I deploy the app via the Jar method :

java -jar build/libs/client.jar

However, our application is eventually going to be deployed to Tomcat (v7.0.40) so I need to create a war file from the project. I've followed the converting jars to war's guide on the spring.io site and have run into a problem. It appears that it is not loading up the application.properties file. Here are the important code snippets:

src/main/java/hello/GreetingController:

@Controller
@Configuration
public class GreetingController {
    @Value("${app.username}")
    private String username;

    @RequestMapping("/greeting")
    public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
        model.addAttribute("name", name);
        model.addAttribute("username", username);
        return "greeting";
    }
} 

src/main/java/hello/Application.java

@ComponentScan
@EnableAutoConfiguration
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

src/main/java/hello/HelloWebXml.java

public class HelloWebXml extends SpringBootServletInitializer {

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

src/main/resources/application.properties

app.username=foo

for completeness, here is the build.gradle:

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-snapshot" }
        mavenLocal()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6")
    }
}

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

war {
    baseName = 'client'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-snapshot" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M6")
    compile("org.thymeleaf:thymeleaf-spring3:2.0.16")
    testCompile("junit:junit:4.11")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.8'
}

I build the application:

gradle clean build

Drop the war in tomcat, and then tail out the logs and see the following:

SEVERE: ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]
.StandardHost[localhost].StandardContext[/client]]
...
...
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating the bean
with name 'greetingController': Injection of autowired dependencies failed; nested exception
is java.lang.IllegalArgumentException: Could not resolve placeholder 'app.username' in string
value "${app.username}"
...
...
...

As I said, it works when I run it via a jar, but does not work when I deploy it to Tomcat. I also looked inside $TOMCAT_HOME/webapps/client/WEB-INF/classes and I see the application.properties file. So I think that it should be on the classpath. My question is, why isn't tomcat loading it? I've tried searching all over and no one else seems to be having this problem so I'm not sure if its just something I have incorrectly configured, or what.

Thanks in advance.

Upvotes: 28

Views: 39112

Answers (4)

Jake OS
Jake OS

Reputation: 190

I think for those who change default naming "application.[properties,yaml,etc]" to, for example, "service.[properties,yaml,etc]", can add this into the build.gradle task as:

bootRun {
    systemProperties = [
       'spring.config.name':'service'
    ]
}

Upvotes: 0

Jiss Janardhanan
Jiss Janardhanan

Reputation: 188

I came here searching for the same issue. application.properties not loading when spring boot application run as a war inside tomcat but it was working fine when running with embedded tomcat. the issue turned out to be in the file name . I had used Application.properties instead of application.properties . when running from tomcat it looks like it is case sensitive . Putting it here so that if someone commits the same stupid mistake as i did

2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./config/application.xml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./config/application.yml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./config/application.properties' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./config/application.yaml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./application.xml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./application.yml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./application.properties' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'file:./application.yaml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/config/application.xml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/config/application.yml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/config/application.properties' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/config/application.yaml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/application.xml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/application.yml' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/application.properties' resource not found 2015-09-10 14:42:13,982 DEBUG o.s.b.c.c.ConfigFileApplicationListener [ContainerBackgroundProcessor[StandardEngine[Catalina]]] Skipped config file 'classpath:/application.yaml' resource not found

Upvotes: 0

matsev
matsev

Reputation: 33749

The problem is that you attempt to use a @Value annotation inside your @Configuration class. From the JavaDoc of the @PropertySource:

In order to resolve ${...} placeholders in <bean> definitions or @Value annotations using properties from a PropertySource, one must register a PropertySourcesPlaceholderConfigurer. This happens automatically when using <context:property-placeholder> in XML, but must be explicitly registered using a static @Bean method when using @Configuration classes.

e.g. add the following lines to the @Configuration class:

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

However, in your example, a more suitable approach is to move the @Configuration annotation from the GreetingController class (it does not contain any configuration) to the Application class. Since the Application class does not contain any @Value annotation it should work without the suggested addition of the static PropertySourcesPlaceholderConfigurer bean.

Upvotes: 12

codecraig
codecraig

Reputation: 3158

follow this guys advice: http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html

try:

@PropertySources(value = {@PropertySource("classpath:application.properties")})

then boom sauce for the win.

Upvotes: 25

Related Questions