We have a database library that gets the connection information (user, host, etc) from a properties file. This file can be a config.properties file located in the classpath, or next to the execution jar or can be passed as an argument -Dproperties=/path/to/myConfig.properties.
We also have several applications that use this library, so each one has its own config.properties file used in its own execution.
But now I'm creating two web applications that use the same library. So, if I deploy them in Tomcat (war file), I have two options (to my knowledge):
1.- Include each config inside the WAR file. But with this, every time I need to tweak something in the config.properties I'll have to repack the war.
2.- Pass the -Dproperties parameter as an execution argument of Tomcat. But different war deployments will have to share the same properties file.
Is there a way around this?
Can I pass the -D argument to a specific deployment in Tomcat (or any other server)?
PS: This is one of the scenarios we have, but is not constraint to database connection info. We have other libraries that get parameters through config.properties file.
EDIT: I want to be able to have different config.properties file for each deployment. Not the same properties shared among them.
I think I found a way around using self contained webserver inside the application, like Jetty.
We've a similar requirement in which we share a common property file between different applications deployed into JBoss EAP server.
In $JBOSS_HOME/bin/standalone.conf file you can add configuration file path as below:
JAVA_OPTS="$JAVA_OPTS -DCONFIG_LOCATION=/external/config/configuration.properties"
Start the server with above specified property and within your application you can read this property file with apache commons-configuration api as below:
try {
props = new PropertiesConfiguration(System.getProperty("CONFIG_LOCATION"));
FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
// Delay 30s
// strategy.setRefreshDelay(30000);
props.setReloadingStrategy(strategy);
} catch (ConfigurationException e) {
e.printStackTrace();
}
With this reload strategy you can change your properties while your server is running. Also you can specify the interval after which all properties specified in the external file needs to be refreshed within your application without bouncing it. Hope this helps!
You can create an environment variable whose value will be the path where the properties file are located. Later use this environment variable will creating bean for property placeholder config.
for UNIX, you can add in your bash profile file
export CONF_DIR=/path/to/conf
And in spring context file, add this
<context:property-placeholder
location="file:///${CONF_DIR}/path/myConfig1.properties,
file:///${CONF_DIR}/path/myConfig2.properties"
properties-ref="applicationDefaultProperties" ignore-resource-not-found="false"
ignore-unresolvable="false"/>
So, when you want to change any thing in the properties file, you can change at one location, and then restart the application to load the new values in your app.
So, if your config file is this
db.user=username
db.password=password
Inside java class, you can use the keys as like this
#Value("${db.user")
private String username;
#Value("${db.password")
private String password;
The solution I found for my problem is using an embedded web server in my application. In my case, I'm using Jetty.
Now I pack my application as an executable jar and pass the system parameters as -D arguments and they live inside the instance of the application.
Like this:
java -Dproperties=config.properties -jar java_app_with_embedded_server.jar
Related
I am trying override few of the properties in my spring boot application. The properties are spread across mutiple yml files within the same directory and hence i would like to specify spring.config.additional-location parameter with the value of directory..
spring.config.additional-location=file:///Mydirectory/
But the application is not able to load the configs. If I explicitly specify the file name, the properties are getting overwritten
spring.config.additional-location=file:///Mydirectory/application.yml
Is it possible to load all the files available in a directory using spring.config.additional-location? If yes, please let me know
We have an application which consists of a war file, and two properties files.
under normal circumstances we just drop the war into /webapps (jetty) and the config into /resources and everything runs up fine.
How do we do that with embedded jetty?
So I have a class file which can create an embedded jetty server and deploy the war file using :
WebAppContext ctx = new WebAppContext(warfileLocation,"/");
The server runs up, but the application doesn't start because it cannot find properties referenced by the application, which expects to find the .properties file on the classpath.
How to I deploy the config properties files programatically to the embedded jetty context?
Presumably by using some method on the context to reference files on my local disk?
Thanks.
A WebAppContext is classloader isolated from the Server classpath, making content available on the Server classpath unavailable to the WebAppContext.
You have two choices.
Flip the rules for the classloader isolation.
If you have only 1 WebAppContext in your embedded-jetty, and you don't care about the classloader isolation, call WebAppContext.setParentLoaderPriority(true);
Add the specific classpath entry you need to the WebAppContext.
You can call WebAppContext.setExtraClasspath(String) to add any arbitrary classpath entries you want to the WebAppContext prior to it being added to the HandlerCollection and started/deployed.
Your main goal is that your config ends up in the application's classpath. How you do it depends on your use cases.
You can put the .properties files under project/src/main/resources of your jar (the one that is running the embedded Jetty) which is automatically on the classpath.
This is useful in development, but this mean the configuration files will be included in your compiled jar file. That is unless you explicitly exclude them in your Maven/Gradle build file if you are using one. For production use you may want to externalize your configuration.
For example you can put the configuration files into an external configs folder and then run your jar using java -classpath my.jar:configs/ Main.
Any files in external configs folder should now be on your classpath.
There are of course other options to modify classpath. Please see Setting the class path. If you still want to run using -jar option you can modify the classpath in META-INF/MANIFEST.mf. This option is described here.
All,
I have found a solution using 'extraClassPath'
//add application config properties
String resourcesDirectory = System.getProperty("resourcesDirectory");
if (resourcesDirectory!=null) {
String ecp = ctx.getExtraClasspath();
ecp = ecp + "," + resourcesDirectory;
ctx.setExtraClasspath(ecp);
}
Where ctx is the context returned from :
WebAppContext ctx = new WebAppContext(warfileLocation,"/");
Essntially you can add a local directory to the classpath of the embedded jetty server using this method. Anything in that path will appear in the classpath
Where can i store SLF4J configuration file so that all production and test environment may have access to it? I want to store the config file outside of the web app at an arbitrary location and retrieve that location upon startup. I also want to allow for changing location of the config file so no classpath. Im thinking about using getters and setters to retrieve the file path.
Any ideas??
slf4j is (for all practical purposes) just the API. You need a backend which does the actual work.
If you use logback you can ship a logback.xml file with your application which just includes another file. If I recall correctly the filename string can hold a ${variable} which you can then define outside your application.
See https://logback.qos.ch/manual/configuration.html#configFileProperty
You may specify the location of the default configuration file with a system property named "logback.configurationFile". The value of this property can be a URL, a resource on the class path or a path to a file external to the application.
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
I need to get the path of catalina.out file which is configured in the logging.properties.
Is there a way to retrieve the property "1catalina.org.apache.juli.FileHandler.directory" via java without knowing the path to the properties file?
If I have understood you correctly, then you want to read an attribute of the Tomcat logging.properties file. As you can see here in the Tomcat FAQ for Logging, java.util.logging.config.file is used to define the path to the property file.
You can then retrieve this path via Java System Properties:
String pathLogProps = System.getProperty("java.util.logging.config.file");
Properties properties = new Properties();
try {
properties.load(new FileInputStream(pathLogProps));
System.out.println(prop.getProperty("database"));
} catch (IOException ex) {
ex.printStackTrace();
}
If this is not set, I would follow the hints from the Apache Tomcat 7 Logging Documentation:
JULI is enabled by default, and supports per classloader
configuration, in addition to the regular global java.util.logging
configuration. This means that logging can be configured at the
following layers:
Globally. That is usually done in the ${catalina.base}/conf/logging.properties file. The file is specified
by the java.util.logging.config.file System property which is set by
the startup scripts.
If it is not readable or is not configured, the default is to use the ${java.home}/lib/logging.properties file in the JRE. In the web
application. The file will be WEB-INF/classes/logging.properties
Per default the path to the logging.properties file should be available over the environment variable catalina.base, respectively CATALINA_BASE.
The file catalina.out is specified neither in any system property, nor is is specified in logging.properties (take a look, it isn't there).
Instead, catalina.out is created by the launching script's shell-based output redirection from within bin/catalina.sh (or bin/catalina.bat). That means that this file is only available if you have launched Tomcat using those scripts, or scripts that emulate this behavior. For example, if you use jsvc on a *NIX platform, or the Tomcat Windows Service, then the file logs/catalina.out does not get created (at least not by default).
If you want to take a peek to see if the file exists, you can bet on it being in $CATALINA_BASE/logs/catalina.out. Recent versions of Tomcat define the catalina.base system property so you can easily take a look like this:
File catalinaOut = new File(System.getProperty("catalina.base"), "logs/catalina.out");
if(catalinaOut.exists())
{
// Do whatever you want
}
I need to have hibernate database config set from outside text file, how can I do it? Is there some kind of method for this, or do I have to make my own?
You can programaticaly configure hibernate within your app: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/session-configuration.html#configuration-programmatic
HTH
Hibernate configuration file (*.cfg.xml) have to be in the class path of your application's war.
But, you can maintain file like 'install.properties' in deployment folder of your application.
Inside it you can maintain database related properties.For eg.
database.name =
database.hostname=
database.username=
databse.password=
Use some predefined constant string inside 'hibernate.cfg.xml' that you can replace during time of application deployment task. For eg.
<property name="hibernate.connection.url">jdbc:mysql://$database.hostname/$database.name</property>
you can write an 'ant' task which 'unwar' the war then replace constant strings with values as mentioned inside 'install.properties' and then make 'war' again.
In this way you can separate out configuration settings from application code structure.
Hibernate configuration files have to be on the class path but can be outside your war. The exact way to add a directory or files to the class path will depend on your app server so you'll have to mention which one you're using (for Tomcat, see this previous question for example).