I'm new to Java (around 2 months Java experience after coming from a .Net background). I've been asked to support a Java application which uses Spring, J2EE, and an Oracle database.
We have an issue with our deployment process which I'm struggling to understand.
The Java application in question has database connection details in an application.properties file. Its location appears to be configured from a Spring configuration file using the following line:
<context:property-placeholder location="classpath:config/application.properties,classpath:config/bookings.properties" ignore-resource-not-found="true" />
On our Development Tomcat server, the application (called Bookings) looks in this location for the application.properties file:
/usr/share/tomcat/webapps/Bookings/WEB-INF/classes/config
Which is what I would expect, looking at the Spring configuration.
However, on Production Tomcat, the application looks in a different location:
/usr/share/tomcat/lib/config
(In this directory, the file is called bookings.properties.
The original developer has left the company and I have no idea why it would look in a different location for the file (and a different filename).
Any ideas what I can look at, or where this could be configured? It should be noted that both files (application.properties and bookings.properties) are present on both Tomcat servers, so I don't understand the discrepancy?
We have re-deployed the same WAR file to both development and production, and the discrepancy still exists, i.e. the servers still look in different places.
classpath is a directory where you could put some resources (to make it simple, further details on the link).
that's a variable and it's added to the launch command, sometimes it's a bit hidden. But that's the way it works.
May be you can watch in $TOMCAT_DIR\bin\catalina.sh to see how the classpath is defined.
In your case, the folders contained in your classpath are different between development server and production server. That's totally normal.
However, you say that in production the file is named bookings.properties.
But with this line :
<context:property-placeholder location="classpath:config/application.properties,classpath:config/buyer-request.properties" ignore-resource-not-found="true" />
we see that you never try to load a file named booking.properties.
So ask yourself why the file is called booking.properties. And rename it application.properties to see what happen.
Hope this help
Related
I am facing a little strange issue while deploying web service to WAR file.
If I deploy the application via Netbeans IDE it is going under \standalone\deployments directory.
However, if I deploy the war file from Admin Console it is always getting deployed at \standalone\tmp directory.
Please guide on this issue. The deployment should go under \standalone\deployments directory only.
The deployment should go under \standalone\deployments directory only
You are quite not right.
It is not an issue. It is what it is.
standalone/deployment folder stand there only for "hot-deployment" functionality available only with standalone mode.
So, Netbeans uses it. You can do the same just by saving EAR or WAR into standalone/deployment and server will pick it. (default scan interval is 5 sec.)
but Admin console or CLI is only (and standard) way to deploy application on domain. In domain mode deployment folder is not in use and there is no deployment scanner.
Then when you use console it goes common way - deploys as on domain regardless is it domain or standalone server.
Updated / follow-up:
In general it is better to keep .properties file(s) out of deployment, in separate location. It is main idea behind them - to be able to change properties without application rebuilding and redeploying. Usually properties are different in different environments (DEV/UAT/PROD)
So there are 2 most popular solutions:
store properties in different location add that location to class path and access them through ClassLoader.getResourceAsStream() mechanism
store properties in different location, pass that location through system (or -D) variable and access them as file. for JBoss you can place your .properties under configuration directory. there is already JBoss variable. Kind of jboss.config.dir (or such, you can find it in Admin console, I do not have JBoss right now).
But of course sometime it still needed to access resources inside WAR/EAR - in that situation it is pretty much the same as first solution above.
Just be sure your .properties file(s) are accessible through to ClassLoader (in class path) and use them from ClassLoader.getResourceAsStream (or if you use Spring point it as "classpath:" not as "file:".
I'm currently developing an application which requires access to an API with credentials. I didn't want to put them hard coded in the application so I created a configuration.properties file for them.
At the moment this file is located in src/main/resources and access it with the following code.
<context:property-placeholder location="classpath:configuration.properties" ignore-unresolvable="true" />
This means that if I change something in the configuration I need to redeploy the WAR.
My question is: Where do I put this configuration file so that I don't need to redeploy in case of a change in the configuration?
I don't want to put it somewhere random on my computer so that I can share my code with other people without to much trouble with the file's location.
I solved it by placing my properties file in Tomcat "D:\Documents\workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps"
And Access it with the following property-placeholder
<context:property-placeholder location="file:${catalina.base}/conf/configuration.properties" ignore-unresolvable="true" />
I think you're already close.
I agree its a good way to have one .war file and reuse it everywhere without adopting it to a specific environment. That means you cannot include it in the .war
What I would do is creating configuration zip files with the assembly plugin (if there are multiple variations). For example from /src/main/config/env1
Then use an environment variable to point to that folder.
The property placeholder configurer thing in spring then references that location through that system property instead of the classpath:
these zip files can be used to be deployed with the .war file (via ssh using the ant runner plugin or some other way)
That can also be used for the logging configuration. Spring has a resolver that will even reload the log config if you change it on the file system.
I am running eclipse on a mac and have my tomcat folder at /Library/WebServer/apache-tomcat.
I am using the tomcat 7 server from within eclipse and configured it to use the original tomcat folder as its working directory.
Problem is that when using the PropertyPlaceholderConfigurer bean in Spring 3.1 and specify the location as "classpath:database.properties", when i start tomcat it will always give me a FileNotFoundException.
I have tried placing the database.properties file in lib,conf and root folder of the tomcat folder.
I am out of options, please help!
EDIT 1
Tried Guido Simone's solution, but i get:
ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: /Library/WebServer/apache-tomcat-7.0.32/conf/database.properties (No such file or directory)
So i finally see the full path that spring is looking for the file(which is correct) and the file is physically there. Any other suggestions? And if this is going to work, do other webservers have this catalina.base variable also or is this tomcat specific? Because i kind of need platform independence at a later stage.
I tend to not use the classpath URL for just this reason. I hate having to keep track of exactly how the classpath is configured for various runtime environments. For property files that are likely to be edited (and cannot go into the WAR file) I would recommend something like:
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:${catalina.base}/conf/database.properties"/>
Now, it's clear that the file is in the conf folder, with all the other configuration stuff.
[update]
catalina.base is definitely Tomcat specific, so the exact XML above would not be portable to other application servers. If you decide to continue with the file: prefix, you would need to do a bit more work and define your own system property to indicate where all your configuration files are ( file:${my.product.conf}/database.properties)
You would need to check the documentation for each app server to figure out how to set this property at startup.
No idea why your are still getting the FileNotFoundException now that the full, absolute path is spelled out. The only thing I can think of is perhaps the file is not really where you think it is :) :) :) Sorry.
I already searched StackOverflow for "properties inside war", but none of the results worked for my case.
I am using Eclipse Galileo and GlassFish v3 to develop a set of web services. I am using a "dynamic web project" with the following structure
Src
-java_code_pkg_1
-java_code_pkg_2
-com.company.config
--configfile.properties WebContent
-META-INF
-WEB-INF
--log4jProperties
--web.xml
--applicationContext.xml
--app-servlet.xml
I want to access the "configfile.properties" inside one of the source files in "java_code_pkg1". I am using the Spring Framework and this file will be instantiated once the application starts on the server.
I have tried the following with no luck
getResourceAsStream("/com.company.config/configfile.properties");
getResourceAsStream("/com/company/config/configfile.properties");
getResourceAsStream("com/company/config/configfile.properties");
getResourceAsStream("/configfile.properties");
getResourceAsStream("configfile.properties");
getResourceBundle(..) didn't work either.
Is it possible to access a file when it's not under the WEB-INF/classes path? if so then how?
Properties props = new Properties();
props.load(this.getClass().getResourceAsStream("/com/company/config/file.properties"));
works when I'm in debug mode. I can see the values in the debugger, but I get a NullPointerException right after executing the "props.load" line and before going into the light below it.
That's a different issue. At least now I know this is the way to access the config file.
Thank you for your help.
If you are in a war, your classpath "current directory" is "WEB-INF/classes". Simply go up two levels.
getResourceAsStream("../../com/company/config/configfile.properties");
It is horrible but it works. At least, it works under tomcat, jboss and geronimo and It works today.
P.S. Your directory structure is not very clear. Perhaps it is:
getResourceAsStream("../../com.company.config/configfile.properties");
Check the location of the properties file in WAR file.
If it is in WEB-INF/classes directory under com/company/config directory
getResourceAsStream("com/company/config/configfile.properties") should work
or getResourceAsStream(" This should work if the config file is not under WEB-INF/classes directoy
Also try using getClass().getClassLoader().getResourceAsStream.
Are you sure the file is being included in your war file? A lot of times, the war build process will filter out non .class files.
What is the path once it is deployed to the server? It's possible to use Scanner to manually read in the resource. From a java file within a package, creating a new File("../applications/") will get you a file pointed at {glassfish install}\domains\{domain name}\applications. Maybe you could alter that file path to direct you to where you need to go?
Since you are using Spring, then use the Resource support in Spring to inject the properties files directly.
see http://static.springsource.org/spring/docs/3.0.x/reference/resources.html
Even if the class that requires the properties file is not Spring managed, you can still get access to the ApplicationContext and use it to load the resource
resource would be something like, classpath:settings.properties, presuming that your properties file got picked up by your build and dropped in the war file.
You can also inject directly, from the docs:
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
We're developing a big J2ee e-sales solution. It's got a lot of integrations: CMS, ERP, Mail server etc. All these systems are divided into test and production environments.
We need to deploy our application to our test servers with test configuration and when deployed to our production servers it should use the production configuration. How do we make our application select the correct properties?
The thing we've tried so far is this:
All our property files contain test properties and production properties
test.mvxapi.server = SERV100TS
test.mvxapi.username = user
test.mvxapi.password = password
test.mvxapi.port = 6006
test.mvxapi.cono = 600
mvxapi.server = SERV10001
mvxapi.username = user
mvxapi.password = password
mvxapi.port = 6001
mvxapi.cono = 100
The Util that reads these properties has a switch: isTest() which prefixes the key with "test."
public String getProperty(String property)
{
return properties.getProperty(prefix + "" + property);
}
The switch is set by another property which is created by our build server. When the .EAR is built the script for our production servers injects (input to build.xml) "isProduction=true" into system.properties.
<propertyfile file="${buildDir}/system.properties">
<entry key="isProduction" value="${systemType}"/>
</propertyfile>
I'm not sure this is the best way to do it. If for some reason "isProduction=false" is committed wrongly to our production environment all hell is loose.
I've read people have properties locally on the server. But we really don't want to have files spread around. We have cluster of production servers. Making sure every server has the right property file doesn't seem fail-safe
What you want to avoid is having the config file inside the EAR, the problem with this is that you need different EAR's for different environments, and also, changing the config file requires a rebuild.
Rather deploy the same EAR to every server but configure each server with a different URL resource. iow, add a JNDI URL resource to all the servers you deploy to that point to the config file for that resource. If you have read only SVN access to your repo then create the config files on the svn repo, or any repo you can access via a URL. The cool thing here is that all your configuration is centralized and thus managing them is easy.
What I've done (by customizing with spring) is make sure that JNDI URL resource optional. So, if it's there, the app will use it, if not, it won't. The app starts up whether it's there or not. That way, even when running with no JNDI resource available, the app still works (development environment for example).
You deploy an EAR? Then put the properties needed in JNDI.
I can't say if this is the best way, however, what we do is include a client and server jar which houses the properties accordingly. We then include those jars in the EAR file. So during our build process we include the appropriate (QA, TEST, PROD) jars for the environment in which we are deploying to.
The downside is we have to manage three sets of environment jars and the build team has to be careful not to deploy the incorrect one. In fact, it has happened once that we had a PROD jar deployed to our QA environment and QA data was getting put into production....yes that sucked and was a major mess to clean up.
I will be watching this discussion because I often wonder how we can make this process better/safer. Great Post +1
In a previous J2EE project, we've been doing exactly that. The build process (an ant script) put together the right config files, added them to a certain jar which was then put into the EAR file for production environments, test, training, QA, etc.
The file name of the EAR file contained the name of the target environment, so it was basically impossible to deploy a file to the wrong environment. If we built for target 156p2 (factory 156, production env. 2), this would be part of the file name of the EAR file and ant would include config_156p2.xml. If the target was incorrect, the EAR file's name would be wrong and as a last failsafe the guy who deployed it would notice.
The build file had to contain this: one ant target to start the build for each environment which would set a property that told ant which config file to include.
The only difference between the EAR files would then be the config files. Everything else was identical. There is a possibility, of course, that someone might have written a wrong value to a config file for a certain environment. However, in practice this never happened in several years, even with some pretty junior developers and about fifteen target environments (different test, QA, training and production servers in different countries).
We have 3 folders for this purpose in our projects, each one contains configuration files (filenames are the same between the folders):
personal: contains paths to test db, server, etc
test: contains paths to the servers shared with my colleagues
production: contains... well you guessed
When I build my project I add the suited profile to Intellij Idea project build, in the desidered module, this basically means that i am adding a different folder to the project structure, but because filenames are the same what changes are only profile properties.
Very old post still responding in case someone checks it. In each application server you can set System properties e.g
Wildfly Management Console --> Configuration --> System Properties
There I add a variable SERVER_ENVIRONMENT with value as DEV/UAT/PROD.
In my java code I use:
System.getProperty ("SERVER_ENVIRONMENT")
which gives me value from the server.
Like #Alberto-Zaccagni said you can have separate folders with properties files that exist only in respective environment. Your code checks for existence of folder starting with PROD then UAT then DEV and when it finds a path exists it uses the properties files there.