Database-driven resource bundle in Spring

依然范特西╮ 提交于 2019-12-18 04:54:18

问题


I have problem to make "database-driven resource bundle" work. In example below TextDAO is properly injected during application start, but when messageSource is accessed, a new Messages object is created - that's the point. How to make this work ?

<!-- message source -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="someapp.bundle.Messages" />
</bean>

Messages.java

@Component
public class Messages extends ListResourceBundle {

    @Autowired
    private TextDAO textDAO;

    public Messages() {
        log.debug("CONSTRUCTOR");
    }

    @Override
    protected Object[][] getContents() {
        // loading messages from DB
        List<Text> texts = textDAO.findAll();  // textDAO is null
        ...
    }
}

RE-OPEN

As Bozho suggest i did my resource bundle as below, but have problem to dynamically reload it. I suppose that ReloadableResourceBundleMessageSource is for properties files, but maybe it is possible to work this, too.

public class DatabaseDrivenMessageSource extends ReloadableResourceBundleMessageSource {

    private Logger log = LoggerFactory.getLogger(getClass());

    private final Map<String, Map<String, String>> properties = new HashMap<String, Map<String, String>>();

    private TextDAO textDAO;

    @Autowired
    public DatabaseDrivenMessageSource(TextDAO textDAO) {
        this.textDAO = textDAO;
        reload();
    }

    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        String msg = getText(code, locale);
        MessageFormat result = createMessageFormat(msg, locale);
        return result;
    }

    @Override
    protected String resolveCodeWithoutArguments(String code, Locale locale) {
        return getText(code, locale);
    }

    private String getText(String code, Locale locale) {
        Map<String, String> localized = properties.get(code);
        String textForCurrentLanguage = null;
        if (localized != null) {
            textForCurrentLanguage = localized.get(locale.getLanguage());
            if (textForCurrentLanguage == null) {
                textForCurrentLanguage = localized.get(Locale.ENGLISH.getLanguage());
            }
        }
        return textForCurrentLanguage != null ? textForCurrentLanguage : code;
    }

    public void reload() {
        properties.clear();
        properties.putAll(loadTexts());
    }

    protected Map<String, Map<String, String>> loadTexts() {
        log.debug("loadTexts");
        Map<String, Map<String, String>> m = new HashMap<String, Map<String, String>>();
        List<Text> texts = textDAO.findAll();
        for(Text text: texts) {
            Map<String, String> v = new HashMap<String, String>();
            v.put("en", text.getEn());
            v.put("de", text.getDe());
            m.put(text.getKey(), v);
        }
        return m;
    }
}

回答1:


basename is a string, so it is not a spring bean, and hence no injection there.

What you can try to do is to subclass ReloadableResourceBundleMessageSource and override some methods there (for example - getMessage(..)). The DAO should be injected in the subclass.




回答2:


ReloadableResourceBundleMessageSource creates an instance of the class named by the basename property. This instance will not have any of its dependencies injected by Spring. That's why the textDAO field in your Messages object is null.

This Spring issue has the source code for an example JDBC backed MessageSource, as an attachment, which you can use instead of ReloadableResourceBundleMessageSource.




回答3:


A bit old, but still relevant... I am using Spring Cloud Config server with JDBC backend as resource bundle for i18n. Zero code. Works awesome!



来源:https://stackoverflow.com/questions/5498998/database-driven-resource-bundle-in-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!