Spring Framework provides a mechanism for Spring managed beans to retrieve internationalized messages from the application context using a MessageSource interface.
In our application, a ResourceBundleMessageSource (Spring’s implementation of MessageSource) bean is initialized with a list of base names (using java.util.ResourceBundle convention) of the resource bundles.
For the purpose of organizing these resource bundles on our project, each bean that requires internationalized messages has a corresponding resource bundle of the same name in the same package; for example, the AdministrationService bean has an AdministrationService.properties file. This is just a logical organization of the resource bundles.
It is easy to think in terms of the way ResourceBundle operates:
- retrieve the resource by base name ;
- lookup the message using the key and appropriate locale information.
However, Spring MessageSource provides an easier but different mechanism – given a message key and locale, it performs the lookup by walking through the list of resource bundles provided in the configuration. This becomes immediately obvious when you think about the MessageSource interface methods such as this one:
String getMessage(String code, Object args, String defaultMessage, Locale locale)
So we could also have organized the resource bundles in terms of the purpose of the messages, for example Validation Exception messages, User messages, etc.
The other important mechanism provided by Spring is that during the application context initialization phase, it looks for a bean with a specific name ‘messageSource’ and initializes it. Spring can automatically inject beans that require a message source provided the beans implement the MessageSourceAware interface.
Probably for historical reasons, the Spring beans in our configuration files that require a message source are specifically initialized through the configuration. For example,
<bean id="AdministrationService" parent="BaseService" class="com.someapp.service.impl.AdministrationServiceImpl" p:messageSource-ref="MessageSource" p:administrationDAO-ref="AdministrationDAO" />
There is nothing wrong with this approach until we started to initialize the message source of Spring beans, through their interfaces, after initialization using InitializingBean.afterPropertiesSet() method.
Because InitializingBean.afterPropertiesSet() happens after Spring beans have bean initialized, methods executed on an interface are open to transaction interception and for a given configuration, this operation may result in an IllegalTransactionStateException. To resolve this problem, we needed to introduce awkward tweaks of transaction interception points. It is much better to use the Spring automatic mechanism to side step all these issues all together.
ResourceBundleMessageSource is a HierarchicalMessageSource and provides a parentMessageSource. Therefore, a ResourceBundleMessageSource will attempt to retrieve the requested message in the normal manner and if that fails will lookup the parent message source. This can be useful for default messages that the application will always require or for storing common messages shared by many beans.