Announcement Announcement Module
Collapse
No announcement yet.
ResourceBundleMessageSource and file path using environment variable Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ResourceBundleMessageSource and file path using environment variable

    In my configuration below PROPERTIES_FOLDER is a system environment variable and the value is c:\properties.Unfortunately the bean is not able to find the file.

    Am I missing something.



    HTML Code:
    	<bean id="servicesResourceBundle"
    		class="org.springframework.context.support.ResourceBundleMessageSource">
    		<property name="basenames">
    			<list>
    				<value>${PROPERTIES_FOLDER}\business-messages</value>
    			</list>
    		</property>
    	</bean>


    My Old configuration is as below where I search for the message file in classpath and I was good.
    HTML Code:
    <bean id="servicesResourceBundle"
    		class="org.springframework.context.support.ResourceBundleMessageSource">
    		<property name="basenames">
    			<list>
    				<value>business-messages</value>
    			</list>
    		</property>
    	</bean>


    Just curious.The way ResourceBundleMessageSource has been designed it looks like it is a good practise to have business message properties resource file to be in the classpath rather than in a file system.Am I right ?
    Last edited by Vlasik; Jul 27th, 2011, 03:17 PM.

  • #2
    Placeholders in Spring xml files do not work by default. You need to explicitly define a PropertyPlaceholderConfigurer for the ${} structure to be picked up correctly.

    edit: you should also specify file:// before your property since by default files are searched in classpath.

    Comment


    • #3
      Hi Enroco,I offcourse explicityly defined a property place holder configurer for PROPERTIES_FOLDER.

      In short even if I tried this it doesnt work

      HTML Code:
      	<bean id="servicesResourceBundle"
      		class="org.springframework.context.support.ResourceBundleMessageSource">
      		<property name="basenames">
      			<list>
      				<value>file://c:/business/properties/business-messages</value>
      			</list>
      		</property>
      	</bean>
      The error I get is
      ResourceBundle [file://c:/business/properties/business-messages] not found for MessageSource: Can't find resource for bundle file://c:/business/properties/business-messages, key en_US

      Note the physical file that exist in the properties folder is business-messages_en_US.properties





      Originally posted by Enrico Pizzi View Post
      Placeholders in Spring xml files do not work by default. You need to explicitly define a PropertyPlaceholderConfigurer for the ${} structure to be picked up correctly.

      edit: you should also specify file:// before your property since by default files are searched in classpath.

      Comment


      • #4
        I admit I never tried to put resource bundles outside of my application and access them with the file: protocol. I assumed that it should work, as it does for example for the propertyplaceholderconfigurer, but maybe I am wrong...

        In effect, resource bundles are java structures that are meant to be loaded by the classloader, so the fact that they should exist in the classpath sounds, now that I think of it, logical.

        Localization files are part of your application, they are not environment-dependant configuration files, so it is more logical to put them inside your application.

        For example, for the web applications that I created, I had a /I18N folder under web app root, that contained all message bundles for all languages.

        Is there any particular reason why you want to put them externally so badly?

        Comment


        • #5
          >>Localization files are part of your application, they are not environment-dependant configuration files, so it is more logical to put them inside your application.


          Enrico,I agree with you big time.

          It is just that our Architect has come with this requirement and I need to convince him that it is not right.Things that should really go outside the application are environment specific properties like Printer information etc but not things like localization.
          Thanks again...you have given me some more reason to convince my boss.

          thanks again
          Vlaski

          Comment


          • #6
            Hi Enrico,I have changed my mind.What if say some in production environment some wording in locale file has changed ,then why there should be a need to recompile entire source code when it has nothing to java file.
            I guess there is pros and cons in both approach.My architect is insisting on having it loaded via file system rather via classpath.


            Any help will be great.

            Comment


            • #7
              Hi Vlasik,

              Message bundles are static resources. You don't need to recompile, rebuild and redeploy your application when you change something in one or more of this files. Just switch from using ResourceBundleMessageSource to ReloadableResourceBundleMessageSource, so that you can hot-switch or modify the message files with the application running. Modifications will be picked up and used by the application almost instantly, with no need to redeploy.

              Read about ReloadableResourceBundleMessageSource in the docs or just google the word.

              Comment


              • #8
                What seems to the problems here? I'm trying to play around the resource bundle as a standalone app.

                messages_en_US.properties under c:\test\

                Code:
                user.name = user not found!
                ValidationConfig.java to wire the xml file
                Code:
                public class ValidationConfig
                {
                
                	private static final String VALIDATION_CONFIG = "validationConfig.xml";
                
                	private ApplicationContext clContext;
                
                	private static ValidationConfig clInstance;
                
                	private ValidationConfig()
                	{
                		final ApplicationContext appCtx = ServiceRequestApplicationContextProvider
                				.getApplicationContext();
                		/*
                		 * Reason why the appCtx can be null if it was not deployed in the web
                		 * application as a spring managed bean. Thus, this will be treated as
                		 * stan alone context using the ClassPathXmlApplictaionContext
                		 */
                		if (appCtx == null)
                		{
                			clContext = new ClassPathXmlApplicationContext(
                					VALIDATION_CONFIG);
                		}
                		else
                		{
                			clContext = appCtx;
                		}
                	}
                
                	public static ValidationConfig getInstance()
                	{
                		if(clInstance == null)
                		{
                			clInstance = new ValidationConfig();
                		}
                		return clInstance;
                	}
                	
                	public String getMessage(final String messageId)
                	{
                		return clContext.getMessage(messageId, null, Locale.US);
                	}
                validationConfig.xml
                Code:
                <?xml version="1.0" encoding="UTF-8"?>
                <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
                <beans>
                
                
                    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
                		<property name="basenames">
                		  <list>
                			<value>file://test/messages_en_US.properties</value>
                		  </list>
                		</property>
                	</bean>
                
                </beans>
                Test
                Code:
                	public static void main(String[] args)
                	{
                	    final ValidationConfig config = ValidationConfig.getInstance();
                	    
                	    System.out.println("Message " + config.getMessage("user.name"));
                
                	}
                Error I'm getting
                Code:
                INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2083fc73: defining beans [messageSource]; root of factory hierarchy
                Exception in thread "main" org.springframework.context.NoSuchMessageException: No message found under code 'user.name' for locale 'en_US'.
                	at org.springframework.context.support.AbstractMessageSource.getMessage(AbstractMessageSource.java:135)
                	at org.springframework.context.support.AbstractApplicationContext.getMessage(AbstractApplicationContext.java:1210)
                	at com.r2d2.app.validation.config.ValidationConfig.getMessage(ValidationConfig.java:50)
                	at com.r2d2.app.validation.ValidationConfigTest.main(ValidationConfigTest.java:15)

                Comment


                • #9
                  2 different problems here. First of all, if you read the rest of the thread you should have inferred that you cannot put resource bundles outside of your webapp and access them through the file:// protocol. Second thing is you mustn't specify the _en_US.properties extension but just the filename. Change your bean definition to this:

                  Code:
                  <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
                  		<property name="basenames">
                  		  <list>
                  			<value>/I18N/messages</value>
                  		  </list>
                  		</property>
                  	</bean>
                  Then under the root of your web application create a /I18N folder and put your messages_en_US.properties file. That should work.

                  Comment

                  Working...
                  X