Search code examples
javaspring

SPRING - Create MessageSources programmatically and use them as beans


I have to create different messageSources programmatically and put them in a Bean in order to use the correct one when needed.

The application must have a messageSource for each of our Customers, so i created a Configuration class

@Configuration
public class MessageSourceConfig implements BeanFactoryAware {

    private BeanFactory beanFactory;

    @Autowired
    private ICompanyService service;

    private Map<Company, MessageSource> messageSourceMap = new HashMap<Company, MessageSource>();

    // default messageSource
    @Bean
    @Primary
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setCacheSeconds(5);
        messageSource.setDefaultEncoding("UTF-8");

        return messageSource;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;

    }

    @PostConstruct
    public void onPostConstruct() {
        ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;

        Iterable<Company> companies = service.findAll();
        for(Company c : companies) {
             String beanName= c.getSlug()+"_messageSource";
             MessageSource bean = getCompanyMessageSource(c);        
             configurableBeanFactory.registerSingleton(beanName, bean);

             messageSourceMap.put(c, bean);
        }


     }


    private MessageSource getCompanyMessageSource(Company company) {
        ReloadableResourceBundleMessageSource ms = new ReloadableResourceBundleMessageSource();
        ms.setBasename("classpath:" + company.getSlug() + "/messages");
        ms.setUseCodeAsDefaultMessage(true);
        ms.setCacheSeconds(5);
        ms.setDefaultEncoding("UTF-8");

        return ms;
    }


    public MessageSource companyMessageSource(Company company) {
        return messageSourceMap.get(company);
    }

In this way we have a default messageSource and one specific messageSource for each Company. The idea was to put this specific messageSources into a Map and then accessing the correct one from the map when we need it. The problem is that companyMessageSource should be a bean, but i cannot pass a parameter to the bean, how can i access dynamically the correct source?


Solution

  • I am not entirely sure I understand how you want to use the created beans, but one way to get the registered singletons of MessageSource is to get them programmatically something like this:

    @Service
    public class CompanyService {
    
        @Autowired
        private ApplicationContext applicationContext;
    
        public void useCompanySpecificMessageSource(Company c) {
            MessageSource ms = applicationContext.getBean(c.getSlug() + "_messageSource");
            log.debug(ms.getMessage("code", null, new Locale("en", "GB"));
        }
    }
    

    Hope this helps.