|
From: Tony F. <ton...@ya...> - 2003-03-16 22:38:00
|
I have just integrated a lot of changes to accomplish 2 main goals:
1) To resolve messages from a MessageSource (ResourceBundle) using a "code"+locale
as the key that message.
2) To allow messages being resolved to take arguments in and have them be substituted
in the message returned.
I'll start with the high level description of what I've done. First, I changed the
MessageSource interface to have the following API:
String getMessage(MessageSourceResolvable resolvable) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
String getMessage(String code, Locale locale, Object args[]) throws NoSuchMessageException;
String getMessage(String code, Locale locale, Object args[], String defaultMessage);
You'll notice 2 new overloads that take in a "MessageSourceResolvable". This is a new
interface I've introduced and it has this API:
public Object getControlledBy();
public String getDefaultMessage();
public Object[] getErrorArgs();
public String getErrorCode();
public Locale getLocale();
Basically, the thought is anyone that wishes to have something resolve it's messages from a MessageSource
need only implement this interface and the MessageSource will know how to return the message.
Notice that there are no setters on this interface - thus from the point of view of
a method receiving a MessageSourceResolvable object it is immutable.
Generally anyone implementing this interface will provide appropriate constructors taking in similar arguments.
The "MessageSourceResolvableImpl" class is a default implementation of this interface with the
appropriate constructors and a good toString() method for showing the internal state.
Also notice the "getMessage(MessageSourceResolvable resolvable, Locale locale)" overload.
Since a MessageSourceResolvable is immutable it's values will generally be set only during
it's construction. It is quite possible that the MessageSourceResolvable might be
created during one HTTPRequest. The message to be displayed to the user might not occur
until another HTTPRequest arrives. Since the Spring Framework accommodates being able to
change the Locale on a HTTPRequest level, you need the ability to pass in a locale to the
getMessage(...) method. This version of the method will use the locale arg passed in rather
than any locale attribute value that may have already been stored on the immutable MessageSourceResolvable.
for message resolution.
Also, a convience class named com.interface21.util.ObjectArrayUtils was introduced. This is
a static helper class that aids you in converting scalars into Object arrays. Perhaps useful
in the creation of the "Object[] args" parameter.
For those interested in knowing the details of all classes included in this change, read on.
----------------------------------------------------
NEW
-------------------
MessageSourceResolvable - new
New interface that contains these methods:
public Object getControlledBy();
public String getDefaultMessage();
public Object[] getErrorArgs();
public String getErrorCode();
public Locale getLocale();
Thought is this interface will be implemented by anyone that wishes to be able to
resolve their message from a messageSource. Example of a few of the classes
using this interface are "ObjectError" and "FieldError" (subclass of ObjectError).
MessageSourceResolvableImpl - new
A default implementation of the new MessageSourceResolvable interface. The
"ObjectError" class subclasses from this.
ParameterizableErrorCodedPropertyVetoException - new
Subclassed ErrorCodedPropertyVetoException and added ability to also take in args.
ParameterizableErrorCoded - new
New sub-interface to ErrorCoded that contains a single method:
Object[] getErrorArgs();
ObjectArrayUtils - new
From a suggestion from Rod.
Contains static APIs like:
public static Object[] toArray(boolean arg1, boolean arg2, boolean arg3) {
Here is part of the JavaDocs:
* Miscellaneous utility methods for creating an object array from
* a bunch of primative args. This utility class is especially
* useful for classes implementing the ParameterizableErrorCoded interface.
* Since there are so many combinations of primitives that can be passed in
* to create an Object array from there are the following limitations.
* CURRENT LIMITATIONS:
* 1) Only implements overload for up to 9 args of SAME PRIMITIVE TYPE.
* 2) Implements a helper overload for creating an array from up to 9 args
* of type object (not a big help, but it saves user from doing "new Object[] {...}"
* and it's consistent.
* 3) Only implements overload for up to 5 args of all combinations
* SAME PRIMITIVE TYPE + any Objects sprinkled in between that primitive type
* (as it's assumed this will be a frequently used combo).
ResourceBundleMessageSourceTestSuite - new
StaticMessageSourceTestSuite - new
test\com\interface21\web\context\WEB-INF\context-messages.properties - deleted
Replaced with specific file for the locales.
test\com\interface21\web\context\WEB-INF\context-messages_en_GB.properties - new
test\com\interface21\web\context\WEB-INF\context-messages_en_US.properties - new
(and moved entry from "context-messages.properties" into here)
CHANGED
-------------------
ErrorCodedPropertyVetoException - chg
More explicit JavaDocs. Added overload to constructor so could subclass
with a certain constructor.
MessageSource - chg
This interface now has 4 overloads (as opposed to 2). Two of the overloads take in
a new arg "MessageSourceResolvable" (a new interface I introduced).
String getMessage(MessageSourceResolvable resolvable) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
String getMessage(String code, Locale locale, Object args[]) throws NoSuchMessageException;
String getMessage(String code, Locale locale, Object args[], String defaultMessage);
NoSuchMessageException - chg
now has a (code, locale) constructor as well as the old (code) constructor
AbstractApplicationContext - chg
made the getMessage(...) methods conform to the new MessageSource interface.
**AbstractMsgSourceResolver
AbstractNestingMessageSource - chg
Ultimately, the core of what I've changed. The API for all the getMessage(...)
methods conforms to the MessageSource interface. I've also taken code from
Struts for how they resolve messages from ResourceBundles and added functionality
to do argument replacement.
MessageSourceResourceBundle - chg
Changed param name of "key" to "code" (conforms with rest of errorCode stuff). Also
had to change call made internally to getMessage(...) method since API changed.
StaticApplicationContext - chg
Changed API of one method from:
public String addMessage(String code, String message) {
to:
public void addMessage(String code, Locale locale, String defaultMessage) {
StaticMessageSource - chg
Changed API of one method from:
public String addMessage(String code, String message) {
to:
public void addMessage(String code, Locale locale, String defaultMessage) {
BindException - chg
Changed method APIs to conform to/emulate new MessageSource API args.
DataBinder - chg
Changed method APIs to conform to/emulate new MessageSource API args.
Errors - chg
Changed method APIs to conform to/emulate new MessageSource API args.
FieldError - chg
Added a bunch of constructor overloads to conform to/emulate new MessageSource
API args.
Changed the toString() method to return more about internal state.
ObjectError - chg
Reparented it to MessageSourceResolvableImpl (thus implements MessageSourceResolvable int).
Added a bunch of constructor overloads to conform to/emulate new MessageSource
API args.
Changed the toString() method to return more about internal state.
EscapedErrors - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
RequestContext - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
RequestContextUtils - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
BindTag - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
MessageTag - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
TagInWebApplicationContext - chg
Changed the orig 2 resolveMessage(...) APIs to now be 4 methods with the same signatures
that are on the MessageSource int only named with resolveMessage:
String resolveMessage(MessageSourceResolvable resolvable) throws NoSuchMessageException;
String resolveMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
String resolveMessage(String code, Locale locale, Object args[]) throws NoSuchMessageException;
String resolveMessage(String code, Locale locale, Object args[], String defaultMessage);
AbstractApplicationContextTests - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
StaticApplicationContextTestSuite - chg
Changed internal method calls to conform to/emulate new MessageSource API args.
|