Announcement Announcement Module
Collapse
No announcement yet.
HierarchicalMessageSource and ApplicationContext hierarchy Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HierarchicalMessageSource and ApplicationContext hierarchy

    Hi,

    It seems that if you define a MessageSource hierarchy in an application context, that it itself part of a context hierarchy (e.g. servlet/webapp), the parent in your message source gets overridden. This was unexpected!

    It would be more consistent if the application context set the parent on the llast MessageSource in the hierarchy (the one with no parent) so that no message source is lost. (The code that overrides the parent is AbstractApplicationSource.initMessageSource.)

    I've included a detailed explanation below if more details are needed.
    Regards,
    Mat McGowan



    I have a webapp, with an application context defined at the webapp level for the core functionality. I have servlets that provide different types of applications based on this functionality (e.g. demo HTML app, web service etc...).

    For i18n, we have property resource bundles packaged with the application JAR in WEB-INF/lib. But to allow customers easy access to redefine selected messages, I've also used a ReloadableResourceBundleMessageSource that retrieves i18n texts from a subdirectory under WEB-INF, with the parent message source is set to load class resources. All is well and good so far.
    Code:
    <bean id="messageSourceBase" class="org.springframework.context.support.ResourceBundleMessageSource">
            <property name="basename"><value>com.company.app.messages</value></property>
        </bean>
    
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames"><value>/WEB-INF/i18n/coremessages</value></property>
        <property name="parentMessageSource"><ref bean="messageSourceBase"/></property>
        <property name="cacheSeconds"><value>0</value></property>    
    </bean>

    The problem occurs when I try to apply the same technique in the servlet context. The demo servlet follows the same pattern as the webapp. It has its own message strings defined in class resources. And as before, I want to use overriding reloadable bundles under WEB-INF. But doing this doesn't work - none of the strings from the base bundle (the classpath resources) are loaded. (The relodable bundle works fine.)

    I think the problem is because the app context sets the parent messageSource to the parent context's message source, thus overwriting the parent source I set up.

    I can offer a few solutions:
    • - allow configuration of the message source overriding functionality so this can be disabled (in this case, my child contexts don't need the parent contexts resources.)
      - if overriding the parent context, walk the hierarchy of message sources until the end, and setting the parent context on the last message source in the hierarchy. The last message source has no parent, so message source is lost.
      - Create a class DelegateMessageSource, which delegates to another message source before delegating to the parent. The application would configure the DelegateMessageSource, setting the delegate as the head of it's chain of message sources. No parent is set up. This leaves the app context free to set the parent. (IMHO, this is not a good soltion.)

    Here's code implementing the second option. This replaces lines 337-344 in AbstractApplicationContext, method initMessageSource
    Code:
    			if &#40;this.parent != null && this.messageSource instanceof HierarchicalMessageSource&#41; &#123;
    				MessageSource parentMessageSource = getInternalParentMessageSource&#40;&#41;;
                    
                    // find the last one in context
                    HierarchicalMessageSource tail = &#40;HierarchicalMessageSource&#41;this.messageSource;
                    while &#40;tail.getParentMessageSource&#40;&#41;!=null&#41;
                    &#123;
                        if &#40;tail==parentMessageSource&#41;
                        &#123;
                            // parent hierarchy already present in message source
                            tail = null;
                            break;
                        &#125;
                        tail = &#40;HierarchicalMessageSource&#41;tail.getParentMessageSource&#40;&#41;;
                    &#125;
    				if &#40;tail!=null&#41; &#123;                    
    					tail.setParentMessageSource&#40;parentMessageSource&#41;;
    				&#125;
    			&#125;

  • #2
    I think this is a valic concern. The parent messagesource gets overriden automatically if there is a paretn context with a messagesource, so that code can talk directly to the messagesource, instead of having to talk to the context. But it does present the problem in the use case you describe.

    Can I ask you to file a bug report in Jira, with a brief description and a pointer to this forum thread, so this doesn't get lost?

    Comment

    Working...
    X