Adding properties file to classpath but getting a FileNotFoundException - java

My spring context file has this:
<context:property-placeholder location="classpath:web.properties" />
and I reference the key/values like:
<property name="username" value="${dataSource.username}"/>
My file layout is like:
>/www/site/app.war
>/www/site/configs/web.properties
And I run my app using:
>java -cp "/www/site/configs/*.*" -jar app.war
But then I get this exception:
java.io.FileNotFoundException: class path resource [web.properties] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
at org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties(PropertiesLoaderSupport.java:181)
at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.java:161)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:78)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:661)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
Even though I added the files to my classpath, it still can't find it why?
Update
So my config files are here:
/www/site/configs/web.properties
/www/site/configs/log4j.properties
I tried this:
>/www/site/java -cp ".:app.war:/www/site/configs/*.*" com.abc.server.MyServer
and:
>/www/site/java -cp ".:app.war:/www/site/configs/web.properties:/www/site/configs/log4j.properties" com.abc.server.MyServer
and even:
/www/site/java -cp ".:app.war" com.abc.server.MyServer
I get the same error:
2013-04-25 01:19:28.210:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
2013-04-25 01:19:28.294:INFO:oejw.WebInfConfiguration:Extract jar:file:/www/site/app.war!/ to /www/site/work/app
2013-04-25 01:19:32.814:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/www/site/app/},file:/www/site/app.war
log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.StandardServletEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2013-04-25 01:19:33.585:INFO:/:Initializing Spring FrameworkServlet 'app'
2013-04-25 01:19:35.750:WARN:/:unavailable
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in ServletContext resource [/WEB-INF/web-context.xml]: Could not resolve placeholder 'dataSource.url' in string value [${dataSource.url}]
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
My web.properties has:
dataSource.url=jdbc:mysql://localhost/appdb
dataSource.username=root
dataSource.password=123
Again my web-context.xml file has:
..
<context:property-placeholder location="classpath*:/web.properties" />
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${dataSource.url}"/>
<property name="username" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
..
I also tried the following variations:
<context:property-placeholder location="classpath:web.properties" />
<context:property-placeholder location="classpath*:web.properties" />
<context:property-placeholder location="classpath*:/web.properties" />

I have also faced similar issues. I cannot say why but I have found -cp arguments not to behave when lugged along with -jar.
You can use,
EDIT
As per the dicussion and going through: http://docs.oracle.com/javase/6/docs/technotes/tools/windows/classpath.html
The correct syntax should be:
In windows:
java -cp "app.war;/www/site/configs/" <Main Class file name>
In Linux:
java -cp "app.war:/www/site/configs/" <Main Class file name>

Items accessible via the CLASSPATH aren't necessarily files at all. They might be still in the JAR or WAR file. They should be accessed as resources, via Class.getResource() and friends.
Entries in the CLASSPATH aren't files either. A CLASSPATH is one or more directories or JAR files inside which the resources are to be found, according to the package structure.

Related

Read PropertyPlaceholderConfigurer classpath Spring with Jboss

Using PropertyPlaceholderConfigurer to externalize spring-configuration
properties.
Added following code to spring-servlet.xml
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:environment.properties</value>
</property>
</bean>
Filter to be externalized from spring-security.xml
<security:custom-filter position="AUTH_FILTER" ref="${filter}" />
filter value is present in environment.properties
environment.properties file is present inside Jboss modules and is readable from code using resource bundle.
But, with these changes somehow properties file is not getting loaded and following error is thrown while publishing code.
Caused by: java.lang.IllegalArgumentException: Could not resolve
placeholder 'filter' in string value "${filter}"
PS:
Also tried hardcoding path as <value>file:${jboss.home.dir}/modules/system/layers/base/configuration/main/environment.properties</value> but, dosen't seems to be working.
I think your problem is that your spring-servlet.xml is not linked to your spring-security.xml. So spring-security.xml has no knowledged of the PropertyPlaceholderConfigurer.
IMO, you should configure PropertyPlaceholderConfigurer in a properties-context.xml (for instance) so you can import this new file into your spring-servlet.xml and spring-security.xml as following:
<import resource="classpath:properties-context.xml" />

Externalize properties in Tomcat

I would like to configure a series of environment-dependant settings as an external resource, so that the same WAR artifact can be configured in any application server.
In Glassfish I rememeber that I just created a .properties file using the built-in Properties Resource JNDI Factory, and it worked like a charm, but there's no such thing in Tomcat.
I tried defining a java.net.URL and a java.lang.String to define just the path that this file is held in, but I get the following error:
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/c://app.properties]
So what would be a good way to create an environment-agnostic set of properties for my application?
PS: this is how I define my properties in Spring:
<jee:jndi-lookup id="appProperties" jndi-name="java:comp/env/url/urlAppProperties" />
<bean id="application-properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>#{ appProperties }</value>
</list>
</property>
</bean>
You can add external configuration values to the JNDI context using Tomcat's resource configuration elements. As described in the Tomcat documentation, you can define a <GlobalNamingResources> element in your server.xml listing a set of configuration values which are available to all contexts (web applications) on that server:
Example taken from the Tomcat docs:
<GlobalNamingResources ...>
...
<Environment name="maxExemptions" value="10"
type="java.lang.Integer" override="false"/>
...
</GlobalNamingResources>
These environment variables are then available via JDNI in the java:comp/env context. In order to use such variables in a web application, you have to link to them in the individual context.xml configuration files using the <ResourceLink> element.
<Context>
<ResourceLink name="maxExemptions" global="maxExemptions" type="java.lang.Integer"/>
</Context>
With this set up, you can access these values through the standard JNDI API.

Liquibase Groovy-DSL Spring

I am developing a spring-shell database migration tool.
At the moment i try to use liquibase with the groovy-dsl extension.
My build.gradle includes the extension jar, also i declared liquibase in the spring-shell-plugin.xml
spring-shell-plugin.xml
<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase" depends-on="postgresService">
<property name="dataSource" ref="psqlDataSource"/>
<property name="changeLog" value="com.example.db.DbChangelog_master"/>
<property name="defaultSchema" value="${postgres.schema}"/>
</bean>
But everytime i start the application liquibase throws the following error
Caused by: liquibase.exception.UnknownChangelogFormatException: Cannot find parser that supports com.example.db.DbChangelog_master
at liquibase.parser.ChangeLogParserFactory.getParser(ChangeLogParserFactory.java:70)
at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:226)
at liquibase.Liquibase.update(Liquibase.java:202)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:434)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:391)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 13 more
The documentation is a bit rare, also the jar is included in the classpath.
Does the groovy scripts need to be in src/main/resources? Currently they are in a seperate package in src/main/groovy
I think that your property
<property name="changeLog" value="com.example.db.DbChangelog_master"/>
is incorrect. This should be the path to your changelog file. If that file is a groovy file, it might be
<property name="changeLog" value="DbChangelog_master.groovy"/>
if that file is available on the classpath.

Load internal (Classpath) and external property file in a Spring Application

I need to load both external and internal property files in my spring application. Once I declare the external file as below
<context:property-placeholder location="file:${JBOSS_HOME}/123.properties" />
I can access the properties defined in this external file. But all properties related to the property file in my class path Could not resolved.
My Application Context
** <!--Refer External File --> **
<context:property-placeholder location="file:${JBOSS_HOME}/123.properties" />
<!--Refer Internal File -->
<bean id="helloWorldBean"
class="com.javacodegeeks.snippets.enterprise.services.HelloWorld">
<property name="internalProperty1" value="${internalProperty1}" />
<property name="**externalProperty**" value="${**externalProperty**}" />
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>constants.properties</value>
</property>
</bean>
I am getting property value of the external property file but not the value of the internal property file.
Exception in thread "main"
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'helloWorldBean' defined in class path resource [applicationContext.xml]: Could not resolve placeholder 'internalProperty1' in string value "${internalProperty1}"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:174)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:151)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:669)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplsamicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.javacodegeeks.snippets.enterprise.App.main(App.java:13)
Cannot I load external(non-class path) and internal (Class path) property file together ?
What you need is something like this:
<!--Order matters, properties in the second file will override the first -->
<context:property-placeholder location="file:${JBOSS_HOME}/123.properties,classpath:configuration.properties"
ignore-unresolvable="false" ignore-resource-not-found="true" />

finding a property using Spring and Webapp properties placeholder

This is a "simple" problem and I am seeking both a how-to and/or a you're-dumb-don't-do-that. I am open to both.
I am building a war file and want the structure to be:
WEB-INF/
properties/
<my properties files>
classes/
...
spring/
<my spring files>
Is that dumb? I know that I can access the properties files though the property-placeholder but I'd rather not nest the properties in the classes section - it doesn't make sense to me.
So the Spring file looks like this:
<context:property-placeholder location="classpath:properties/*.properties" />
if I want to access them in the classes area. I thought that
<context:property-placeholder location="properties/*.properties" />
would let me just put the directory under WEB-INF directly...am I wrong (ps I think I am :) ).
Any advice?
This should work
<context:property-placeholder location="WEB-INF/properties/*.properties" />
WEB-INF is not the root of the of the web-app, so you need to add WEB-INF to the path.
spring-context-3.1.xsd
<xsd:attribute name="location" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
<![CDATA[
The location of the properties file to resolve placeholders against, as a Spring
resource location: a URL, a "classpath:" pseudo URL, or a relative file path.
Multiple locations may be specified, separated by commas. If neither location nor properties-ref is
specified, placeholders will be resolved against system properties.
]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
You can't do it the way you want since the classpath for the Classloader will be the /classes directory and any jars in the /lib directory. This is the standard configuration for a war file.
Wars and ears have specific configurations which you have to follow for the files to be valid. If you think about it, it would make it difficult to have different vendors provide web containers that could deploy the same war file if there was no standard format. There is a pretty informative page here.
To achieve something similar to what you want, you can simply have directories of /classes/properties and /classes/spring and look them up appropriately from your classpath ("classpath:properties/myfile.properties).
I am not sure what you want to achieve. Here the method I use to inject the properties from a basic properties file to a bean:
In the spring files (XML bean definitions), I add the reference to my property file (myfile.properties):
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:myfile.properties" />
</bean>
and then I add my references to the properties (db.url is the URL address for my database connection, I kept only the bean properties referenced in my property file).
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.login}</value></property>
<property name="password"><value>${db.password}</value></property>
</bean>
By default, if the property is not defined in the property file, Spring uses the System Properties (this behaviour can be changed).

Categories