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?
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.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With