Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 551 Vote(s) - 3.47 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Programmatic access to properties created by property-placeholder

#1
I'm reading properties file using `context:property-placeholder`. How can I access them **programatically** (`@Value` doesn't work - I don't know property titles at the moment of developing)?

The main problem is I can't change `applicationContext.xml` file because it's setted up by "parent" framework

ps. It's strange but `Environment.getProperty` returns `null`
Reply

#2
No you can't. `PropertyPlaceholderConfigurer` is a [`BeanFactoryPostProcessor`][1], it is only "alive" during bean creation. When it encounters a `${property}` notation, it tries to resolve that against its internal properties, but it does not make these properties available to the container.

That said: similar questions have appeared again and again, the proposed solution is usually [to subclass `PropertyPlaceHolderConfigurer`][2] and make the Properties available to the context manually. Or [use a `PropertiesFactoryBean`][3]


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#3
Spring follows Inversion Of Control approach, this means that we can simply inject particular property into POJO. But there are some cases, when you would like to access property given by name directly from your code - some might see it as anti-pattern - this is palpably true, but lets concentrate on how to do it.



The `PropertiesAccessor` below provides access to properties loaded by `Property Placeholder` and encapsulates container specific stuff. It also caches found properties because call on `AbstractBeanFactory#resolveEmbeddedValue(String)` is not cheap.



@Named
public class PropertiesAccessor {

private final AbstractBeanFactory beanFactory;

private final Map<String,String> cache = new ConcurrentHashMap<>();

@Inject
protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

public String getProperty(String key) {
if(cache.containsKey(key)){
return cache.get(key);
}

String foundProp = null;
try {
foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");
cache.put(key,foundProp);
} catch (IllegalArgumentException ex) {
// ok - property was not found
}

return foundProp;
}
}
Reply

#4
Found answer at below site:

[To see links please register here]


<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="propertyConfigurer">
<property name="properties" ref="props" />
</bean>
<bean id="props" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="file:C:/CONFIG/settings.properties"/>
</bean>
Reply

#5
We use the following approach to access properties for our applications

<!-- language: xml -->

<util:properties id="appProperties" location="classpath:app-config.properties" />
<context:property-placeholder properties-ref="appProperties"/>

Then you have the luxury of just autowiring properties into beans using a qualifier.

<!-- language: java -->

@Component
public class PropertyAccessBean {

private Properties properties;

@Autowired
@Qualifier("appProperties")
public void setProperties(Properties properties) {
this.properties = properties;
}

public void doSomething() {
String property = properties.getProperty("code.version");
}

}

If you have more complex properties you can still use ignore-resource-not-found and ignore-unresolvable. We use this approach to externalise some of our application settings.

<!-- language: xml -->

<util:properties id="appProperties" ignore-resource-not-found="true"
location="classpath:build.properties,classpath:application.properties,
file:/data/override.properties"/>
<context:property-placeholder ignore-unresolvable="true" properties-ref="appProperties"/>
Reply

#6
Let's asume that you the properties file defined in that "parent" framework

<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:main.properties" />
</bean>

You can use the @Value annotation in this way:

@Value( value = "#{applicationProperties['my.app.property']}" )
private String myProperty;

Reply

#7
@Value

annotation works on new releases of Spring (tested on v3.2.2)
Here is how it is done:

1. Map your properties file in spring configuration file

<!--Import Info:
xmlns:context="http://www.springframework.org/schema/context"

[To see links please register here]

[To see links please register here]

;

<context:property-placeholder location="classpath:/app-config.properties" />
2. Create app-config.properties inside (root) your source folder

my.property=test
my.property2=test2

3. Create a controller class

@Controller
public class XRDSBuilder
{
@Value("${my.property}")
private String myProperty;

public String getMyProperty() { return myProperty; }
}

Spring will automatically map the content of my.property to your variable inside the controller


[Mapping to a list][1]

Property value:

my.list.property=test,test2,test3

Controller class configuration:

@Value("#{'${my.list.property}'.split(',')}")
private List<String> myListProperty;


[Advanced mapping][2]

@Component("PropertySplitter")
public class PropertySplitter {

/**
* Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2
*/
public Map<String, String> map(String property) {
return this.map(property, ",");
}

/**
* Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2
*/
public Map<String, List<String>> mapOfList(String property) {
Map<String, String> map = this.map(property, ";");

Map<String, List<String>> mapOfList = new HashMap<>();
for (Entry<String, String> entry : map.entrySet()) {
mapOfList.put(entry.getKey(), this.list(entry.getValue()));
}

return mapOfList;
}

/**
* Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4
*/
public List<String> list(String property) {
return this.list(property, ",");
}

/**
* Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2
*/
public List<List<String>> groupedList(String property) {
List<String> unGroupedList = this.list(property, ";");

List<List<String>> groupedList = new ArrayList<>();
for (String group : unGroupedList) {
groupedList.add(this.list(group));
}

return groupedList;

}

private List<String> list(String property, String splitter) {
return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property);
}

private Map<String, String> map(String property, String splitter) {
return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property);
}
}

Property value:

my.complex.property=test1:value1,test2:value2

Controller class:

@Value("#{PropertySplitter.map('${my.complex.property}')}")
Map<String, String> myComplexProperty;


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#8
Create beans for your properties before putting them in property-placeholder to make the properties easy to access in-code.

Ex:

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="resources" value="classpath:META-INF/spring/config.properties" />
</bean>

<context:property-placeholder properties-ref="configProperties" ignore-unresolvable="true"/>

Code:

@Autowired
private PropertiesFactoryBean configProperties;

You can also use @Resource(name="configProperties")
Reply

#9
<util:properties id="prop" location="location of prop file" />

This return java.util.Properties object

In JAVA Code

Properties prop = (Properties) context.getBean("prop");

Now you can access ,

prop.getProperty("key");
Reply

#10
This works if you need to scan multiple locations for your properties ...

<bean id="yourProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<array value-type="org.springframework.core.io.Resource">
<value>classpath:yourProperties.properties</value>
<value>file:../conf/yourProperties.properties</value>
<value>file:conf/yourProperties.properties</value>
<value>file:yourProperties.properties</value>
</array>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
<context:property-placeholder properties-ref="yourProperties" ignore-unresolvable="true"/>

And then in your actual classes ...

@Autowired
Properties yourProperties;

Tested using Spring 5.1.4
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through