Firs read how the workflow about conversion and validation errors works;
Then read Type Conversion Error Handling from the official documentation (bolds are mine):
Type conversion error handling provides a simple way to distinguish
between an input validation problem and an input type conversion
problem.
Any error that occurs during type conversion may or may not wish to be
reported. For example, reporting that the input "abc" could not be
converted to a number might be important. On the other hand, reporting
that an empty string, "", cannot be converted to a number might not be
important - especially in a web environment where it is hard to
distinguish between a user not entering a value vs. entering a blank
value.
By default, all conversion errors are reported using the generic i18n
key xwork.default.invalid.fieldvalue
, which you can override (the
default text is Invalid field value for field "xxx", where xxx is the
field name) in your global i18n resource bundle.
However, sometimes you may wish to override this message on a
per-field basis. You can do this by adding an i18n key associated with
just your action (Action.properties) using the pattern
invalid.fieldvalue.xxx
, where xxx
is the field name.
It is important to know that none of these errors are actually
reported directly. Rather, they are added to a map called
conversionErrors in the ActionContext. There are several ways this map
can then be accessed and the errors can be reported accordingly.
There are two ways the error reporting can occur:
By default, the conversion interceptor is included in
struts-default.xml in the default stack. To keep conversion
errors from reporting globally, change the interceptor stack, and add
additional validation rules.
Then what is happening in your case ?
You are using a default stack (or a custom stack with the same behaviour), that is running the ConversionErrors Interceptor before the Validation Interceptor.
Then, since you are defining a ConversionErrorFieldValidator
, you are using both the mechanisms, while you should use only one of them.
You can go with any of the three following way:
Global resource way
Local resource way
Custom way
- remove the ConversionError Interceptor from your stack, for all the actions with this need.
With the first two solutions, you can't shortcircuit it, then you will have both the conversion AND the (first, if short-circuit) validator error. But the values will be preserved and repopulated automatically (eg. inserting abc
into an int
field, will repopulate abc
in the page).
With the last solution, your message will be shortcircuited, but you will have to handle manually the repopulation of the fields, AND you will need to remember to use a custom @ConversionErrorFieldValidator
for every field, because unless the conversion error messages will be swallowed.
Personally, I would go with solution 1. It is the safest, and it costs basically zero work.