DiF offers a flexible system to use and customize the presentation layer messages. It also offers a simple way to prepare your applications for internationalization (I18N). This section will show the main message-related features offered by the framework. It will also cover some key concepts behind the message mechanism.
Messages are managed by an entity aptly named message manager. The message manager is defined by this interface. Prior to present the interfaces's features it's useful to discuss some of the Java types associated with messages.
The nuclear message-related object for the message manager is the MessageList. The message list contains represents a view message with the available translations for the message. It's a key object for I18N. It's strongly advised that you check carefully it's interface here.
The message list is a set of Message objects. The Message type offers customization capabilities for the messages. When building a new message the user can supply a default value and a custom value. Upon message fetching the custom message value is returned if it's available (that is, if it was set on message creation). If no custom value exists, the default is returned. There methods to force the default message value fetching and to check if the message is customized. Message objects are immutable. Check this link to learn more on Java immutability.
The message manager will be described here with some more detail. There are three main functional areas on the message manager: the language management, the message management and the repository access. Each of these will be described below.
The message manager implementation offers a RAM-based message cache for the default messages. This cache is always available, even a custom message implementation is supplied.
The message manager offers three methods that concern language management. They support the language addition, and language support operations. Check the JavaDoc links below for more information.
There are several families of message-related methods. There are methods to fetch messages with all the available translations for a given DEM entity, there are methods to fetch messages on a given a language for a given DEM entity and there are methods to update messages.
The message update methods are available in two flavors: for DEM entities and for plain Java classes. They both work the same way apart from this scope-related issue. To change a message the user passes the class or DEM Entity associated to the message, the message ID and a MessageTranslation object with all the translation the message will be available in. Check the methods JavaDoc for more information.
The messages can have two sources: a properties-like file (more on this subject below) and another customizable source, such as a database. The files are the default message source. Different manager implementations can define custom messages sources and as such there must be a way to collect the messages from that source. These means are the collectEntityMessagesFromRepository(Entity,Object) and the collectEntityMessagesFromRepository(Class) methods. As one can see, they are pretty much the same thing, except that one is used for DEM entities and other for classes.
Upon message updating there must be a way to force the cache to reload the messages. To do so there's the invalidateMessages() method.
Until now a lot was said about the inner workings of the message manager but very little about how to define the messages and their translations. Messages are defined on properties-like files. The file must be be named after the entity or class (respecting it's case) they refer to and suffixed with .messages. The file must be located on your application's resources folder. If the message file refers to a class it must be placed inside the messages sub-folder. If the message file refers to a DEM entity it must be placed on a messages sub-folder that mimics the entity's hierarchy (using the IDs and not the class names). An example below will help to better understand the rules.
If the message file name is suffixed with just .messages the default language defined on the framework is assumed. To supply messages in other languages you must add yet another suffix. This will identify the messages file as containing translations for the suffixed language. You are strongly advised to adhere to the ISO 639-1 convention for language identification. It helps to get a cleaner code and provides a common identifier that everyone can understand what it is and to what language it refers.
The following example shows the project message folder structure and features messages files for a class named MyClass, a provider named mockupProvider, an application named mockupApplication, a service named mockupService and a stage named mockupStage (it's implementing class if MockupStage.java). All entities have messages and the stage and the class present portuguese translations for the messages.
myProject | |-- src |-- main |-- resources |-- messages |-- MyClass.messages |-- MyClass.messages.pt |-- MockupProvider.messages |-- mockupProvider |-- MockupApplication.messages |-- mockupApplication |-- MockupService.messages |-- mockupService |-- MockupStage.messages |-- MockupStage.messages.pt
A message file example would be the following:
pageTitle=This is some page title author=Eddie T. Headd aMessage=This is just a message
The default RAM-based implementation ships bundled with DiF. It does not support message customization. To change the messages values one must edit the .mesg files directly. The RAM-based implementation spreads over two classes: AbstractMessageManager and MessageManagerImpl. Check the JavaDoc for a complete overview of this implementation.
At the time of this writing there is just an alternative implementation for the message manager. This implementation is available as a separate framework module and offers a database back-end integration for custom messages. Check the module's own project site} for more information.