Obtaining configured properties from Springs - spring

I am trying to obtain properties' values configured in Springs context with Environment bean (like in spring PropertyPlaceholderConfigurer and context:property-placeholder checked answer).
public class SpringsPropertiesProvider implements IPropertiesProvider {
#Autowired Environment envinronment;
#Override
public String getProperty(String key) {
return envinronment.getProperty(key);
}
}
This class is registered with following xml:
<context:property-placeholder
location="classpath:myproject/example.properties" />
<context:annotation-config />
<bean class="myproject.SpringsPropertiesProvider" id="springsPropertiesProvider"/>
But SpringsPropertiesProvider.getProperty method does not return values configured within example.properties file.
What I am doing wrong and how can I get dynamic access to properties configured by placeholderconfigurer?
PS.
During environment.getPropert(key) call debugging shows that org.springframework.core.env.PropertySourcesPropertyResolver has only two entries in its propertySources field ([systemProperties,systemEnvironment]) and both entries does not contain any keys defined within example.properties.

Try this
<context:property-placeholder
location="classpath:myproject/example.properties" ignore-resource-not-found="true"/>
If the project does not startup then that means spring was not able to locate the properties file.
Speaking of which, what does your project structure look like?
Update:
The following link explains why this is not working

Related

Accessing user defined properties using spring expression language

Is it poosible to read user defined .properties file using SpEL? I know we can do something like this for systemProperties
#Value("#{ systemProperties['user.region'] }")
I want to access a property in a user defined properties file. Also is it possible to use SpEL in #ContextConfiguration annotation? I want to set the value of this annotation using a properties file defined by me.
Yes, you can do:
private #Value("${propertyName}") String propertyField;
And you will need PropertyPlaceholderConfigurer
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:myProps.properties" />
or with java config
#PropertySource("classpath:myProps.properties")
on the config class
Yes, you can use...
#Bean
public Properties props() {
...
}
#Value("#{props.foo}")
How do you want to use SpEL in #ContextConfiguration ?

New in Spring: Load Application Context

I am new with Spring.
So far in my application, every time I need to use a bean I load the XML.
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
So, in every class where I need to load a particular bean I use the above line.
In terms of efficciency or right use, I would like to know if this is the correct use (I suspect it is not) or if the context should be passed as parameter everytime one class need it.
Thanks
I assume that you are using Spring in non-web application.
If you are creating new application context each time you need to retrieve a bean, it is indeed not the correct solution. You should create application context once per application.
So the solution would be as you suggest passing the application context instance to classes that need it, or to otherwise ensure that you use the same instance in your application.
One of many issues you might run into with your current setup is problem with bean scoping. Spring has singleton beans, but those are singletons only within one application context. So if you retrieve a bean that is singleton from two different application contexts, they will not be the same instance. Other issues will involve performance, because application context creation will be expensive operation.
If you use spring, then you should use it everywhere. So instead of passing the application context around, put every bean in there and let Spring connect the dots for you.
In a nutshell, never call new yourself. Ask Spring for the bean instead. If a bean has dependencies, use constructor injection.
That way, Spring can create all the beans for you, wire them up and return fully working instances without you having to worry about where something comes form.
You should also read the articles about Java-based container configuration.
Related articles:
Spring by Example: Basic Constructor Injection
Spring Constructor-based Dependency Injection
Just Load the XML file and create the application context object. As long as XML is loaded, Spring will inject all the object dependencies.
So, You don't need to load or create application context object again and again. Just check your console with the below example, you will understand it.
Example: In main method you only write this line of code.
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
interface IParent {
public void whoAreYou();
}
class ChildA implements IParent {
public ChildA (IParent ChildB) {
super();
System.err.println("Constructor ChildA ");
ChildB.whoAreYou();
}
public ChildA (){
System.err.println("Constructor ChildA ");
}
#Override
public void whoAreYou() {
System.err.println("ChildA ");
}
}
class ChildB implements IParent {
public ChildB (){
System.err.println("Constructor ChildB");
}
#Override
public void whoAreYou() {
System.err.println("ChildB");
}
}
XML File :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:annotation-config/>
<bean id="childA" class="com.spring.xmlbased.config.ChildA">
<constructor-arg>
<bean id="ChildB" class="com.spring.xmlbased.config.ChildB"/>
</constructor-arg>
</bean>
</beans>
Please let me know, if u need further clarification.

org.springframework.core.env.Environment.getProperty(String) returns null

I am trying to access some properties programmatically in a controller of a spring mvc application. I configured it by xml. I tried both PropertyPlaceholderConfigurer and <context:property-placeholder />
I tried to use in the controller class(saw it in a working example but it was configured with #Configuration):
#Inject
private Environment environment;
and afterwards i use:
environment.getProperty("upload.location")
but i get a null value. The entry exists in the properties file(i have only one) and also using ${...} in the xml works
A much simpler way - use #Value to inject the system property, as follows:
private #Value("${systemPropertyFoo}") String systemPropertyFoo;
In your case (I"m assuming the variable is a system property):
private #Value("${upload.location}") String uploadLocation;
This annotation depends on the PropertyPlaceholderConfigurer, so keep it in your config.

reading a dynamic property list into a spring managed bean

I've been searching but cannot find these steps. I hope I'm missing something obvious.
I have a properties file with the following contents:
machines=A,B
I have another file like that but having a different number of members in the machines element like this:
machines=B,C,D
My question is how do I load this variable-length machines variable into a bean in my spring config in a generic way?
something like this:
<property name="machines" value="${machines}"/>
where machines is an array or list in my java code. I can define it however I want if I can figure out how to do this.
Basically I'd rather have spring do the parsing and stick each value into a list element instead of me having to write something that reads in the full machines string and do the parsing myself (with the comma delimiter) to put each value into an array or list. Is there an easy way to do this that I'm missing?
You may want to take a look at Spring's StringUtils class. It has a number of useful methods to convert a comma separated list to a Set or a String array. You can use any of these utility methods, using Spring's factory-method framework, to inject a parsed value into your bean. Here is an example:
<property name="machines">
<bean class="org.springframework.util.StringUtils" factory-method="commaDelimitedListToSet">
<constructor-arg type="java.lang.String" value="${machines}"/>
</bean>
</property>
In this example, the value for 'machines' is loaded from the properties file.
If an existing utility method does not meet your needs, it is pretty straightforward to create your own. This technique allows you to execute any static utility method.
Spring EL makes easier.
Java:
List <String> machines;
Context:
<property name="machines" value="#{T(java.util.Arrays).asList('${machines}')}"/>
If you make the property "machines" a String array, then spring will do it automatically for you
machines=B,C,D
<property name="machines" value="${machines}"/>
public void setMachines(String[] test) {
Since Spring 3.0, it is also possible to read in the list of values using the #Value annotation.
Property file:
machines=B,C,D
Java code:
import org.springframework.beans.factory.annotation.Value;
#Value("#{'${machines}'.split(',')}")
private List<String> machines;
You can inject the values to the list directly without boilerplate code.(Spring 3.1+)
#Value("${machines}")
private List<String> machines;
for the key "machines=B,C,D" in the properties file by creating following two instance in your configuration.
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public ConversionService conversionService() {
return new DefaultConversionService();
}
Those will cover all the separate based split and whitespace trim as well.

Apply dynamic properties to a bean at runtime

Assume I have a bean DialogBox, with properties for height and width:
public class DialogBox {
int x;
int y;
...
}
In my applicationContext.xml I would define properties as reasonable defaults:
<bean id="dialogbox" class="DialogBox">
<property name="x" value="100"/>
<property name="y" value="100"/>
</bean>
We have multiple clients that use the dialogBox bean, and each wants a custom value for x and y. One route we have discusses is having multiple properties files, one for each client, and have the client id map to the proper file, for example client 123 would map to dialogbox_123.properties:
dialogbox_123.properties:
x=200
y=400
Then at runtime when the bean is requested, spring would look to see if a custom properties file exists for the client, and use those properties, otherwise use the defaults. I am aware of the PropertyOverrideConfigurer, but AFAIK this only works when the context is started so will not work for our purposes. Is there an existing facility in spring to achieve this, or can someone recommend another way?
Use FactoryBean (as already suggested) to customize instantiation.
set scope="prototype" on the bean, so that each time an instance is required, a new one should be created.
In case you want to inject the prototype bean into a singleton bean, use lookup-method (Search for lookup-method here)
I'm not sure if this would fit your case though. Another suggestion would be:
In #PostConstruct methods of your various "clients" set the properties as desired on the already injected dialog window. Like:
public class MyDialogClient {
#Autowired
private Dialog dialog;
#PostConstruct
public void init() {
dialog.setWidth(150); //or read from properties file
dialog.setHeight(200);
}
...
}
Again, in this case, you can play with the scope atrribute.
Take a look at the Spring OSGi Compendium services, they've got a property manager called "managed-properties", which allows you not only to update the properties at runtime, but while the application is running if you select the "container-managed" update strategy.
If I understood the question, you can use a FactoryBean to customize bean creation logic in Spring.

Resources