Spring - get all resolvable message keys Spring - get all resolvable message keys spring spring

Spring - get all resolvable message keys


Well, I "solved" my problem by extending ResourceBundleMessageSource.

package org.springframework.context.support;import java.util.Locale;import java.util.ResourceBundle;import java.util.Set;public class ExposedResourceBundleMessageSource extends        ResourceBundleMessageSource {    public Set<String> getKeys(String basename, Locale locale) {        ResourceBundle bundle = getResourceBundle(basename, locale);        return bundle.keySet();    }}

Now I have access to the keys, but I have to do an ugly cast in my controller, in addition to having to specify the message source basename. Ugh, that's a lot of coupling.

Set<String> keys =   ((ExposedResourceBundleMessageSource)  messageSource).getKeys("messages", locale);


I have solve this issue.

public class ExposedResourceBundleMessageSource extends        ResourceBundleMessageSource {    public static final String WHOLE = "whole";    private Set baseNames;    private Map> cachedData = new HashMap>();    public Set getKeys(String baseName, Locale locale) {        ResourceBundle bundle = getResourceBundle(baseName, locale);        return bundle.keySet();    }    public Map getKeyValues(String basename, Locale locale) {        String cacheKey = basename + locale.getCountry();        if (cachedData.containsKey(cacheKey)) {            return cachedData.get(cacheKey);        }        ResourceBundle bundle = getResourceBundle(basename, locale);        TreeMap treeMap = new TreeMap();        for (String key : bundle.keySet()) {            treeMap.put(key, getMessage(key, null, locale));        }        cachedData.put(cacheKey, treeMap);        return treeMap;    }    public Map getKeyValues(Locale locale) {        String cacheKey = WHOLE + locale.getCountry();        if (cachedData.containsKey(cacheKey)) {            return cachedData.get(cacheKey);        }        TreeMap treeMap = new TreeMap();        for (String baseName : baseNames) {            treeMap.putAll(getKeyValues(baseName, locale));        }        cachedData.put(cacheKey, treeMap);        return treeMap;    }    public void setBasenames(String[] basenames) {        baseNames = CollectionUtils.arrayAsSet(basenames);        super.setBasenames(basenames);    }}


My solution:

  1. use spring <util:properties />

    <util:properties id="message" location="classpath:messages.properties" />
  2. Add an interceptor, with 'message' set to request attributes

    request.setAttribute("msgKeys", RequestContextUtils.getWebApplicationContext(request).getBean("message"));
  3. In JSP, use the msgKeys to retrieve message through <fmt:message /> tag

    var msg = {<c:forEach items="${msgKeys}" var="m" varStatus="s">    <c:set var="key" value="${fn:substringBefore(m,'=')}"/>    "${fn:substringAfter(key)}":"<fmt:message key="${key}"/>",</c:forEach>};

(Of course you need to further escape the output to match js string.)

So, for properties

app.name=Application Nameapp.title=Some title

would output

var msg = { "name":"Application Name", "title":"Some title" };

The good thing about that is that you can do some more logic in c:forEach loop.