How to automatically reload messages.properties files in Java/Spring? - java

I've been working on an interntaional website using Java/Spring using #springMessage() tags and message.properties files. See my recent question: In Java/Spring, how to gracefully handle missing translation values?
I want to be able to edit (overwrite) the messages.properties files and be able to see the new translations immedatiately in my browser (without restarting Tomcat).
I thought that http://commons.apache.org/proper/commons-configuration/userguide/howto_filebased.html#Automatic_Reloading would be what I need, but I'm not sure how to edit my webmvc-config.xml to use that.

Figured it out. It worked after I edited webmvc-config.xml:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename">
<value>${content.path.config}/WEB-INF/messages</value>
</property>
<property name="defaultEncoding" value="UTF-8" />
<property name="cacheSeconds" value="2"/>
</bean>
(I just needed to add the cacheSeconds property.)

Related

Problems using multiple PropertySourcesPlaceholderConfigurer

Ok, I have been fighting this too long, time to ask for help. HELP!!!
I'm deploying an indipendent jar maven project that will be used as dependency into other projects.
I need that this jar loads its own properties file ("versione.properties" released inside the jar) when the application that will use it, will start up but I want that the application doesn't care about it. This should be in charge on the lib.
I want that who will use this lib, will have just to
include the right dependency inside his pom.xml
add <import resource="classpath*:*-context.xml" /> inside his spring app-context.xml to be sure to include also the lib-context.xml during the spring-context initialization
For this reason, the jar has its own spring lib-context.xml file as the following:
<context:component-scan base-package="it.eng.inps.comppsr" />
<bean id="propertyPlaceholderConfigurer2" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false" />
<property name="locations">
<list>
<value>classpath:versione.properties</value>
</list>
</property>
</bean>
<bean id="version" class="it.eng.inps.comppsr.util.Versione">
<property name="buildVersion" value="${comppsrutil.build.version}"/>
<property name="buildDate" value="${comppsrutil.build.timestamp}"/>
</bean>
As you can immagine, "versione.properties" file contains comppsrutil.build.version and comppsrutil.build.timestamp.
During my tests, I've tried also <value>classpath*:versione.properties</value>, <value>classpath:/versione.properties</value> and <value>classpath:*/versione.properties</value> but with no luck.
This library is used by a web-service application (a war inside an ear file) and this application has got its own spring app-context.xml that loads it own properties file as described by the following code snippet
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="lookupPropertiesInitializer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchSystemEnvironment" value="true" />
<property name="ignoreResourceNotFound" value="false" />
<property name="locations">
<list>
<value>file:///#{lookupPropertiesInitializer.pathToProperties}</value>
<value>classpath*:version.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="it.eng.inps.util, it.eng.inps.comppsr" />
<import resource="classpath*:*-context.xml" />
When I start the application (it runs inside JBoss EAP 7.3), I get this error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'comppsrutil.build.version' in value "${comppsrutil.build.version}"
So, it seems that something goes wrong within the lib initialization.
If I rename the "versione.properties" file in "version.properties" (so with the same name used by the app properties file), this error desappear, I think, because it is loaded by the application PropertyPlaceholderConfigurer, so the lib property file is well located.
For this reason I think that the bean propertyPlaceholderConfigurer2 defined inside lib-context.xml, doesn't work as I expected but I didn't understand why.
Does anyone give me any tips?

Spring Could not resolve placeholder while loading config file form filesystem

I'm facing an issue with spring placeholder configuration. I've searched the web trying to find a solution but nothing worked for me at all.
We had used to use spring configurer for loading our .properties files and everything worked fine since the configfiles where located in META-INF dir.
Now we need to have our config files located in /etc/sep/properties directory or in some other filesystem directory.
I tried to use
<context:property-placeholder location="file:/etc/sep/properties/jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.databaseurl}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="${jdbc.initialPoolSize}" />
</bean>
the content of /etc/sep/properties/jdbc.properties is following:
cat /etc/sep/properties/jdbc.properties
jdbc.driverClassName= org.postgresql.Driver
jdbc.dialect=org.hibernate.dialect.PostgreSQLDialect
jdbc.databaseurl=jdbc:postgresql://localhost:5432/sep?characterEncoding=utf8&autoReconnect=true
jdbc.username=****
jdbc.password=****
I also tried using another approach as folows, but it worked for me neither.
<context:property-placeholder properties-ref="prop" />
<util:properties id="prop" location="reso"/>
<bean id="reso" class="org.springframework.core.io.FileSystemResource">
<constructor-arg index="0" value="/etc/sep/properties/jdbc.properties" />
</bean>
I don't know if it matters but we are using maven building, so that the application-context.xml is placed in core-lib.jar which is used in our web-app as dependency. Other config, such as logging work great.
I would be grateful for any suggestions.
This is just an idea but it may work,
Have you checked that the .property file has the correct access rights? I mean, is it accessible by the user that runs your Spring application?
It would help a lot if you show the error displayed.
Ok, I've finally resolved it. There were two things about it.
At First: My tomcat server was not updating deployed files properly.
And finally I'm not pretty sure if it helped, but we added one more slash after file: specification, so that the result was:
<context:property-placeholder location="file:///etc/sep/properties/*.properties" />
Now it is loading all config files properly.

How to read jBoss configuration files in Spring?

I want to have a project independent configuration file that I can access from different projects. What I'm currently trying (and does not give me good results at all):
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="${JBOSS_HOME}/standalone/configuration/wro.properties" />
</bean>
I use Spring 3 and JBoss 7.1. My configuration files are under jboss/standalone/configuration/....properties. Besides that I want to read message files from that same directory with:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="messages,local" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
Currently it looks for messages.properties and local.properties in src folder?
This is the solution I ended up using, which is platform independent and portable:
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="file:#{systemProperties['jboss.home.dir']}/standalone/configuration/wro.properties" />
</bean>
The configuration of the message source is identical.
A ResourceBundleMessageSource uses the basenames provided to (and the locale) to build a resource name (ex. message.properties) which is eventually (in the call stack) used by java.util.ResourceBundle.Control#newBundle(...). This resource name is then looked for on the classpath starting at its root (ex. /message.properties).
If you're on an IDE like Eclipse, your classpath very likely starts at src.
If jboss/standalone/configuration/... is on your classpath as well and the properties file are in there, you can change the basenames to
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="jboss/standalone/configuration/messages,jboss/standalone/configuration/local" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>

Modify Spring message text without restarting application?

I am doing a Spring web application. I use Spring 3.1 and Eclipse. I run the application via Jetty within Eclipse.
I have many JSP pages that contain text such as this:
<spring:message code="label.subject"/>
This type of text comes from a file called messages_en.properties defined in Spring context:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
I need to constantly modify the text in messages_en.properties. However, new text does not show up in the application without restarting Jetty, which is quite inconvenient to me.
How can I modify Spring message text without restarting Jetty?
Thanks for your help!
Regards.
The answer is in ResourceBundleMessageSource's documentation itself: use ReloadableResourceBundleMessageSource.
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
<property name="cacheSeconds" value="1"/>
</bean>
You can do it in many ways. You can monitor your files for change with a file monitor and reload the resource programmatically. You can take a look at this: http://docs.oracle.com/javase/tutorial/essential/io/notification.html
Basically the idea would be upon starting your app to register a file monitor on your resource and then when you change it, just reinitialize your resource.

context:property-placeholder not working for multiple files

I have got 2 properties file with me. I have mentioned both the files in the context:property-placeholder like this...
<context:property-placeholder location="conf/ConfServer.conf,conf/LicenseSettings.properties" />
Also I have tried this
<context:property-placeholder location="conf/ConfServer.conf,conf/LicenseSettings.properties" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>conf/LicenseSettings.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
Both the above mentioned methods I have tried are not working.
Can anyone spot out the mistake and help me out of this?
I already referred to this, but it didn't work good for me.
You can specify multiple context:property-placeholder tags within your configuration file. You can also specify which will be loaded first using the order attribute.
<context:property-placeholder location="conf/ConfServer.conf" order="1" ignore-unresolvable="true" />
<context:property-placeholder location="conf/LicenseSettings.properties" order="2" ignore-unresolvable="true" />
Can you try referring these properties from project root directory
conf/ConfServer.conf
conf/LicenseSettings.properties
These may not be referred correctly.

Categories