Defining and using project variables in Java CAPS (JCAPS) 5.1.3 - java

I'm trying to experiment with project variables in JCAPS, and while I can find some information on how to define them, I cannot find anything on how to actually use them.
Basically, I have a JCD defined that has one item (a filename) that changes between deployments. I would like to be able to re-use the JCD for multiple deployments, supplying the filename via a project variable (configured in the deployment profile).

I would advise you to not use the variables. We have had much better success using property files that we have stored on the server.

Related

Sharing common properties across different property files in Java

I have two properties files in my Java project. Both of them have some common properties, e.g.
PropertyFile1.properties
p1=v1
p2=v2
p3=v3
p4=v4
PropertyFile2.properties
p1=v1
p2=v2
p23=v23
p24=v24
Here, p1 and p2 properties are common to both files.
I need to be able to separate out such common properties in a different file, e.g.
Common.properties
p1=v1
p2=v2
And then refer this common.properties inside PropertyFile1 and PropertyFile2.properties files.
Basically, I need to be able to inherit the common properties and their values across different property files.
Is this possible?
I've come across following link but not sure how to use it for my requirement.
http://commons.apache.org/proper/commons-configuration/
Thanks.
Properties is a file extension for files mainly used in Java related technologies to store the configurable parameters of an application. The advantage of using properties file is, we can configure things which are environment specific (or are prone to change over a period of time) without the need of changing anything in code. Hence inheriting common properties is not a good approach. If a property seems to be static for all e.g. environments, then it shouldn't be a property.
But, it could be we have multiple development environments and production, where we would share same properties in the environments meant for development purposes and different properties for production. In this case we could create a common properties file and inherit it in all our environment specific properties files. Another scenario could be, that at the moment of development the property is same for all environments, but we would like to provide the option of changing it in the future, when required.
There are two ways to inherit properties from a common properties file:
include
includeOptional
The value of these properties is the name of a file on the disk, that file will be included into the configuration. The difference between "include" and "includeOptional" is that if the file value is absent, processing continues with "includeOptional" but stops with "include".

Can SpEL be passed an enviroment variable directly or is a properties file in some form always required?

We build micro services and I am working on a generic way of generating documentation for them. This has created a situation where I need to set a variable which is static across all our services yet has two possible values depending on the environment the service is deployed in. Hence I would like to inject a value based directly on an environment variable rather than through my Application.yml file, and it's various profiles, as I would usually do. Is there any way to do this?
Here is an example of what I imagine this would look like (with a syntax similar to what it would have looked like if it was a regular property in Application.yml):
#Value("#{enviromentProperties['environment'].equals['production'] ? jupiter : mars}")
private String APIGatewayHostname;
Just to be clear we have situations where we deploy several profiles behind the same proxy. Hence we want the hostname reference to be the proxy host so people don't attempt to call the service directly as this is not possible. We only have one proxy per environment regardless which profiles we are running at any given time hence my desire to use an environment variable rather than a property. Also this proxy is not really a part of the design of the services themselves so it seems counter intuitive to store it in multiple profiles in the Application.yml file.
NB: If there are other better ways to accomplish this feel free to let me know :)

Purpose of storing variables in web.xml?

A lot of the advice on the web on storing variables which may change depending on the env/other conditions is to put them in web.xml, but isn't the web.xml within the war file? even if you find the exploded war and change it, wouldn't it get overriden if you update the war file? Or does the webcontainer provide any method to configure the web.xml without tinkering with the war file?
The web.xml variables are of very limited use, in my experience - the only advantage is that it's a standard location to look for hard-coded "configuration".
There are several common solutions to get a more sensible way to configure web apps, none of which is standard:
Use system properties (which usually involves fiddling around with startup scripts, and it can be hard to get a good overview of your entire config)
Use environment variables (same drawbacks as system properties)
Read a config file from a predefined location; often from the classpath by using getResourceAsStream (IIRC that usually means putting the config files in Tomcat's lib directory)
You can also use JNDI, which has the disadvantage of being rather heavy-weight both to set up and read (if you're using vanilla Java, anyways - Spring for example has rather good support for reading from JNDI). However, JNDI is rather good because it's per-application, and not a process-global setting. If you need to run several instances of the same app on the same server, JNDI is pretty much the only option (although you can use it to just point out a config file somewhere, which makes things easier to work with).
This may be relevant to your interests: How can I store Java EE configuration parameters outside of an EAR or WAR?
Advantages of specifying Parameter Values in web.xml
Using your own settings file requires additional coding and management.
Hard-coding parameter values directly into your application code makes them more difficult to change in the future, and more difficult to use different settings for different deployments (eg: JDBC settings, mail server address).
Other developers using your code will be able to find any relevant parameters more easily, as this is a standard location for such parameters to be set.
See also:
Advantages of specifying Parameter Values in web.xml
Web.xml.EnvEntry
Referencing Environment Variables in web.xml
As far as I know web.xml does not provide ability to store custom variables. Typical way to configure your web application is to store configuration in database, separate properties/xml/json/other file, get configuration from separate web service or provide it through environment variables.
Often a mixture of all these is used. For example you can add system variable using -D switch when running your container. This variable will contain path to file or URL where your configuration can be found.
You can supply parameters using OS environment.
You choice should depend on how many parameters do you have, what kind of application are you developing and how can you configure application server or computer OS. For example if you a hosting application on server you cannot configure these ways are not for you, so DB or web service are your only ways.
The folks that work on the Tomcat container recognize the irony that you have identified and have implemented a way to work-around the issue.
The solution that they implemented for the issues that you have alluded to is to create another xml file... the context.xml file, which is read by the server.
It appears that you can edit this file and have the new values read by the Tomcat without a restart... as long as you keep the elements out of the server.xml.
I do not use Tomcat so I might be mis-interpreting the docs
The GlassFish web container supports a similar feature, but does it via a couple admin cli command (asadmin):
set-web-env-entry
set-web-context-param
There is probably web admin console support and you can set them up by editing the domain.xml. It seems like it isn't as flexible as the Tomcat implementation... but it does make it really easy to use.
You need to disable and then enable your application for the changed values to 'take'. Do not redeploy you app, since that will delete the value that you just set.

Best way to reference the file system in a spring mvc app

In a spring mvc application, what is the best way to reference the filesystem?
Say I want to know the root of my applications path?
Should I create a properties file and hard code this value in the property file, then create different versions for production and development environments?
I might want to reference a file outside of my application also, so I guess a property file is best suited for this correct?
I understood your question as a config/release problem, not coding problem. If you want to access file (say with absolute path) there are different ways to achieve it:
if you use maven to build your app. create maven profile with corresponding property, e.g. file.path and at build-time fill the property to spring bean (e.g. a String)
create different properties files, which containing config parameters for different environments. and let maven fill the placeholder in spring conf, which properties file should be used.
use spring profile. put server-relevant beans in profiles, and your application choose the right profile (the set of beans) at runtime.
well if you have different databases for different environments, you could consider to save some config parameters in a config table. And application loads those data when it starts or when it needs. At least this is another option.
did that answer your question? or I am just talking about something else?...
Get real path and complete your remaining action
String realContextPath = session.getServletContext().context.getRealPath(request.getContextPath());

Running one file on multiple servers

Right now my team deals with about 4-5 different servers and about 2-3 different DB servers and we're using environmental variables to decide which server we're on and what server configuration to use.
Is there a better way to do this as my team continues to expand? I've considered compiler flags / args, but it doesn't seem as robust.
From my perspective, in java, you have basically 3 ways to crack this cookie:
Environment variables
-D JVM parameters (which are System Properties)
properties files
You've already discovered Environment Variables and that is pretty much "the unix way" to get the effect you are after; different configuration to common binary that customizes the running application for the environment it is executing on.
System Properties are really the Java "moral equivalent" of Environment Variables. They come in via -D parameters on your application's command line like...
java -Dlogback.configurationFile=/opt/dm/logback.xml -cp app.jar org.rekdev.App
Explicit Properties file processing http://docs.oracle.com/javase/tutorial/essential/environment/properties.html in Java is a third variant which you often see coupled with -D to get something like default behavior which can be overridden at runtime from the command line. That is what is basically going on with the logback.xml configuration above, the JAR file has a logback.xml inside it that will be used unless a System Property called "logback.configurationFile" exists, at which point the App will load it instead.
As you try to figure out how to keep this all in sync and working correctly in a multi-server environment, consider the use of chef http://wiki.opscode.com/display/chef/Home to do the deployments and put each specific environment's customizations under chefs control. Put the chef "recipes" in version control and, voila, full on configuration management.
SHIP IT!
I can see two scenarios
You embed all the different properties within your package (can be a war, ear, jar, or on the file system /yourapp/etc/)
You embed only one property file and this one is created during build (with ant or maven)
Say your app is named foo
Solution 1
It has the advantage that your app can be put as-is on any of the supported servers (all that have a property file in your app package).
Your properties will be named foo.dev.properties, foo.test.properties, foo.prod.properties, foo.damien.properties, foo.bob.properties.
One other advantage is that every developer working has its own dev file that he can safely push on svn/git/whatever and be sure that other developer won't destroy his config.
At runtime the application can check the -D parameter or even retrieve the hostname dinamycally, in order to load the correct property file.
Solution 2
It has the advantage that your package is not polluted by unnecessary properties files.
You must configure a lot of ant tasks/maven target in order to build for specific environment. You will have in your source directory the properties files for the environments also, but only one will be shipped with your app. This one foo.properties will only have placeholders for values, and values will be inferred within it using foo.ENV.properties with the right ant task/maven target.
At my actual job and the previous one also, we did use the solution 1, I think it brings flexibility.
Some parameter (like database user/password) were fetched directly from environment variables on the Unix servers though (so that only the server admins knew the credentials).
You can safely mix the solutions, in order to get where you feel there is the more flexibility for you and your team.

Categories

Resources