Define environment variable for app in Tomcat, outside of deployment - java

I need to provide a config file path to my Java web application that runs in Apache Tomcat 10.1.
The config path must be set outside of the deployment. It's a property of the machine / stage on which the application is deployed. And not an attribute of the application. So it must not be set in the web.xml.
For example /srv/myapp/prod/config.ini or C:\EclipseDeveloperOnWindows\config.ini.
I've thought about multiple options:
Operating system environment variable MYAPPCONFIG, like PATH or JAVA_HOME: Independent of my application and even independent of the Tomcat container. Downside: May become error-prone if I want to run multiple distributions / Tomcats with different configurations as the same system user.
Java system property as a command line option for Tomcat in CATALINA_OPTS, e.g. -DmyApp.config=/some/path.ini
Tomcat context parameter in <CATALINA_BASE>\conf\server.xml. This way, each Tomcat instance (one CATALINA_HOME, multiple CATALINA_BASE) could define a different value for the config path property. (Do I have to include a reference to the server.xml context parameter in the web.xml? And can I look it up from ServletContext?)
Tomcat environment entry in <CATALINA_BASE>\conf\server.xml - what are the differences / pros and cons of Tomcat context parameters vs. Tomcat environment entries? (Can I look it up from ServletContext?)
Something else, that maybe can be looked up using JNDI?
Did I miss some options? And which one is recommended? Which approach do you use for what reason?

Putting the configuration into the Context is probably your best option. Note that Contexts can be defined in various ways, not just in server.xml.
See the Defining a context in the Tomcat 10.1 docs for details.
For our product, the same war file is deployed to the staging environment and the production environment. The differences between the environments are exhaustively described by the two Context descriptors (one for each environment).

Related

Using application.properties to set jvm arguments

I'm using spring boot 2.6.2 with docker etc. - my app reads some configuration via application.properties which looks like this:
foo.bar=hello
run.jvmArguments=-Xmx1G -XX:+ExitOnOutOfMemoryError
foo.bar definitely works as expected. But I'm not sure if it's correct to put ..
run.jvmArguments=-Xmx1G -XX:+ExitOnOutOfMemoryError
.. in there too. Does this work?
Plus - I'm using DefaultPropertiesPersister from spring to manage and change some variables in application.properties which works like a charm. But for some reason it puts some backslashes in there which results in:
run.jvmArguments=-Xmx1G -XX\:+ExitOnOutOfMemoryError
.. is this still correct? Does it work?
Thanks for any help or advice :-)
Properties from application.properties are loaded after the JVM is started and before the application context is initialized.
So there isn't any chance of them affecting the JVM.
Also there is not any real relation between application properties and environment properties for JVM. Not every spring application is a spring boot application that loads a JVM for the embedded Server. Some spring applications are deployed as wars without an embedded server, where the JVM already executes and it is the hosting server, for mutliple applications (meaning probably multiple application.properties).
Also take a look on Spring doc
SpringApplication will load properties from application.properties
files in the following locations and add them to the Spring
Environment
Also here
All configuration in Spring emanates from the Spring Environment
abstraction. The Environment is sort of like a dictionary - a map with
keys and values. Environment is just an interface through which we can
ask questions about, you know, the Environment. The abstraction lives
in Spring Framework and was introduced in Spring 3, more than a decade
ago.
Spring environment is not the same as OS or System environment that affects the JVM.

How to implement environment-specific init parameters in my tomcat application

I'd like to be able to implement a configuration-less deployment for my java application (tomcat7, spring-mvc). For example, right now we are considering creating one context.xml file for each environment (prod, stage, dev) we deploy to:
context_prod.xml
context_stage.xml
context_dev.xml
context.xml (for localhost)
On each of our servers we would have a symlink context.xml which would point to the appropriate context file (e.g. context_prod.xml). So when we deploy, we don't have to worry about changing database references, keys, etc.
I feel like there's probably a better way to do this; perhaps one that is built into spring?
Spring has recently added the functionality to handle environment configuration:
http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
This still seems a little bit complicated for me and I have done exactly what you are asking in my own Spring MVC applications for our logging. In my DispatcherServlet configuation I have this line:
<context:property-placeholder location="classpath*:/system.properties"/>
<util:properties id="mySystemProperties" location="classpath:/logging/log4j-${system.runMode}.properties" />
system.runMode is just an env variable that we created and is set in CATALINA.SH at startup like this: Setting environment variable TESSDATA_PREFIX in Tomcat
I then use Spring EL to reference any values I want and it works per environment. As you can see I did this for our logging and have a different logging configuration file per environment.
You could use Spring #Profile introduced in Spring 3.1. In your case you could use profiles like dev, stage, prod etc.
This profile value could be initialized run time. So when your application started, Spring could fetch appropriate profile based on configuration.
You could setup profile from environment variable, via deployment descriptor (web.xml) etc. This Spring source tutorial could be interesting for you.
I personally using Maven build to replace the profile value during build time in the web.xml. In the build time I passed profile value as build argument.

How to parameterize the initialization of a web application (not a servlet)

I have a web application which I wish to configure via settings in an external folder (external to the container and to the .war file). Therefore I want to inject just a single setting into my webapp which is the root folder of my configurations. The reasons for doing this are so that the maintenance team can update configuration settings in nice plain text files without having to re-deploy the war file.
My question is, what is the best way to parametrize a web application in the case of just a single configuration setting. I know I can use a JVM arg and then detect it from my initialization servlet. Ideally, I'd like something that I can put in the server.xml (not the web.xml file) that can be programmatically acquired from my ServletContextListener.contextInitialized(ServletContextEvent paramServletContextEvent) method.
Is there a way to do this using the ServletContextListener approach or is another way?
We are using -Dconfig.location=/foo/bar/config.properties and it works fine. It's a JVM arg, so it goes to the startup script.
You can register properties via JNDI in server.xml, but I'm not convinced this is a better option. server.xml or catalina.sh - both are container-level

Can I change web application root globally in jboss 4.2?

I have following situation of deployment:
application_one.war
application_two.war
application_three.war
When I deploy it in Jboss, I get three url contexts:
http//myserver/application_one/
http//myserver/application_two/
http//myserver/application_three/
Is it possible to change (prepend) globally an additional path to all deployed webapplication in a single setting, so that my new path would look like this?
http//myserver/globalprefix/application_one/
http//myserver/globalprefix/application_two/
http//myserver/globalprefix/application_three/
I do not want to change the war by using jboss-web.xml, but I am looking to do this in a general way on a central position, so even new wars will get this context prepended.
This is slightly off topic, but in a lot of production environments you'd have a web server such as Apache "in front" of your appserver (in this case JBoss), which you would be able to set up with a path (check out mod_rewrite, though don't quote me on that).

Best way to configure a Java enterprise application

I have a set of EJBs and other Java classes which need to be configured differently based on the system environment in which they are deployed: production, test, or lab. The configuration information includes stuff like URLs and database connection information.
We'd like to deploy the same exact product (EAR file) in each environment, and have the code then figure out where it is and what its configuration should be, without having to reach out to each deployment server in each environment to make changes.
What is the best way to configure all these components in a centralized, reliable, easy-to-maintain fashion?
Thanks for your thoughts.
The best, IMHO, is to use JNDI entries.
You may have to recode some parts of your application in order to use theses entries instead of plain vars, but with this setup:
Configuration is server-independant: each vendor provides its own implementation, but spec is a standard.
In a clustered environment, config can be persisted in a cluster-wide JNDI tree (see JBoss)
Configuration can be changed thru webadmin without restarting server.
How database connection pool information is stored / configured depends on the app server vendor. Put other variable stuff in property files on the classpath.
If you are deploying the exact same EAR to three different instances of a certain container than you will have to edit the deployment settings as there is no way that the deployment process could have any idea about which one of your three versions you would like to use at a particular deployment.
Deployment settings should go into JNDI entries as Piere-Yves said above.
If I were you, I would have my deployment-script (Ant?) properly populate the JNDI entries depending upon which environment you are deploying to.

Categories

Resources