Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Spring MessageSource Support Multiple Class Path?

Tags:

I am designing a plugin system for our web based application using Spring framework. Plugins are jars on classpath. So I am able to get sources such as jsp, see below

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] pages = resolver.getResources("classpath*:jsp/*jsp");

So far so good. But I have a problem with the messageSource. It seems to me that ReloadableResourceBundleMessageSource#setBasename does NOT support multiple class path via the "classpath*:" If I use just "classpath:", I get the messageSource just only from one plugin.

Does anyone have an idea how to register messageSources from all plugins? Does exist such an implementation of MessageSource?

like image 844
banterCZ Avatar asked Oct 08 '10 08:10

banterCZ


People also ask

What is classpath in Spring XML?

This special prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens via a ClassLoader. getResources(...) call), and then merged to form the final application context definition. So classpath: starts at the root of your classpath.

What is spring boot class path?

It's a path inside your project where you place resources. During the build step, Maven will take files in there and place them in the appropriate place for you to use them in your runtime classpath, eg in an executable . jar , some physical file system location used in the classpath (with java 's -cp option), etc.

What is ResourceBundleMessageSource in spring?

The ResourceBundleMessageSource is the implementation of MessageSource interface which is used for resolving messages. 2. This message source caches both the accessed ResourceBundle instances and the generated MessageFormats for each message.


1 Answers

With the solution of @seralex-vi basenames /WEB-INF/messages did not function.

I overwrited the method refreshProperties on the class ReloadableResourceBundleMessageSource wich perform both type of basenames (classpath*: and /WEB-INF/)

public class SmReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {

private static final String PROPERTIES_SUFFIX = ".properties";

private PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

@Override
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
    if (filename.startsWith(PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
        return refreshClassPathProperties(filename, propHolder);
    } else {
        return super.refreshProperties(filename, propHolder);
    }
}

private PropertiesHolder refreshClassPathProperties(String filename, PropertiesHolder propHolder) {
    Properties properties = new Properties();
    long lastModified = -1;
    try {
      Resource[] resources = resolver.getResources(filename + PROPERTIES_SUFFIX);
      for (Resource resource : resources) {
        String sourcePath = resource.getURI().toString().replace(PROPERTIES_SUFFIX, "");
        PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
        properties.putAll(holder.getProperties());
        if (lastModified < resource.lastModified())
          lastModified = resource.lastModified();
      }
    } catch (IOException ignored) { 
    }
    return new PropertiesHolder(properties, lastModified);
}

On the spring-context.xml you must have the classpath*: prefix

<bean id="messageSource" class="SmReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>/WEB-INF/i18n/enums</value>
            <value>/WEB-INF/i18n/messages</value>
            <value>classpath*:/META-INF/messages-common</value>
            <value>classpath*:/META-INF/enums</value>
        </list>
    </property>
</bean>
like image 61
ajaristi Avatar answered Sep 22 '22 03:09

ajaristi