Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Table of Contents

Table of Contents
indent10px
styledisc
printablefalse

MessageContext

The MessageContext allows using a fluent API for

  • Creating messages
  • Creating message text
  • Processing messages
  • Changing the configuration of the current context
  • Using the current context as template for a new context

Furthermore, the context provides the current locale.

...

The default implementation provides

  • Descriptor (Key or inline-message)
  • Arguments
    • Numbered arguments
    • Named arguments
  • Payload

The Message interface extends Localizable . Therefore it's possible to use a MessageContext to create the final message text based on the message and the current configuration of the MessageContext .

...

... creates a message with the key 'msgKey' as message descriptor.
(The concrete syntax of a key depends on the used MessageResolver. Further details are available in the DevDoc.)

Example 3

Code Block
titleCreating messages with arguments
borderStylesolid
Message message = messageContext.message().text("Hello {0}").argument("MyFaces").create();

...

Code Block
titleCreating messages with payload
borderStylesolid
Message message = messageContext.message().text("Hello CODI").payload(MessageSeverity.Error.classERROR).create();

... creates a message with 'Hello CODI' as message descriptor and error as message-severity.
Payload is based on similar to the validation payload of Bean-Validation. Via payload it's possible to provide additional information via a typesafe mechanism. It's possible to use the provided types of payload ( MessageSeverity or InternalMessage ) or to create custom payload like Label or to create something like serializable attatchments. It's possible to handle messages depending on the payload of the message. By default a message is created with MessageSeverity.InfoINFO .

Creating message text

Example 1

...

... creates the message-text based on the constructed message.

To avoid side-effects with other libs as well as IDEs there is no #toString().

Example 2

Code Block
titleCreating the message-text of a given message
borderStylesolid
//Message message = messageContext.message().text("Hello {name}").namedArgument("name", "MyFaces").create();
String messageText = message.toString(messageContext);

... creates the message-text based on the given message and MessageContext message and MessageContext . That's essential if you would like to create the final text with a different/new MessageContext e.g. with a different configuration or with the current MessageContext if you receive a de-serialized message instance.

Processing messages

It's possible to register MessageHandler s which process or forward messages added to the MessageContext .

...

Code Block
titleImplementation of a custom message-builder
borderStylesolid
public class CustomMessageBuilder extends SimpleMessageBuilder
{
    private CustomMessageBuilder ()
    {
    }

    public static MessageBuilder message()
    {
        return new CustomMessageBuilder();
    }

    public static MessageBuilder technicalMessage()
    {
        return new CustomMessageBuilder().payload(TechnicalMessage.classPAYLOAD);
    }

    public static MessageBuilder label()
    {
        return new CustomMessageBuilder().payload(Label.classPAYLOAD);
    }
}

A custom MessageResolver has to know how to handle the different message types. If a payload type just allows one possible value (as marker), we can use the class of the payload to check if the payload-map contains such a marker entry.

Code Block
titleHandling different message types
borderStylesolid
public class TestMessageResolver implements MessageResolver
{
    public String getMessage(String key, Locale locale, Map<Class, Class<? extends MessagePayload>>MessagePayload> messagePayload)
    {
        if (!isKey(key))
        {
            return key;
        }

        try
        {
            key = extractKey(key);

            if(messagePayload.containsKey(Label.class))
            {
                return ResourceBundle.getBundle(TEST_LABELS, locale, getClassLoader()).getString(key);
            }
            else if(messagePayload.containsKey(TechnicalMessage.class))
            {
                return ResourceBundle.getBundle(TEST_TECHNICAL_MESSAGES, locale, getClassLoader()).getString(key);
            }
            return ResourceBundle.getBundle(TEST_MESSAGES, locale, getClassLoader()).getString(key);
        }
        catch (MissingResourceException e)
        {
            return key;
        }
    }
    //The full example is available in the code-base (see: TestMessageResolver)
}

...

Code Block
titleBusiness client specific messages
borderStylesolid
    @Produces
    @RequestScoped
    @ClientQualifier
    public MessageContext createClientAwareContext(@Jsf MessageContext messageContext,
                                                   Client client)
    {
        MessageResolver clientAwareMessageResolver = createMessageResolverForClient(client.getId());

        return messageContext.config().use().messageResolver(clientAwareMessageResolver).create();
    }

    private MessageResolver createMessageResolverForClient(final String currentClientId)
    {
        return new MessageResolver()
        {
            public String getMessage(String messageDescriptor,
                                     Locale locale,
                                     Map<Class, Class<? extends MessagePayload>>MessagePayload> messagePayload)
            {
                FacesContext facesContext = FacesContext.getCurrentInstance();

                try
                {
                    return facesContext.getApplication()
                            .getResourceBundle(facesContext, currentClientId).getString(messageDescriptor);
                }
                catch (MissingResourceException e)
                {
                    return "???" + messageDescriptor + "???";
                }
            }
        };
    }

...