I need a configuration free, deployable war, myapp1.war that can retrieve the configuration files from the tomcat/lib folder. As I have other web applications coexisting on the same Tomcat: myapp2.war, myapp3.war, I need this layout:
tomcat/lib/myapp1/application.properties
tomcat/lib/myapp2/application.properties
tomcat/lib/myapp3/application.properties
This way I can build the war files without any properties files inside the war and deploy on any server.
I have read the Spring documentation but it explains how to set the location when running as a jar:
java -jar myapp.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
I cannot figure out how to do this for the case of multiple coexisting war files.
I would like to know if this is possible or should I give up on Spring Boot and go back to the traditional Spring MVC applications.
A solution could be to load application-{profile}.properties as @PropertySource annotations as this question suggests, but then the logging system wont work, as you can see in the documentation .
The logging system is initialized early in the application lifecycle and as such logging properties will not be found in property files loaded via @PropertySource annotations.
This means that your logging properties in application-{profiles}.properties like:
logging.config=classpath:myapp1/logback.xml
logging.path = /path/to/logs
logging.file = myapp1.log
will be ignored and the logging system wont work.
To solve this I have used the SpringApplicationBuilder.properties() method to load properties at the beginning, when the application is configured. There I set the 'spring.config.location' used by Spring Boot to load all the application-{profiles}.properties:
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
return springApplicationBuilder
.sources(Application.class)
.properties(getProperties());
}
public static void main(String[] args) {
SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
.sources(Application.class)
.properties(getProperties())
.run(args);
}
static Properties getProperties() {
Properties props = new Properties();
props.put("spring.config.location", "classpath:myapp1/");
return props;
}
}
Then I have moved the properties files from src/main/resources to src/main/resources/myapp1
.
├src
| └main
| └resources
| └myapp1
| └application.properties
| └application-development.properties
| └logback.xml
└─pom.xml
In the pom.xml I have to set the scope of embedded tomcat libraries as "provided". Also, to exclude all properties files in src/main/resources/myapp1 from the final war and generate a configuration free, deployable war:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingExcludes>
**/myapp1/
</packagingExcludes>
</configuration>
</plugin>
Then in Tomcat I have
├apache-tomcat-7.0.59
└lib
├─myapp1
| └application.properties
| └logback.xml
└─myapp2
└application.properties
└logback.xml
Now I can generate the configuration free war and drop it into the apache-tomcat-7.0.59/webapps folder. Properties files will be resolved using the classpath, independently for each webapp:
apache-tomcat-7.0.59/lib/myapp1
apache-tomcat-7.0.59/lib/myapp2
apache-tomcat-7.0.59/lib/myapp3
With Spring 4.2 and @Annotation config and tomcat on linux serveur
In your Application class set the @PropertySource like that :
@Configuration
@EnableWebMvc
@PropertySource(value = { "classpath:application-yourapp.properties"})
@ComponentScan(basePackages = "com.yourapp")
public class YourAppWebConfiguration extends WebMvcConfigurerAdapter {
...
}
Now you just need to include the property file in your classpath
In production
Deploy your .war files ( or anything ) on tomcat, and put your application-yourapp.properties anyway on your production machine. ( for exemple in /opt/applyconfigfolder/application-yourapp.properties" )
Then in your tomcat ( here tomcat 7 ) open bin\\catalina.sh
You have this line
# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=
Just add the path of the folder which contains application.properties
CLASSPATH=:/opt/applyconfigfolder
If you have already some classpath define you can add it
CLASSPATH=:/opt/applyconfigfolder:/yourpath1:/yourpath2:
I haven't try with windows but I think there is no problem
In Dev ( with eclipse )
├src
| └main
| └ ....
└config
| └application-yourapp.properties
instead of src/main/resources/application-yourapp.properties
Now in eclipse add your config folder to classpath, go to "Run Configurations" of your tomcat server ( or equivalent ) and add the folder Config to User Entries
Ok that's it, your application.properties is out of the application and your project run perfectly in dev environment.
Daniel Mora gave a good solution but instead of using spring.config.location you can use spring.config.name ( https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files ), so you can have different properties file for different web apps in the same tomcat/lib directory:
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
return springApplicationBuilder
.sources(Application.class)
.properties(getProperties());
}
public static void main(String[] args) {
SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(Application.class)
.sources(Application.class)
.properties(getProperties())
.run(args);
}
static Properties getProperties() {
Properties props = new Properties();
props.put("spring.config.name", "myapp1");
return props;
}
}
I think that the lib directory is for third party libraries not for storing configuration properties for your web apps. So I think that a better solution is to add an external folder as additional classpath folder using shared.loader property in conf/catalina.properties:
shared.loader=${catalina.base}/shared/configurations
You can put your application properties app1.properties, app2.properties, ecc.. in apache-tomcat-7.0.59/shared/configurations.
Before finding Daniel Mora solution of overridding configure method of SpringBootServletInitializer my solution was to add a context.xml in src/main/webapp/META-INF with this content:
<Context>
<Environment name="spring.config.name" value="myapp1" type="java.lang.String" override="false" description="define the property file for srping boot application"/>
</Context>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.