Modify Spring message text without restarting application? - java

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.

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?

Allow semicolon only for some specific url in Spring Security 5 i.e. StrictHttpFirewall?

We are using primefaces media component and it generates the url as /javax.faces.resource/dynamiccontent.properties;/ .pdf which contains semicolon(;).
Due to that, we are getting exception i.e. The request was rejected because the URL contained a potentially malicious String.
In Spring Security 5 update by default StrictHttpFirewall is enabled.
We can specify to allow semicolon by using setAllowSemicolon(true) in StrictHttpFirewall.
But this will be applicable for all URL.
Is there any way through which we can configure to allow semicolon only for specific URL?
As the answer above indicated I also added the following XML definition for a custom firewall that allows semi-colons.
<bean id="myHttpFirewall" class="org.springframework.security.web.firewall.StrictHttpFirewall">
<property name="allowSemicolon" value="true"/>
</bean>
<security:http-firewall ref="myHttpFirewall"/>
However byt itself this had no affect. To use that firewall in my application I had to add it to my FilterChainProxy as follows:
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list>
<security:filter-chain pattern="/**" filters="...."/>
</list>
</constructor-arg>
<property name="firewall" ref="myHttpFirewall"/>
</bean>
If you use xml configuration, Declare your bean:
<bean id="customStrictHttpFirewall"
class="org.springframework.security.web.firewall.StrictHttpFirewall">
<property name="allowSemicolon" value="true"/>
</bean>
then in security.xml ref:
<http-firewall ref="customStrictHttpFirewall"/>
if you use annotations, You can search for answers, like this!

Spring MVC 3 i18n, how to store locale in session instead of URL parameter?

I'm making a spring web app with i18n support. Right now the way the app works is that if there is a language defined in the URL parameter it'll use that, and if the parameter doesn't exist or is empty it will use the default. However I'm not satisfied with having the parameter there and I'm wondering if there's a way I can store the locale in session so it's behind the scenes and persists over all pages in the web app(because now if there is no locale parameter in the URL it'll use the defaultLocale).
My current configuration is:
applicationConfig.xml
<beans ... >
...
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="hr" />
</bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" >
<property name="paramName" value="locale" />
</bean>
</mvc:interceptors>
</beans>
I've managed to solve my problem by using instead of tags so I'll consider this question resolved. Thanks for the help.

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

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.)

How do I read JVM arguments in the Spring applicationContext.xml

I have a JSF web application with Spring and I am trying to figure out a way to reference the JVM arguments from the applicationContext.xml. I am starting the JVM with an environment argument (-Denv=development, for example). I have found and tried a few different approaches including:
<bean id="myBean" class="com.foo.bar.myClass">
<property name="environment">
<value>${environment}</value>
</property>
</bean>
But, when the setter method is invoked in MyClass, the string "${environment}" is passed, instead of "development". I have a work around in place to use System.getProperty(), but it would be nicer, and cleaner, to be able to set these values via Spring. Is there any way to do this?
Edit:
What I should have mentioned before is that I am loading properties from my database using a JDBC connection. This seems to add complexity, because when I add a property placeholder to my configuration, the properties loaded from the database are overridden by the property placeholder. I'm not sure if it's order-dependent or something. It's like I can do one or the other, but not both.
Edit:
I'm currently loading the properties using the following configuration:
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc.mydb.myschema"/>
</bean>
<bean id="props" class="com.foo.bar.JdbcPropertiesFactoryBean">
<property name="jdbcTemplate">
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="myDataSource" />
</bean>
</property>
</bean>
<context:property-placeholder properties-ref="props" />
You can use Spring EL expressions, then it is #{systemProperties.test} for -Dtest="hallo welt"
In your case it should be:
<bean id="myBean" class="com.foo.bar.myClass">
<property name="environment">
<value>#{systemProperties.environment}</value>
</property>
</bean>
The # instead of $ is no mistake!
$ would refer to place holders, while # refers to beans, and systemProperties is a bean.
May it is only a spelling error, but may it is the cause for your problem: In the example for your command line statement you name the variable env
(-Denv=development, for example...
But in the spring configuration you name it environment. But both must be equals of course!
If you register a PropertyPlaceholderConfigurer it will use system properties as a fallback.
For example, add
<context:property-placeholder/>
to your configuration. Then you can use ${environment} in either your XML configuration or in #Value annotations.
You can load a property file based on system property env like this:
<bean id="applicationProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="searchSystemEnvironment" value="false" />
<property name="locations">
<list>
<value>classpath:myapp-${env:prod}.properties</value>
</list>
</property>
</bean>
If env is not set default it to production otherwise development and testing teams can have their flavor of app by setting -Denv=development or -Denv=testing accordingly.
Use #{systemProperties['env']}. Basically pass the propertyName used in the Java command line as -DpropertyName=value. In this case it was -Denv=development so used env.
Interestingly, Spring has evolved to handled this need more gracefully with PropertySources:
http://spring.io/blog/2011/02/15/spring-3-1-m1-unified-property-management/
With a few configurations and perhaps a custom ApplicationInitializer if you are working on a Web app, you can have the property placeholder handle System, Environment, and custom properties. Spring provides PropertySourcesPlaceholderConfigurer which is used when you have in your Spring config. That one will look for properties in your properties files, then System, and then finally Environment.
Spring 3.0.7
<context:property-placeholder location="classpath:${env:config-prd.properties}" />
And at runtime set:
-Denv=config-dev.properties
If not set "env" will use default "config-prd.properties".

Categories