Reputation: 3228
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?
Upvotes: 1
Views: 1230
Reputation: 66
My goal was to inject the messages I set as default via gist and I solved it this way
You can update it according to your needs.
@Configuration
open class I18nConfig : InitializingBean {
@Bean
open fun messageSource(): ResourceBundleMessageSource {
val source = ResourceBundleMessageSource()
source.setBasename("i18n/messages")
source.setDefaultEncoding(StandardCharsets.UTF_8.name())
source.setCacheMillis(Duration.ofHours(2).toMillis())
source.setFallbackToSystemLocale(false)
source.setUseCodeAsDefaultMessage(true)
return source
}
override fun afterPropertiesSet() {
val files = ClassPathResource("i18n").file.listFiles() ?: return
files.forEach { file ->
val locale = file.nameWithoutExtension.split("_").last()
val properties = loadBaseTranslations(locale)
file?.let {
it.inputStream().use { stream ->
val reader = InputStreamReader(stream, StandardCharsets.UTF_8)
properties.load(reader)
}
}
file?.let { it.outputStream().use { stream -> properties.store(stream, null) } }
} }
private fun loadBaseTranslations(locale: String): Properties {
val url = URI
.create("https://gist.githubusercontent.com/emirhannaneli/.../global-messages:$locale")
.toURL()
val connection = url.openConnection()
connection.connect()
val inputStream = connection.getInputStream()
val reader = InputStreamReader(inputStream, StandardCharsets.UTF_8)
val properties = Properties()
properties.load(reader)
return properties
}
}
Upvotes: 0
Reputation: 2676
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.
Upvotes: 1