How to manually reload properties file from Spring messageSource - java

For spring framework, I want to manually reload data inside properties file. Actually, have to write reload servlet that will manually reload data when I manually run this servlet file.
I have already defined spring configuration for messageSource.
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
p:basename="classpath:/message" />
But don't want to autoreload at certain amount of time for example can autoreload when setting:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
p:basename="classpath:/message"
p:cacheSeconds="1" />
I tried before by clearCaches() but not autoreload.

It is working now. Need to inject messageSource into servlet file and call clearCache(). It does clear previous properties data and reload updated properties file.
In ReloadServlet.java,
ReloadableResourceBundleMessageSource rs = Global.getBean("messageSource", ReloadableResourceBundleMessageSource.class);
rs.clearCache();
In Global.java,
private static ApplicationContext context;
public static <T> T getBean(String s, Class<T> type) {
return context.getBean(s, type);
}
Thanks.

I don't know, what you mean manually reload properties file. Spring already provide to load properties file as below.
Configure your properties file in your spring configuration file. Eg. applicationContext.xml or spring-beans.xml
<util:properties id="MY_CONFIG" location="classpath:MY_CONFIG.properties"/>
In your sping bean, inject as below
#Resource(name = "MY_CONFIG")
private Properties properties;
Your servlet invoke that spring bean.
Update
If you would like to load the file from Servlet or other classes directly
Load properties file in Servlet/JSP

Related

How to load two ResourceBundles and inject them separately

I am using Spring for loading localized resource bundles into my application. Here is what I have done.
<bean id="systemMessages" class="o.s.c.s.ResourceBundleMessageSource">
<property name="basename" value="locale/system">
</bean>
<bean id="clientMessages" class="o.s.c.s.ResourceBundleMessageSource">
<property name="basename" value="locale/client">
</bean>
I want to load messages based on the locale in my controller, and I tried both these ways below
#Autowired
#Qualifier("clientMessages")
ResourceBundleMessageSource clientMessages;
#Resource(name="systemMessages")
ResourceBundleMessageSource systemMessages;
EDIT
The application is a JAXRS application and the injection is being tried in a Global Exception Mapper. From the comments I now understand that this class would have been created by the JAXRS container and not Spring ( Code below). How to let Spring know that this injection must work?
import javax.ws.rs.WebApplicationException;
//other imports
public class GlobalWebApplicationException extends WebApplicationException{
private String systemMessage;
private String clientMessage;
//Autowire the multiple resourcebundles
public GlobalWebApplicationException (String key, Locale locale) {
// this is where I want to use the injected object fetch the property
}
public doSomething(){
// Business Logic
}
}
But the injection is not happening and I am getting an NPE. How do I achieve this?
When using Spring and having it do auto wiring using annotations the fields cannot be null. The dependencies need to be satisfied on startup of the application. If that doesn't happen there can be 1 of 2 things wrong
You haven't enabled annotation processing
You aren't using a spring managed bean but are creating instances yourself
For the first option add <context:annotation-config /> to your application context, or if you want to do component scanning add <context:component-scan /> the latter already implies annotation processing.
For the second option you need to make your bean a spring managed bean and use that instead of creating new instances yourself.

Spring Injection of XML Data Files to Java Classes

Is there a way to easily use Spring Injection to grab one or more *.xml data files from a folder location (either in a deployed *.war or on a server folder) and inject that data from the *.xml files into a Java class (e.g. in a web service)? I have been asked by another programmer if I can do this.
I've had a look at a few links on stackoverflow, but so far the easiest way I've found is to put the *.xml files into a particular folder location (e.g. WEB-INF/classes) and use something like this to retrieve them:
Thread.currentThread().getContextClassLoader.getResourceAsStream("/WEB-INF/classes/data.xml")
The above method is easy; however, it is obviously not Spring Injection. Is there a way to do this using Spring Injection instead? I would have thought that since configuration files can be loaded this way, that xml data could also be loaded similarly.
Thanks.
Spring provides a class called Resource which you can use to inject resource files into a spring bean. So you can do this:
public class Consumer {
public void setResource(Resource resource) {
DataInputStream resourceStream = new DataInputStream(resource.getInputStream());
// ... use the stream as usual
}
...
}
Then:
<bean class="Consumer">
<property name="resource" value="classpath:path/to/file.xml"/>
</bean>
or,
<bean class="Consumer">
<property name="resource" value="file:path/to/file.xml"/>
</bean>
You can also directly use the #Value annotation:
public class Consumer {
#Value("classpath:path/to/file.xml")
private Resource resource;
...
}

Read all properties files in a directory

Right now I am reading properties file in spring as
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="customer/messages" />
</bean>
Here I am specifying that read messages.properties in customer directory. But what I want to do is to specify a directory and ask spring to read all properties file present in that directory. How can I achieve that?
I tried value="customer/*" but it doesn't work.
Using <context:property-placeholder> is more recommended as:
<context:property-placeholder
locations="classpath:path/to/customer/*.properties" />
You can also do this using Spring 3.1+ Java Config with:
#Bean
public static PropertyPlaceholderConfigurer properties(){
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[ ]
{ new ClassPathResource( "path/to/customer/*.properties" ) };
ppc.setLocations( resources );
ppc.setIgnoreUnresolvablePlaceholders( true );
return ppc;
}
You may need to tailor the type of resource to load properties from:
Resource abstract implementations
Built-in resource implementation
A complete walk through of properties in Spring
To use a property, you can use Environment abstraction. It can be injected and used to retrieve property values at runtime.
Finally used approach given on following blog -
http://rostislav-matl.blogspot.in/2013/06/resolving-properties-with-spring.html

How to read properties (or any other text) file in Java Spring MVC app?

I need to read java properties file inside my Spring MVC app but I can't find the way to do that. I tried several answers from similar question here on SO, but I was unsuccessful. I'm new to Java, and especially Spring MVC so I probably messed up something.
I'm not sure anymore that the file is being successfully deployed. I'm using Tomcat btw.
If you are using Spring 3.1+ you can use the #PropertySource annotation:
#Configuration
#PropertySource("classpath:/com/example/app.properties")
public class AppConfig {
// create beans
}
or for XML-based configuration you can use the <context:property-placeholder>:
<beans>
<context:property-placeholder location="classpath:com/example/app.properties"/>
<!-- bean declarations -->
</beans>
then you can autowire the key in the properties file using the #Value annotation:
#Value("${property.key}") String propertyValue;
Read more details in the Spring reference docs.
You can have properties files automatically loaded in Spring by using the PropertySourcesPlaceholderConfigurer.
Here is an example of configuring a PropertySourcesPlaceholderConfigurer using Spring JavaConfig:
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer props = new PropertySourcesPlaceholderConfigurer();
props.setLocations(new Resource[] {
new ClassPathResource("/config/myconfig.properties"),
new ClassPathResource("version.properties")
});
}
This will load the properties from the files above on the classpath.
You can use these properties in property replacements within your application. For example, assume that there is a property in one of those files above named myprop. You could inject myprop's value into a field using the following:
#Value(${myprop})
private String someProperty;
You can also access the values of the properties by injecting Spring's Environment object into your classes.
#Resource
private Environment environment;
public void doSomething() {
String myPropValue = environment.getProperty("myprop");
}
In order to read any old file from within a web application the link that Frederic posted in the comments above provides a good explanation of the normal classloader hurdles one encounters when attempting to read files from within their war file and the solutions around it.
You can try the below code.
Add this to servelt-context.xml
<context:property-placeholder location="classpath:config.properties"/>
And to access the contents of config file in java,
#Value("${KEY}")
private String value;

Programmatically refresh the spring mvc resource bundle

ResourceBundleMessageSource messages are configured in Spring's configuration file as
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"
p:basenames="WEB-INF/strings/appstrings" />
Whenever I changed any message in that properties file I have to restart server.
I want to read these updated messages programatically in my application without restarting server.
How can I read these messages programatically in one of my #Controller while running application.
There is a ReloadableResourceBundleMessageSource ( http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/context/support/ReloadableResourceBundleMessageSource.html ) in spring that should do what you want.
You can find more info here on stackoverflow:
How to Inject Spring ReloadableResourceBundleMessageSource
How to Inject Spring ReloadableResourceBundleMessageSource
Define your ResourceBundle property in applicationContext.xml file like:
<!-- Message Source for appstrings -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="WEB-INF/strings/appstrings" />
</bean>
In you Java class/controller auto-wire it as:
private ReloadableResourceBundleMessageSource messageSource;
#Autowired
public void setMessageSource(MessageSource messageSource) {
this.messageSource = (ReloadableResourceBundleMessageSource) ((DelegatingMessageSource) messageSource).getParentMessageSource();
}
Then call clearCache() in any function in that class/controller.
messageSource.clearCache();
I got this exception in controller
ReloadableResourceBundleMessageSource incompatible with org.springframework.context.support.DelegatingMessageSource
When you try to run it through messageSource in your controller, you get NOTHING, empty string. And if you look closely, you will find that you have a DelegatingMessageSource in your messageSource property, with an empty parent source, which means it is EMPTY, i.e. always returns blank.
Here’s the solution for this little challenge: move your messageSource definition from spring-servlet.xml to applicationContext.xml!
Read more..

Categories

Resources