Question

I'm trying to use a reloadable spring resource bundle but spring cannot find the file. I've tried tons of different paths, but can't get it to work anywhere. In the code below you'll see that i load both the spring bundle and the regular one from the same path variable but only one works.

I've been banging my head against this for far too long. Anybody have any ideas?

logfile


INFO  2010-04-28 11:38:31,805 [main] org.myorg.test.TestMessages: C:\www\htdocs\messages.properties
INFO  2010-04-28 11:38:31,805 [main] org.myorg.data.Messages: initializing Spring Message Source to C:\www\htdocs\messages.properties
INFO  2010-04-28 11:38:31,821 [main] org.myorg.data.Messages: Attempting to load properties from C:\www\htdocs\messages.properties
DEBUG 2010-04-28 11:38:31,836 [main] org.springframework.context.support.ReloadableResourceBundleMessageSource: No properties file found for [C:\www\htdocs\messages.properties_en_US] - neither plain properties nor XML
DEBUG 2010-04-28 11:38:31,842 [main] org.springframework.context.support.ReloadableResourceBundleMessageSource: No properties file found for [C:\www\htdocs\messages.properties_en] - neither plain properties nor XML
DEBUG 2010-04-28 11:38:31,848 [main] org.springframework.context.support.ReloadableResourceBundleMessageSource: No properties file found for [C:\www\htdocs\messages.properties] - neither plain properties nor XML
INFO  2010-04-28 11:38:31,848 [main] org.myorg.test.TestMessages: I am C:\www\htdocs\messages.properties

Messages.java


package org.myorg.data;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;

public class Messages {
    protected static final Log logger = LogFactory.getLog(Messages.class);
    private static ReloadableResourceBundleMessageSource msgSource = null;
    private static ResourceBundle RESOURCE_BUNDLE;

    public static final String PATH = "C:" + File.separator + "www" 
            + File.separator + "htdocs" + File.separator + "messages.properties";

    private Messages() {

    }

    public static String getString(String key) {
        initBundle();

        return msgSource.getMessage(key, null, 
                    RESOURCE_BUNDLE.getString(key), null); 
    }

    private static void initBundle(){
        if(null == msgSource || null == RESOURCE_BUNDLE){
            logger.info("initializing Spring Message Source to " + PATH);
            msgSource = new ReloadableResourceBundleMessageSource();
            msgSource.setBasename(PATH);
            msgSource.setCacheSeconds(1);

            FileInputStream fis = null;
            try {
                logger.info("Attempting to load properties from " + PATH);
                fis = new FileInputStream(PATH);
                RESOURCE_BUNDLE = new PropertyResourceBundle(fis);
            } catch (Exception e) {
                logger.info("couldn't find " + PATH);
            } finally {
                try {
                    if(null != fis)
                        fis.close();
                } catch (IOException e) {

                }
            }
        }
    }
}

TestMessages.java


package org.myorg.test;

import org.myorg.data.Messages;

public class TestMessages extends AbstractTest {
        public void testMessage(){
            logger.info(Messages.PATH);
            logger.info(Messages.getString("OpenKey.TEST"));
        }
}

Was it helpful?

Solution

Just for the record you may try this approach:

  1. declare the reloadableResourceBundle bean with basename='messages' .properties extension is assumed and not required
  2. inject this as reference into your bean
  3. create messages.properties file and place your stuff in it
  4. copy messages.properties into yourProject/web/messages.properties
  5. lay back and enjoy

Explanation: Spring reloadable message bundle doesn't use class path as it get's cached by app servers. You may circumvent this by classpath:your.properies but then again you may as well use the non reloadable version which is a few ticks faster. In other words the trick is to use the webApp directory which doesn't get cached. You may place your files under yourProject/web or anywhere below as long as you let the loader know.

place this in webapp-config.xml

<bean id="messageSource"  class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="message"/>
    <property name="cacheSeconds" value="1"/>
</bean>

and this is your bean:

public class YouBeanWithMsgReloadableResourceBundle {
    public void yourMethod(){
    String msg = ms.getMessage("your.memo.nic", null, "your default message", Locale.CANADA);
}

@Autowired MessageSource ms;}

And since JSF2 is really cool stuff you may want to use this in a faces context then:

public void validate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException {
MessageSource ms = FacesContextUtils.getWebApplicationContext(context).getBean(MessageSource.class);
String msg = ms.getMessage("your.memo.nic", null, "your default message", Locale.CANADA);
}

OTHER TIPS

You can specify the properties file(s) be outside of the archive by configuring in the application context file like so:

<bean id="messageSource"
      class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="defaultEncoding" value="UTF-8"/>
    <property name="basenames">
        <list>
            <value>file:/whatever_your_file_path_is/messages/admin_i18n</value>
            <value>file:/whatever_your_file_path_is/messages/customer_i18n</value>
        </list>
    </property>
</bean>

With ReloadableResourceBundleMessageSource you have to move the message files out of the classpath if you want them to actually be reloadable. If you don't care for the reloadable feature you can put them in the classpath and use the classpath: prefix.

<bean id="messageSource"
      class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="defaultEncoding" value="UTF-8"/>
    <property name="basenames">
        <list>
            <value>classpath:messages/admin_i18n</value>
            <value>classpath:messages/customer_i18n</value>
        </list>
    </property>
</bean>

I just switch to ReloadableResourceBundleMessageSource. This is working for me.

rather than reading from a file, you should probably read from the classpath using

Messages.class.getResourceAsStream("/path/from/classpathroot/messages.properties")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top