How to log properties loaded by Spring? - spring

is it possible to simply log all the content of the properties file loaded by spring with <context:property-placeholder /> ?
Thanks

You can set the log level of org.springframework.core.env.PropertySourcesPropertyResolver to "debug". Then, you will be able to see the value of the properties during resolving.

You can do it this way:
<context:property-placeholder properties-ref="myProperties"/>
<bean id="myProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
.. locations
</list>
</property>
</bean>
and add a logging bean similar to one below (here annotation based and with slf4j api):
#Component
public class PropertiesLogger {
private static Logger logger = LoggerFactory.getLogger(PropertiesLogger.class);
#Resource("myProperties")
private Properties props;
#PostConstruct
public void init() {
for (Map.Entry<Object, Object> prop : props.entrySet()) {
logger.debug("{}={}", prop.getKey(), prop.getValue());
}
}
}

Related

Load configuration files dynamically using Spring

We already have a setup in which we are loading files like :
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${AN_ENV_CONFIGURED_DIR}/project.properties</value>
</list>
</property>
The config files are there in server in a separate location. I want to load the configuration files dynamically if there is a change in it. Now since I already have this setup is there a simple way to reload config files from Spring other than using TimerTask and if its the only way then still its not sufficing the need to loading the file immediately.
You can use ReloadableResourceBundleMessageSource, following is the code snippet.
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:${AN_ENV_CONFIGURED_DIR}/project.properties</value>
</list>
</property>
<property name="cacheSeconds" value="1"/>
</bean>
For more info : http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/ReloadableResourceBundleMessageSource.html
Use the below bean to reload config.properties every 1 second.
#Component
public class PropertyLoader {
#Autowired
private StandardEnvironment environment;
#Scheduled(fixedRate=1000)
public void reload() throws IOException {
MutablePropertySources propertySources = environment.getPropertySources();
PropertySource<?> resourcePropertySource = propertySources.get("class path resource [config.properties]");
Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("/config.properties");
properties.load(inputStream);
inputStream.close();
propertySources.replace("class path resource [config.properties]", new PropertiesPropertySource("class path resource [config.properties]", properties));
}
}
Your main config will look something like:
#EnableScheduling
#PropertySource("classpath:/config.properties")
public class HelloWorldConfig {
}
Then access the property any where:
#Autowired
private Environment environment;
environment.get("my.property");

Reading message from properties file in spring4

I am facing an issue in reading the properties file in spring mvc4. To read messages I have added following in spring-servlet.xml file located under WEB-INF folder.
<context:component-scan base-package="com.test.restful.producer" />
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
In my controller class,
#Value("${MSG}")
private String msg;
i am getting msg as null. Please helpout me how to load properties file. My appilcation.properties file is available in classpath only.
I am using Spring-4.0.5
Thank you
You can try this xml for creating properties bean.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:propertyFile.properties" name="propertiesBean"/>
Or go for non xml version as below
#PropertySource("classpath:propertyFile.properties")
public class AppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

Getting an EhCache instance with Spring... intelligently

I need to get a specific EhCache instance by name and I'd prefer to autowire if possible. Given the following automatically configured controller, how can I autowire in the cache instance I'm looking for?
#Controller
public class MyUniqueService {
...
}
<beans ...>
<ctx:component-scan base-package="my.controllers"/>
<mvc:annotation-driven />
</beans>
How do I configure EhCache in my application context? I don't see any log messages from EhCache about it loading the ehcache.xml file in my /WEB-INF/ directory. How do I make it load it?
How can I integrate EhCache with my Spring application to have it load the ehcache.xml file from my /WEB-INF/ directory and autowire a cache by a given name into my MyUniqueService controller?
First you need to create a Ehcache CacheManager singleton in you app context like this:
<bean id="myEhCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:my-ehcache.xml"/>
</bean>
Here configLocation is set to load from classpath or use value="/WEB-INF/my-ehcache.xml".
In your controller simply inject the CacheManager instance:
#Controller
public class MyUniqueService {
#Resource(name="myEhCacheManager")
private CacheManager cacheManager;
...
}
Alternatively, if you'd like to go the "entirely autowired" route, do:
<bean class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/ehcache.xml"/>
</bean>
</property>
</bean>
Setup your class like so:
#Controller
public class MyUniqueService {
#Autowired
private org.springframework.cache.CacheManager cacheManager;
public org.springframework.cache.Cache getUniqueObjectCache() {
return cacheManager.getCache("uniqueObjectCache");
}
}
uniqueObjectCache corresponds to this cache instance in your ehcache.xml cache definition:
<cache name="uniqueObjectCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"
transactionalMode="off"/>
There isn't a way to inject an actual cache instance, but as shown above, you can inject a cache manager and use it to get the cache you're interested in.
Assuming you have cacheManager defined:
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:/ehcache.xml"/>
</bean>
You can get/inject specific cache like this:
#Value("#{cacheManager.getCache('myCacheName')}")
private Cache myCache;
See also examples how to use Spring EL inside the #Value() http://www.mkyong.com/spring3/spring-el-method-invocation-example/ if you are interested.
You can also use autowire if the context can find a bean with the correct class. Here is how I configured my xml
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation">
<value>WEB-INF/ehcache.xml</value>
</property>
</bean>
<bean id="cache" class="net.sf.ehcache.Cache" factory-bean="cacheManager" factory-method="getCache">
<constructor-arg value="CacheNameHere" />
</bean>
And my java class
#Autowired
private net.sf.ehcache.Cache cache;
This setup works for me.
Indeed! Or if you want to use a java config class:
#Inject
private ResourceLoader resourceLoader;
#Bean
public CacheManager cacheManager() {
EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
try {
ehCacheCacheManager.setCacheManager(ehcacheCacheManager().getObject());
} catch (Exception e) {
throw new IllegalStateException("Failed to create an EhCacheManagerFactoryBean", e);
}
return ehCacheCacheManager;
}
#Bean
public FactoryBean<net.sf.ehcache.CacheManager> ehcacheCacheManager() {
EhCacheManagerFactoryBean bean = new EhCacheManagerFactoryBean();
bean.setConfigLocation(resourceLoader.getResource("classpath:ehcache.xml"));
return bean;
}

Inject a file resource into Spring bean

What is a good way to inject some file resource into Spring bean ?
Now i autowire ServletContext and use like below. Is more elegant way to do that in Spring MVC ?
#Controller
public class SomeController {
#Autowired
private ServletContext servletContext;
#RequestMapping("/texts")
public ModelAndView texts() {
InputStream in = servletContext.getResourceAsStream("/WEB-INF/file.txt");
// ...
}
}
Something like this:
#Controller
public class SomeController {
private Resource resource;
public void setResource(Resource resource) {
this.resource = resource;
}
#RequestMapping("/texts")
public ModelAndView texts() {
InputStream in = resource.getInputStream();
// ...
in.close();
}
}
In your bean definition:
<bean id="..." class="x.y.SomeController">
<property name="resource" value="/WEB-INF/file.txt"/>
</bean>
This will create a ServletContextResource using the /WEB-INF/file.txt path, and inject that into your controller.
Note you can't use component-scanning to detect your controller using this technique, you need an explicit bean definition.
Or just use the #Value annotation.
For single file:
#Value("classpath:conf/about.xml")
private Resource about;
For multiple files:
#Value("classpath*:conf/about.*")
private Resource[] abouts;
What do you intend to use the resource for? In you example you don't do anything with it.
From it's name, however, it looks like you are trying to load internationalisation / localisation messages - for which you can you a MessageSource.
If you define some beans (possibly in a separate messages-context.xml) similar to this:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>WEB-INF/messages/messages</value>
</list>
</property>
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en_GB" />
</bean>
Spring will load your resource bundle when you application starts. You can then autowire the MessageSource into your controller and use it to get localised messages:
#Controller
public class SomeController {
#Autowired
private MessageSource messageSource;
#RequestMapping("/texts")
public ModelAndView texts(Locale locale) {
String localisedMessage = messageSource.getMessage("my.message.key", new Object[]{}, locale)
/* do something with localised message here */
return new ModelAndView("texts");
}
}
NB. adding Locale as a parameter to your controller method will cause Spring to magically wire it in - that's all you need to do.
You can also then access the messages in your resource bundle in your JSPs using:
<spring:message code="my.message.key" />
Which is my preferred way to do it - just seems cleaner.

How to inject complete propertiesfile in a springbean

I have a properties-file with a lot of values and I do not want to list them in my bean-configuration-file separately. E.g.:
<property name="foo">
<value>${foo}</value>
</property>
<property name="bar">
<value>${bar}</value>
</property>
and so on.
I imagine to inject all completely as java.util.Properties or less as a java.util.Map.
Is there a way to do so?
For Java config you can use something like this:
#Autowired #Qualifier("myProperties")
private Properties myProps;
#Bean(name="myProperties")
public Properties getMyProperties() throws IOException {
return PropertiesLoaderUtils.loadProperties(
new ClassPathResource("/myProperties.properties"));
}
You can also have multiple properties this way, if you assign a unique bean name (Qualifier) to each instance.
Yes, you can use <util:properties> to load a properties file and declare the resulting java.util.Properties object as a bean. You can then inject that as you would any other bean property.
See section C.2.2.3 of the Spring manual, and their example:
<util:properties id="myProps" location="classpath:com/foo/jdbc-production.properties"
Remember to declare the util: namespace as per these instructions.
For Java Config, use PropertiesFactoryBean:
#Bean
public Properties myProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/myProperties.properties"));
Properties properties = null;
try {
propertiesFactoryBean.afterPropertiesSet();
properties = propertiesFactoryBean.getObject();
} catch (IOException e) {
log.warn("Cannot load properties file.");
}
return properties;
}
And then, set the properties object:
#Bean
public AnotherBean myBean() {
AnotherBean myBean = new AnotherBean();
...
myBean.setProperties(myProperties());
...
}
Hope this helps for those interested in Java Config way.
It's possible with the PropertyOverrideConfigurer mechanism:
<context:property-override location="classpath:override.properties"/>
Properties file:
beanname1.foo=foovalue
beanname2.bar.baz=bazvalue
The mechanism is explained in the section 3.8.2.2 Example: the PropertyOverrideConfigurer
This is an echo of #skaffman's response in this SO question. I am adding more details to help others and myself when I try to solve this in the future.
There are three ways to inject the property file
Method 1
<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:com/foo/jdbc-production.properties</value>
</list>
</property>
</bean>
Reference ( link )
Method 2
<?xml version="1.0" encoding="UTF-8"?>
<beans
...
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="...
...
http://www.springframework.org/schema/util/spring-util.xsd"/>
<util:properties id="myProps" location="classpath:com/foo/jdbc-production.properties"/>
Reference ( link )
Method 3
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:com/foo/jdbc-production.properties" />
</bean>
Reference ( link )
Essentially, all the methods can create a Properties bean out of the properties file. You may even directly inject a value from the property file by using #Value injector
#Value("#{myProps[myPropName]}")
private String myField;

Resources