Set custom property in Tomcat7 - java

We are running our application using Tomcat-7 in Windows environment. We are using Shibboleth IDP for our application, due to this we need to set system property at the container level to identify one new property called "idp.home". So we found that the property can be set in "catalina.properties". We set it and it was running successfully by using "idp.home" property but the problem is that if we use the same compiled war file in another machine, the property "idp.home" is not working.
cataline.properties
idp.home=../../IdP
Structure:
Build --> IdP
--> tomcat-->conf-->catalina.properties
Queries:
1) Is custom property "idp.home" cached in tomcat some where?
2) do we need to set "idp.home" property in any file along with the "catalina.properties" in tomcat.
3) Is there any other way to inform tomcat about "idp.home"?
Thanks in advance.

We can pass system properties with the -D parameter as VM arguments to tomcat, for example "-Dmy.prop.name=value"
or
Place system properties in a property file and specify the path of the property file in VM arguments, for example -Dcom.propertyfiles="path of the property File"

Related

The best way to make app configs editable for docker image/container?

I have an app which is dockerized like this:
FROM openjdk:11-jre-slim as jdkbase
FROM jdkbase
COPY target/dependency-jars /run/dependency-jars
COPY target/resources /run/resources
ADD target/app-1.0.2.jar /run/app-1.0.2.jar
CMD java -jar run/app-1.0.2.jar
This app uses some configs from application.properties. I push this docker image into my private registry for using it inside Kubernetes cluster.
There is no problems unless i have to change any properties in application.properties. Lets say, my database URL was changed. So, I have to undate it in application.properties and then force my app to use updated configs. I've tried to edit application.properties inside the running docker container and then restart the container. As a result, after i restart my container it has edited application.properties BUT the app still uses old URL.
The only way i've found to force the app to use new configs is to commit changed container into new image and then start the new image.
It works, but it doesn't seems to me to be an optimal solution: like, after every changes in app's configs I have to recreate image, which is +300Mb of data, I have to push this new image into registry, I have to recreate Kubernetes pod from new image... It looks like too much unnecessary actions to just change one URL.
So, is there any other more optimal way to work with needs to change application.properties from time to time?
If this is a spring boot application is easy to define a variable as an environment variable. If an environment variable is present it overwrite the variable with the same name defined in your application.properties.
What happens is called externalized configuration and it is defined here :
Spring Boot allows you to externalize your configuration so you can work with the same application code in different environments. You can use properties files, YAML files, environment variables and command-line arguments to externalize configuration. Property values can be injected directly into your beans using the #Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects via #ConfigurationProperties.
Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Properties are considered in the following order:
Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).
#TestPropertySource annotations on your tests.
#SpringBootTest#properties annotation attribute on your tests.
Command line arguments.
Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
ServletConfig init parameters.
ServletContext init parameters.
JNDI attributes from java:comp/env.
Java System properties (System.getProperties()).
OS environment variables.
A RandomValuePropertySource that only has properties in random.*.
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
Application properties outside of your packaged jar (application.properties and YAML variants).
Application properties packaged inside your jar (application.properties and YAML variants).
#PropertySource annotations on your #Configuration classes.
Default properties (specified using SpringApplication.setDefaultProperties).
So you can pass at runtime an environment variable to your docker to solve this problem. You don't need to recreate the Docker image each time.

Different properties files on the same server

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

Custom config location and config name on Spring Boot

I'm trying to customize Spring Boot config location and config name using spring.config.name and spring.config.location properties as I've saw on Spring Boot reference guide
I've created an Spring Boot basic application to test it.
I'm able to customize it using OS environment variable like export SPRING_CONFIG_NAME=custom and/or export SPRING_CONFIG_LOCATION=classpath:/custom/location.properties. That works fine!
But I want to know, if it's possible to define spring.config.name=custom on default application.properties and then create a custom.properties file where I'll be able to define all application configuration properties.
I've checked it, and seems that it's not working defining spring.config.name property on application.properties... but I want to know if this is a valid way to do it before to create an issue on gitHub.
Regards,
From spring documentation:
spring.config.location environment property (comma-separated list of
directory locations, or file paths)
Moreover, code in ConfigFileApplicationListener shows that if there if no environment property, processing fallbacks to:
DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
And for the name:
DEFAULT_NAMES = "application";
So it is normal that what you are doing is not working.

How to reference ${catalina.base} in logback.groovy config?

I am trying to deploy a webapp that uses logback's groovy config files.
I saw that in xml files you can reference ${catalina.base}
Is there a way to reference that from logback.groovy? I want a reference to tomcat home or logs folder. I want it to work even if I don't have the environment variable set.
If I write it as is I get "No such property: catalina"
I am trying to make my logs go to tomcat/logs/... regardless of the hostname. I want to make it webapp specific, not in tomcat/conf/
catalina.base is a system property which is set by Tomcat startup scripts (catalina.sh, catalina.bat).
When working with logback's groovy config files you can simply read the value of this system property into a variable and use it, for example:
def catalinaBase = System.properties['catalina.base']
appender("FILE", FileAppender) {
file = "${catalinaBase}/mylog.log"
...
}

How to retrieve path of catalina.out in java program?

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
}

Categories

Resources