Springframework beans - java

I have not until now had worked with spring framework. I tried reading and reading the spring documentation but could not locate the answer to the following simple question.
The application is ant built to a build directory. So far when I tried to start the JBOSS (or apache) server, the logs says it is unable to build the bean because it could not find
var/config/madagascar.prop.
.
WRT the following snippet in WEB-INF/applicationContext.xml
<bean id="application.home" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="java.lang.System"/>
<property name="targetMethod" value="getProperty"/>
<property name="arguments">
<list>
<value>application.home</value>
</list>
</property>
</bean>
<bean id="propertyFile" class="java.io.File">
<constructor-arg ref="application.home"/>
<constructor-arg value="var/config/madagascar.prop"/>
</bean>
Could you tell me where {application.home} and var/config are expected to be located?
Is it relative to the Eclipse project home or relative to WEB-INF?
What is the bean id="application.home" attempting to do - is it trying to read the value for "application.home" from the system env?

"application.home" is the runtime value of System.getProperty("application.home") and the "propertyFile" bean is a java.io.File object returned from calling new java.io.File(String, String) with the whatever application.home is set to and that second String.
If the bean you wanted was 'propertyFile', the runtime equivalent would be:
File file = new File(System.getProperty("application.home"),"var/config/madagascar.prop");
That config is a very Spring 1.x (read old) way of doing things. XML is a very kludgy way to perform many of these types of initialization, and that's one of the reasons that Spring's #JavaConfig approach became so popular.

Related

properties file not loading in Unix machine but the same is working on windows machine. could not understand why?

I am using spring 4.3.6 and tomcat 7 for our web application. I have the following configuration in my xml file :-
<bean id="appResourcesProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:resources\xxxxxxResources.properties</value>
</list>
</property>
</bean>
This worked fine on windows machine but when the same deployed on unix machine the properties file did not get loaded.
Then i have removed "*" after the classpath and modified as below:-
<bean id="appResourcesProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:resources\WCApplicationResources.properties</value>
</list>
</property>
</bean>
This worked fine on unix machine. Why this happened? I could not understand the reason. Can somebody help me understand this. Thanking in advance.
the reason is '\', try using '/' instead, like resources/WCApplicationResources.properties
Classpath*: portability
The wildcard classpath relies on the getResources() method of the
underlying classloader....
In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.
And the getResources finds like this:
The name of a resource is a '/'-separated path name that identifies the resource.
Hope it helps in something.

springMVC : No message found under code 'com.info.write.text' for locale 'en_US'

While reading properties file from folder com.resources I got following error
javax.servlet.jsp.JspTagException: No message found under code 'com.info.write.text' for locale 'en_US'.
I am not using maven. So, I understand that spring will not read the resources automatically.
I know how to write and read data from simple property file in java is simple task as, need to provide path using FileReader now the question is how I can provide path to properties file?
This is some relevant part of my dispatcherServlet-servlet.xml
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="message" />
</bean>
here is data of property file i.e (message.property)
com.info.write.text=Greetings of the day
This is how I am trying to use data from property file as message
<p><spring:message code="com.info.write.text" /></p>
and the file structure to message.properties is
src/com/resources/message.properties
How to read properties file in spring without using maven or any build tool(directly) ?
Either use full name in dispatcherServlet-servlet.xml
like
<property name="basename" value="src/com/resources/message" />
or use ClassPath like
<property name="basename" value="classpath*:resources/message" />

Read properties file from WEB-INF folder

I want to read properties file from WEB-INF folder and not from the classpath since I dont want to compile my application again if I make any modifications. My file is coming in build in the directory but when I am trying to acces its not showing anything. Please can anyone help me with this. I am using Spring framework. So if there is any method in Spring which will allow us that we are not required to compile our application again and again and the modifications are taken up by the applications on its own.
Add this to your application context configuration file and try.
<bean id="applicationProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>yourPropertiesFile.properties</value>
</list>
</property>
</bean>
To access properties from the properties file, use the bean's ID in your class which must be annotated with #Service or #Component
#Resource(name="applicationProperties")
private Properties anyVariableName;
...
...
String propValue = anyVariableName.getProperty("propertyName");
You can put the properties file in the resources folder. It will not require recompiling of the application.
In spring you can use the following lines to read the property values from property file :
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:dash_conf.properties</value>
</list>
</property>
</bean>
Also if you want to read the property file from java class you can use :
InputStream in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(fileName);
Properties prop = new Properties();
prop.load(in);
Hope this solves your problem.

Optional additional property file in spring context

I have a default properties file that my app uses but I also need to be able to allow for an additional property file which can be specified by a -D flag on startup and will be pointing to a path on the file system (not in my classpath). What's the correct syntax to do that?
I tried this but it didn't work:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations"
value="classpath:/config/config.properties,file:/${additional.configs}" />
</bean>
as it complained that:
java.io.FileNotFoundException: class path resource [config/config.properties,file://var/tmp/cfg/qa.properties] cannot be opened because it does not exist
It looks like the comma delimination isn't working despite me finding some examples suggesting to do it that way. I don't think I can use the list of location beans version of it since the additional attribute file is optional. Any thoughts? I am using spring 3.1.1.
Thanks!
Update: Using the list approach works, however how to make it optional is still outstanding. For now I am using ignoreResourceNotFound=true, however that's not ideal because if someone mistypes the property then it won't fail...
I think you should be able to do this by using a wildcard on the property file you want to be optional. e.g.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/config/config.properties</value>
<value>file:/${additional.configs}*</value>
</list>
</property>
</bean>
Obviously you need to set the additional.configs parameter to something sensible. You can't leave it blank on systems that don't have the file, since the wildcard will then match all files! Instead you can set it to a dummy value for a non-existent file. e.g.
additional.config=/non-existent-file.txt
Spring doesn't throw an error if a wildcard doesn't match anything, so this has the affect of making this property file optional, without having to resort to ignoreResourceNotFound=true.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/config/config.properties</value>
<value>file:/${additional.configs}</value>
</list>
</property>
</bean>
If it still does not work, you can try to specify properties location without slash:
<value>file:${additional.configs}</value>

Elegant ways to separate configuration from WAR in Tomcat

I am trying to find the best way to pass complex configurations in a Spring webapp running in Tomcat. Currently I use JNDI to pass data sources and strings from the Tomcat context into the webapp, and this works well.
But, lets say I need to select the implementation of a notification service. There is no way that Spring can conditionally select which bean to instantiate (although in the past I have used a JNDI string to import a predefined configuration of beans by setting contextConfigLocation).
I've also seen many webapps which supply a configuration tool which will create a custom WAR file. In my opinion this is bad form, if for no other reason than it prevents the redeployment of WARs from upstream without many checks to ensure all the configuration has been re-applied.
Ideally I would be able to supply a Spring XML file which existed on the filesystem, outside of the webapp. But, the spring import directive does not seem to resolve ${} variables, making it impossible to supply customisations.
Are there any techniques I can employ here to properly separate complex configuration from the webapp?
If I have a specific set of beans that I'd like to configure, and this configuration must be separated from the WAR file, I usually do the following:
In applicationContext.xml:
<!-- here you have a configurer based on a *.properties file -->
<bean id="configurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file://${configDir}/configuration.properties"/>
<property name="ignoreResourceNotFound" value="false" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="searchSystemEnvironment" value="false" />
</bean>
<!-- this is how you can use configuration properties -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${smtp.host}"/>
</bean>
In configuration.properties:
smtp.host=smtp.your-isp.com
You also need to start Tomcat with -DconfigDir=/path/to/configuration/directory
If you are using Spring 3, you can take advantage of the Spring Expression Language. Let's say you have two applications app1.war and app2.war and they require a properties file named config.properties. The applications will be deployed with context paths /app1 and /app2.
Create two directories app1 and app2 in a common directory, eg. C:\myConfig\app1 and C:\myConfig\app2.
Put config.properties inside app1 and another config.properties inside app2.
Then create a file ${CATALINA_HOME}/conf/[enginename]/[hostname]/context.xml.default with the contents:
context.xml.default:
<Context>
<Parameter name="myConfigDirectory" value="C:/myConfig" override="false"/>
</Context>
The parameter myConfigDirectory will be available to all the applications on the host. It is better to create this parameter in context.xml.default rather than in server.xml, because the file can be changed later without restarting tomcat.
In the applicationContext.xml inside war you can access config.properties using the SpEL expression: "#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties", so for example you can write:
applicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties" />
</bean>
The expression will get expanded to C:/myConfig/app1 for application with contextPath /app1, and C:/myConfig/app2 for application with contextPath /app2. This will make the applications access the config.properties file based on their contextPath.
If you want to be fully portable between web containers you cannot rely on anything outside your WAR-file. In Tomcat the SecurityManager allows you to discover the physical location on disk where your code is deployed, and you can then use that knowledge to navigate the disk to a location where your configuration file is placed.
See e.g. Determine location of a java class loaded by Matlab

Categories