Top Description Inners Fields Constructors Methods
org.springframework.context.support

public Class ReloadableResourceBundleMessageSource

extends AbstractResourceBasedMessageSource
implements ResourceLoaderAware
Class Inheritance
All Implemented Interfaces
org.springframework.context.ResourceLoaderAware, org.springframework.beans.factory.Aware
Imports
java.io.IOException, .InputStream, .InputStreamReader, java.text.MessageFormat, java.util.ArrayList, .Collections, .List, .Locale, .Map, .Properties, java.util.concurrent.ConcurrentHashMap, .ConcurrentMap, java.util.concurrent.locks.Lock, .ReentrantLock, org.springframework.context.ResourceLoaderAware, org.springframework.core.io.DefaultResourceLoader, .Resource, .ResourceLoader, org.springframework.lang.Nullable, org.springframework.util.Assert, .CollectionUtils, .DefaultPropertiesPersister, .PropertiesPersister, .StringUtils

Spring-specific org.springframework.context.MessageSource implementation that accesses resource bundles using specified basenames, participating in the Spring org.springframework.context.ApplicationContext's resource loading.

In contrast to the JDK-based ResourceBundleMessageSource, this class uses java.util.Properties instances as its custom data structure for messages, loading them via a org.springframework.util.PropertiesPersister strategy from Spring Resource handles. This strategy is not only capable of reloading files based on timestamp changes, but also of loading properties files with a specific character encoding. It will detect XML property files as well.

Note that the basenames set as "basenames" property are treated in a slightly different fashion than the "basenames" property of ResourceBundleMessageSource. It follows the basic ResourceBundle rule of not specifying file extension or language codes, but can refer to any Spring resource location (instead of being restricted to classpath resources). With a "classpath:" prefix, resources can still be loaded from the classpath, but "cacheSeconds" values other than "-1" (caching forever) might not work reliably in this case.

For a typical web application, message files could be placed in WEB-INF: e.g. a "WEB-INF/messages" basename would find a "WEB-INF/messages.properties", "WEB-INF/messages_en.properties" etc arrangement as well as "WEB-INF/messages.xml", "WEB-INF/messages_en.xml" etc. Note that message definitions in a previous resource bundle will override ones in a later bundle, due to sequential lookup.

This MessageSource can easily be used outside an org.springframework.context.ApplicationContext: it will use a org.springframework.core.io.DefaultResourceLoader as default, simply getting overridden with the ApplicationContext's resource loader if running in a context. It does not have any other specific dependencies.

Thanks to Thomas Achleitner for providing the initial implementation of this message source!

Authors
Juergen Hoeller, Sebastien Deleuze
See Also
setCacheSeconds, setBasenames, setDefaultEncoding, setFileEncodings, setPropertiesPersister, setResourceLoader, org.springframework.core.io.DefaultResourceLoader, ResourceBundleMessageSource, java.util.ResourceBundle

Nested and Inner Type Summary

Modifier and TypeClass and Description
protected class

Field Summary

Modifier and TypeField and Description
private final ConcurrentMap<String, Map<Locale, List<String>>>
private final ConcurrentMap<Locale, ReloadableResourceBundleMessageSource.PropertiesHolder>
private final ConcurrentMap<String, ReloadableResourceBundleMessageSource.PropertiesHolder>
private boolean
private Properties
private List<String>
private PropertiesPersister
private ResourceLoader
private static final String

Constructor Summary

AccessConstructor and Description
public

Method Summary

Modifier and TypeMethod and Description
protected List<String>

Returns:

the List of filenames to check
calculateAllFilenames
(String
the basename of the bundle
basename
,
Locale
the locale
locale
)

Calculate all filenames for the given bundle basename and Locale.

protected List<String>

Returns:

the List of filenames to check
calculateFilenamesForLocale
(String
the basename of the bundle
basename
,
Locale
the locale
locale
)

Calculate the filenames for the given bundle basename and Locale, appending language code, country code, and variant code.

public void
clearCache()

Clear the resource bundle cache.

public void
clearCacheIncludingAncestors()

Clear the resource bundle caches of this MessageSource and all its ancestors.

protected List<ReloadableResourceBundleMessageSource.PropertiesHolder>

Returns:

the list of properties holders
collectPropertiesToMerge
(Locale
the locale
locale
)

Determine the properties to merge based on the specified basenames.

protected ReloadableResourceBundleMessageSource.PropertiesHolder
getMergedProperties(Locale locale)

Get a PropertiesHolder that contains the actually visible properties for a Locale, after merging all specified resource bundles.

protected ReloadableResourceBundleMessageSource.PropertiesHolder

Returns:

the current PropertiesHolder for the bundle
getProperties
(String
the bundle filename (basename + Locale)
filename
)

Get a PropertiesHolder for the given filename, either from the cache or freshly loaded.

protected Properties

Returns:

the populated Properties instance
loadProperties
(Resource
the resource to load from
resource
,
String
the original bundle filename (basename + Locale)
filename
)

Load the properties from the given resource.

protected ReloadableResourceBundleMessageSource.PropertiesHolder

Returns:

a single merged properties holder
mergeProperties
(List<ReloadableResourceBundleMessageSource.PropertiesHolder>
the list of properties holders
holders
)

Merge the given properties holders into a single holder.

protected Properties

Returns:

a plain Properties instance
newProperties
()

Template method for creating a plain new Properties instance.

protected ReloadableResourceBundleMessageSource.PropertiesHolder
refreshProperties(String
the bundle filename (basename + Locale)
filename
,
ReloadableResourceBundleMessageSource.PropertiesHolder
the current PropertiesHolder for the bundle
propHolder
)

Refresh the PropertiesHolder for the given bundle filename.

protected MessageFormat
resolveCode(String
the code of the message to resolve
code
,
Locale
the locale to resolve the code for (subclasses are encouraged to support internationalization)
locale
)

Implements abstract org.springframework.context.support.AbstractMessageSource.resolveCode.

Resolves the given message code as key in the retrieved bundle files, using a cached MessageFormat instance per message code.
protected String
resolveCodeWithoutArguments(String
the code of the message to resolve
code
,
Locale
the locale to resolve the code for (subclasses are encouraged to support internationalization)
locale
)

Overrides org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

Resolves the given message code as key in the retrieved bundle files, returning the value found in the bundle as-is (without MessageFormat parsing).
protected Resource

Returns:

the Resource to use, or null if none found
resolveResource
(String
the bundle filename (basename + Locale)
filename
)

Resolve the specified bundle filename into a concrete Resource, potentially checking multiple sources or file extensions.

public void
setConcurrentRefresh(boolean concurrentRefresh)

Specify whether to allow for concurrent refresh behavior, i.e. one thread locked in a refresh attempt for a specific cached properties file whereas other threads keep returning the old properties for the time being, until the refresh attempt has completed.

public void
setFileEncodings(Properties
a Properties with filenames as keys and charset names as values. Filenames have to match the basename syntax, with optional locale-specific components: e.g. "WEB-INF/messages" or "WEB-INF/messages_en".
fileEncodings
)

Set per-file charsets to use for parsing properties files.

public void
setFileExtensions(List<String>
the file extensions (starts with a dot)
fileExtensions
)

Set the list of supported file extensions.

public void
setPropertiesPersister(PropertiesPersister propertiesPersister)

Set the PropertiesPersister to use for parsing properties files.

public void
setResourceLoader(ResourceLoader
the ResourceLoader object to be used by this object
resourceLoader
)

Implements org.springframework.context.ResourceLoaderAware.setResourceLoader.

Set the ResourceLoader to use for loading bundle properties files.
public String
toString()

Overrides java.lang.Object.toString.

Returns a string representation of the object.
Inherited from org.springframework.context.support.AbstractResourceBasedMessageSource:
addBasenamesgetBasenameSetgetCacheMillisgetDefaultEncodinggetDefaultLocaleisFallbackToSystemLocalesetBasenamesetBasenamessetCacheMillissetCacheSecondssetDefaultEncodingsetDefaultLocalesetFallbackToSystemLocale

Field Detail

cachedFilenamesback to summary
private final ConcurrentMap<String, Map<Locale, List<String>>> cachedFilenames
cachedMergedPropertiesback to summary
private final ConcurrentMap<Locale, ReloadableResourceBundleMessageSource.PropertiesHolder> cachedMergedProperties
cachedPropertiesback to summary
private final ConcurrentMap<String, ReloadableResourceBundleMessageSource.PropertiesHolder> cachedProperties
concurrentRefreshback to summary
private boolean concurrentRefresh
fileEncodingsback to summary
private Properties fileEncodings
Annotations
@Nullable
fileExtensionsback to summary
private List<String> fileExtensions
propertiesPersisterback to summary
private PropertiesPersister propertiesPersister
resourceLoaderback to summary
private ResourceLoader resourceLoader
XML_EXTENSIONback to summary
private static final String XML_EXTENSION

Constructor Detail

ReloadableResourceBundleMessageSourceback to summary
public ReloadableResourceBundleMessageSource()

Method Detail

calculateAllFilenamesback to summary
protected List<String> calculateAllFilenames(String basename, Locale locale)

Calculate all filenames for the given bundle basename and Locale. Will calculate filenames for the given Locale, the system Locale (if applicable), and the default file.

Parameters
basename:String

the basename of the bundle

locale:Locale

the locale

Returns:List<String>

the List of filenames to check

See Also
setFallbackToSystemLocale, calculateFilenamesForLocale
calculateFilenamesForLocaleback to summary
protected List<String> calculateFilenamesForLocale(String basename, Locale locale)

Calculate the filenames for the given bundle basename and Locale, appending language code, country code, and variant code.

For example, basename "messages", Locale "de_AT_oo" → "messages_de_AT_OO", "messages_de_AT", "messages_de".

Follows the rules defined by java.util.Locale#toString().

Parameters
basename:String

the basename of the bundle

locale:Locale

the locale

Returns:List<String>

the List of filenames to check

clearCacheback to summary
public void clearCache()

Clear the resource bundle cache. Subsequent resolve calls will lead to reloading of the properties files.

clearCacheIncludingAncestorsback to summary
public void clearCacheIncludingAncestors()

Clear the resource bundle caches of this MessageSource and all its ancestors.

See Also
clearCache
collectPropertiesToMergeback to summary
protected List<ReloadableResourceBundleMessageSource.PropertiesHolder> collectPropertiesToMerge(Locale locale)

Determine the properties to merge based on the specified basenames.

Parameters
locale:Locale

the locale

Returns:List<ReloadableResourceBundleMessageSource.PropertiesHolder>

the list of properties holders

Since
6.1.4
See Also
getBasenameSet(), calculateAllFilenames, mergeProperties
getMergedPropertiesback to summary
protected ReloadableResourceBundleMessageSource.PropertiesHolder getMergedProperties(Locale locale)

Get a PropertiesHolder that contains the actually visible properties for a Locale, after merging all specified resource bundles. Either fetches the holder from the cache or freshly loads it.

Only used when caching resource bundle contents forever, i.e. with cacheSeconds < 0. Therefore, merged properties are always cached forever.

See Also
collectPropertiesToMerge, mergeProperties
getPropertiesback to summary
protected ReloadableResourceBundleMessageSource.PropertiesHolder getProperties(String filename)

Get a PropertiesHolder for the given filename, either from the cache or freshly loaded.

Parameters
filename:String

the bundle filename (basename + Locale)

Returns:ReloadableResourceBundleMessageSource.PropertiesHolder

the current PropertiesHolder for the bundle

loadPropertiesback to summary
protected Properties loadProperties(Resource resource, String filename) throws IOException

Load the properties from the given resource.

Parameters
resource:Resource

the resource to load from

filename:String

the original bundle filename (basename + Locale)

Returns:Properties

the populated Properties instance

Exceptions
IOException:
if properties loading failed
mergePropertiesback to summary
protected ReloadableResourceBundleMessageSource.PropertiesHolder mergeProperties(List<ReloadableResourceBundleMessageSource.PropertiesHolder> holders)

Merge the given properties holders into a single holder.

Parameters
holders:List<ReloadableResourceBundleMessageSource.PropertiesHolder>

the list of properties holders

Returns:ReloadableResourceBundleMessageSource.PropertiesHolder

a single merged properties holder

Since
6.1.4
See Also
newProperties(), getMergedProperties, collectPropertiesToMerge
newPropertiesback to summary
protected Properties newProperties()

Template method for creating a plain new Properties instance. The default implementation simply calls Properties#Properties().

Allows for returning a custom Properties extension in subclasses. Overriding methods should just instantiate a custom Properties subclass, with no further initialization or population to be performed at that point.

Returns:Properties

a plain Properties instance

Since
4.2
refreshPropertiesback to summary
protected ReloadableResourceBundleMessageSource.PropertiesHolder refreshProperties(String filename, ReloadableResourceBundleMessageSource.PropertiesHolder propHolder)

Refresh the PropertiesHolder for the given bundle filename.

The holder can be null if not cached before, or a timed-out cache entry (potentially getting re-validated against the current last-modified timestamp).

Parameters
filename:String

the bundle filename (basename + Locale)

propHolder:ReloadableResourceBundleMessageSource.PropertiesHolder

the current PropertiesHolder for the bundle

See Also
resolveResource(String)
resolveCodeback to summary
protected MessageFormat resolveCode(String code, Locale locale)

Implements abstract org.springframework.context.support.AbstractMessageSource.resolveCode.

Resolves the given message code as key in the retrieved bundle files, using a cached MessageFormat instance per message code.

Parameters
code:String

Doc from org.springframework.context.support.AbstractMessageSource.resolveCode.

the code of the message to resolve

locale:Locale

Doc from org.springframework.context.support.AbstractMessageSource.resolveCode.

the locale to resolve the code for (subclasses are encouraged to support internationalization)

Returns:MessageFormat

Doc from org.springframework.context.support.AbstractMessageSource.resolveCode.

the MessageFormat for the message, or null if not found

Annotations
@Override
@Nullable
resolveCodeWithoutArgumentsback to summary
protected String resolveCodeWithoutArguments(String code, Locale locale)

Overrides org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

Resolves the given message code as key in the retrieved bundle files, returning the value found in the bundle as-is (without MessageFormat parsing).

Parameters
code:String

Doc from org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

the code of the message to resolve

locale:Locale

Doc from org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

the locale to resolve the code for (subclasses are encouraged to support internationalization)

Returns:String

Doc from org.springframework.context.support.AbstractMessageSource.resolveCodeWithoutArguments.

the message String, or null if not found

Annotations
@Override
resolveResourceback to summary
protected Resource resolveResource(String filename)

Resolve the specified bundle filename into a concrete Resource, potentially checking multiple sources or file extensions.

If no suitable concrete Resource can be resolved, this method returns a Resource for which Resource#exists() returns false, which gets subsequently ignored.

This can be leveraged to check the last modification timestamp or to load properties from alternative sources — for example, from an XML BLOB in a database, or from properties serialized using a custom format such as JSON.

The default implementation delegates to the configured ResourceLoader to resolve resources, checking in order for existing Resource with extensions defined by setFileExtensions(List) (.properties and .xml by default).

When overriding this method, loadProperties(Resource, String) must be capable of loading properties from any type of Resource returned by this method. As a consequence, implementors are strongly encouraged to also override loadProperties().

As an alternative to overriding this method, you can configure a PropertiesPersister that is capable of dealing with all resources returned by this method. Please note, however, that the default loadProperties() implementation uses loadFromXml for XML resources and otherwise uses the two load methods for other types of resources.

Parameters
filename:String

the bundle filename (basename + Locale)

Returns:Resource

the Resource to use, or null if none found

Annotations
@Nullable
Since
6.1
setConcurrentRefreshback to summary
public void setConcurrentRefresh(boolean concurrentRefresh)

Specify whether to allow for concurrent refresh behavior, i.e. one thread locked in a refresh attempt for a specific cached properties file whereas other threads keep returning the old properties for the time being, until the refresh attempt has completed.

Default is "true": this behavior is new as of Spring Framework 4.1, minimizing contention between threads. If you prefer the old behavior, i.e. to fully block on refresh, switch this flag to "false".

Since
4.1
See Also
setCacheSeconds
setFileEncodingsback to summary
public void setFileEncodings(Properties fileEncodings)

Set per-file charsets to use for parsing properties files.

Only applies to classic properties files, not to XML files.

Parameters
fileEncodings:Properties

a Properties with filenames as keys and charset names as values. Filenames have to match the basename syntax, with optional locale-specific components: e.g. "WEB-INF/messages" or "WEB-INF/messages_en".

See Also
setBasenames, org.springframework.util.PropertiesPersister#load
setFileExtensionsback to summary
public void setFileExtensions(List<String> fileExtensions)

Set the list of supported file extensions.

The default is a list containing .properties and .xml.

Parameters
fileExtensions:List<String>

the file extensions (starts with a dot)

Since
6.1
setPropertiesPersisterback to summary
public void setPropertiesPersister(PropertiesPersister propertiesPersister)

Set the PropertiesPersister to use for parsing properties files.

The default is DefaultPropertiesPersister.

See Also
DefaultPropertiesPersister#INSTANCE
setResourceLoaderback to summary
public void setResourceLoader(ResourceLoader resourceLoader)

Implements org.springframework.context.ResourceLoaderAware.setResourceLoader.

Set the ResourceLoader to use for loading bundle properties files.

The default is a DefaultResourceLoader. Will get overridden by the ApplicationContext if running in a context, as it implements the ResourceLoaderAware interface. Can be manually overridden when running outside an ApplicationContext.

Parameters
resourceLoader:ResourceLoader

Doc from org.springframework.context.ResourceLoaderAware.setResourceLoader.

the ResourceLoader object to be used by this object

Annotations
@Override
See Also
org.springframework.core.io.DefaultResourceLoader, org.springframework.context.ResourceLoaderAware
toStringback to summary
public String toString()

Overrides java.lang.Object.toString.

Doc from java.lang.Object.toString.

Returns a string representation of the object.

Returns:String

a string representation of the object.

Annotations
@Override
org.springframework.context.support back to summary

protected Class ReloadableResourceBundleMessageSource.PropertiesHolder

extends Object
Class Inheritance
  • java.lang.Object
  • org.springframework.context.support.ReloadableResourceBundleMessageSource.PropertiesHolder

PropertiesHolder for caching. Stores the last-modified timestamp of the source file for efficient change detection, and the timestamp of the last refresh attempt (updated every time the cache entry gets re-validated).

Field Summary

Modifier and TypeField and Description
private final ConcurrentMap<String, Map<Locale, MessageFormat>>
cachedMessageFormats

Cache to hold already generated MessageFormats per message code.

private final long
private final Properties
private final Lock
private volatile long

Constructor Summary

AccessConstructor and Description
public
public
PropertiesHolder(Properties properties, long fileTimestamp)

Method Summary

Modifier and TypeMethod and Description
public long
public MessageFormat
public Properties
public String
public long
public void
setRefreshTimestamp(long refreshTimestamp)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

cachedMessageFormatsback to summary
private final ConcurrentMap<String, Map<Locale, MessageFormat>> cachedMessageFormats

Cache to hold already generated MessageFormats per message code.

fileTimestampback to summary
private final long fileTimestamp
propertiesback to summary
private final Properties properties
Annotations
@Nullable
refreshLockback to summary
private final Lock refreshLock
refreshTimestampback to summary
private volatile long refreshTimestamp

Constructor Detail

PropertiesHolderback to summary
public PropertiesHolder()
PropertiesHolderback to summary
public PropertiesHolder(Properties properties, long fileTimestamp)

Method Detail

getFileTimestampback to summary
public long getFileTimestamp()
getMessageFormatback to summary
public MessageFormat getMessageFormat(String code, Locale locale)
Annotations
@Nullable
getPropertiesback to summary
public Properties getProperties()
Annotations
@Nullable
getPropertyback to summary
public String getProperty(String code)
Annotations
@Nullable
getRefreshTimestampback to summary
public long getRefreshTimestamp()
setRefreshTimestampback to summary
public void setRefreshTimestamp(long refreshTimestamp)