Features to merge
original list: https://issues.apache.org/jira/browse/DELTASPIKE-119
Part 1
Feature |
Comments |
Objections |
Discussion finished |
---|---|---|---|
Basic API |
|
|
|
Serializable messages |
|
not compatible with type-safe messages |
|
Transferable messages (resolve the final text for a different context (locale,…)) and context-config |
|
|
|
custom message types |
|
|
|
creating messages via builder pattern |
|
|
|
numbered message arguments |
|
|
|
eval existing converter approach for numbered message arguments |
|
|
|
message resolver to support different message-sources |
|
|
|
message interpolator |
|
|
|
locale resolver |
|
|
due to type-safe messages it changed a bit - we have to re-visit it |
type safe messages |
|
|
|
Part 2
This part depends on decissions of part 1.
Feature |
Comments |
Objections |
Discussion finished |
---|---|---|---|
el support (= el interpolation) |
|
|
|
named message arguments |
|
|
|
message payload -> allows to control processing of the message (via custom impl. of different SPIs) – similar to payload in bean-validation |
|
|
|
message context (config) is immutable to avoid side-effects |
|
|
|
clone a message context to use the same config but it’s possible to change it before the new context gets created (and is immutable) |
|
|
|
formatter to allow to format argument-values for the final message text (similar to a converter -> we can think about merging the concepts) |
|
|
|
tooling for devs to generate their own type-safe messages |
|
|
|
messages within a database, or any other possible back end |
|
|
|
inline translated type safe messages |
|
|
|
pluralizer system for message i18n |
|
|
|
static helpers for simple messages |
|
|
|
Part 3
This part depends on the planned integration with other technologies like JSF, BV,...
Feature |
Comments |
Objections |
Discussion finished |
---|---|---|---|
add message to the "current" context |
|
|
|
factories to customize the default behaviour |
|
|
|
allows multi-tenant support |
|
|
|
message targets (ie. a message for a specific component) |
|
|
|
application and client locale |
|
|
|
application and client timezone |
|
|
|
support jsr310 dates |
|
|
|
transaction phase for message, ie. only produce a message when a transaction is committed (usually used in conjunction with observers) |
|
|
|
integrate type safe messages with bean validation |
|
|
|
ability to hook Bean Validation messages into same infrastructure |
needs clarification - reason: ConstraintViolation#getMessage returns a string |
|
|
ability to hook JSF validation messages into same infrastructure |
see "current" context |
|
|
messages surviving multiple http redirects |
|
|
|
Part 4
This part contains features for integrating 3rd party libraries.
Feature |
Comments |
Objections |
Discussion finished |
---|---|---|---|
support joda-time dates |
|
|
|
Agreed API
Basic API
/** * Basic interface for all message-types */ public interface Message extends Localizable, Serializable { /** * @return the message key (or inline-text) of the current message */ String getDescriptor(); /** * @return all named and numbered arguments */ Serializable[] getArguments(); /** * @param arguments 1-n new arguments for the current message * @return the current instance */ Message addArgument(Serializable... arguments); /* * TBD */ String toText(); }
@MessageBundle public interface CustomMessageBundle { @Message("Hello %s") Message sayHello(String cause); } //... @Inject private CustomMessageBundle messages; //... String messageText; messageText = messages.sayHello("DeltaSpike").toText(); //or messageText = messages.sayHello("DeltaSpike").toString(); //or Message message = messages.sayHello("DeltaSpike");
API under discussion - Part 1
Message Interface
/** * Basic interface for all message-types */ public interface Message extends Localizable, Serializable { /** * @return the message key (or inline-text) of the current message */ String getDescriptor(); /** * @return all named and numbered arguments */ Serializable[] getArguments(); /** * @param arguments 1-n new arguments for the current message * @return the current instance */ Message addArgument(Serializable... arguments); //TODO check compatibility with type-safe messages //payload postponed (addPayload, getPayload) }
Localizable
/** * Classes which implement it can provide the message-text based on the given {@link MessageContext} */ public interface Localizable { /** * @param messageContext the current context * @return the text which represents the current instance for the given message context */ String toString(MessageContext messageContext); }
MessageInterpolator
/** * Implementations are responsible to replace placeholders in a message with the final value */ public interface MessageInterpolator extends Serializable { /** * replaces the arguments of the given message with the given arguments * * @param messageContext the current {@link org.apache.myfaces.extensions.cdi.message.api.MessageContext} * instead of a MessageContextAware interface. we need it to avoid expensive operations like locking or deep cloning * @param messageText the message text which has to be interpolated * @param arguments a list of numbered and/or named arguments for the current message * @return the final (interpolated) message text * if it was possible to replace the parameters with the given arguments * the unmodified messageText otherwise */ String interpolate(MessageContext messageContext, String messageText, Serializable... arguments); }
MessageResolver
/** * Implementations have to resolve the text stored for a given key in the message-source they are aware of */ public interface MessageResolver extends Serializable { String MISSING_RESOURCE_MARKER = "???"; /** * @param messageContext the current {@link org.apache.myfaces.extensions.cdi.message.api.MessageContext} * @param messageDescriptor the message key (or in-lined text) of the current message * @param payload //TBD the payload of the message e.g. to use different message sources * @return the final but not interpolated message text */ String getMessage(MessageContext messageContext, String messageDescriptor, /*TBD*/ Map<Class, MessagePayload> payload); }
LocaleResolver
/** * Implementations have to provide the current locale */ public interface LocaleResolver extends Serializable { /** * @return the current locale */ Locale getLocale(); }
MessageContext
/** * Central context for handling messages */ public interface MessageContext extends LocaleResolver, MessageHandler, Serializable { /** * @return message builder to add and/or create a new message based on the current context via a fluent api */ MessageBuilder message(); /** * @return the current config to change it or create a new one base on the current config */ MessageContextConfig config(); /* * TBD: */ /** * @param contextType the type of the custom implementation * @return the instance of the current message context to use the api of the concrete implementation */ <T extends MessageContext> T typed(Class<T> contextType); /* * convenient methods */ /** * @return creates a new context based on the current one */ MessageContext cloneContext(); //the rest will be discussed later }
MessageContextConfig
/** * Config for customizing a {@link MessageContext} */ public interface MessageContextConfig extends Serializable { /** * create a new context based on the default context - the default context won't get modified * * @return a message context builder based on the current config */ MessageContextBuilder use(); /** * change the default context * * @return a message context builder to change the current config */ MessageContextBuilder change(); /** * @return the current message interpolator */ MessageInterpolator getMessageInterpolator(); /** * @return the current message resolver */ MessageResolver getMessageResolver(); /** * @return the current locale resolver */ LocaleResolver getLocaleResolver(); //the rest will be discussed later interface MessageContextBuilder { /** * @param messageInterpolator a new message interpolator * @return the instance of the current message context builder */ MessageContextBuilder messageInterpolator(MessageInterpolator messageInterpolator); /** * @param messageResolver a new message resolver * @return the instance of the current message context builder */ MessageContextBuilder messageResolver(MessageResolver messageResolver); /** * @param localeResolver a new locale resolver * @return the instance of the current message context builder */ MessageContextBuilder localeResolver(LocaleResolver localeResolver); /** * @return a new message context based on the current config */ MessageContext create(); //the rest will be discussed later } }