Release Notes for 2.0
Breaking Changes
Boolean converter processes no value, since 2.0.0
Previously, BooleanConverter did not process missing or empty string parameter values, leaving boolean form fields with default values, typically false for primitive boolean fields and null for object boolean. Now, for sensible defaults for Collection<Boolean> fields, missing or empty values are converted to false. The previous conversion behaviour can be restored by disabling processNoValue in BooleanConversion annotations, such as below:
@BooleanConversion(processNoValue = false)
private Boolean enableGroup;
Collection-based policies changed to list-based, since 2.0.0
Previously, list converters, list post-conversion adjusters, and list post-conversion validators were named after collection and read and/or returned them. This ignored converted values, such as comma separated values, can have an order. Worse, collection converters were responsible for returning a collection compatible with the recipient form field despite no documented requirement. Now, these policies are named after list, use them to preserve order, and compatibility is the framework's responsibility.
In the convert function, replace calls to makeCollectionForRecipient(recipientFieldClass) with
new ArrayList<>(), ConversionResult.makeSkippedCollectionResult() with ConversionResult.makeSkippedListResult(),
and ConversionResult.makeSuccessCollectionResult() with ConversionResult.makeSuccessListResult().
For the format function, replace the Collection parameter with List.
Default list converters no longer exist and single value converters default for array collection fields, since 2.0.0
Previously, collection form fields with no converter annotation defaulted to a default collection converter for the type, if any. Now, to be more like display formatting, the default is the default single value converter for the type, if any, applying to each entry. The previous conversion behaviour can be restored by explicitly annotating with the list converter, such as below:
@IntegerCSVConversion
private Collection<Integer> ids;
Form merges doValidate and doValidate2 functions, since 2.0.0
Previously, Form defined doValidate2 for Actions that supported ValidationAware2 and kept doValidate for older implementations. This was clunky and code that called the latter now calls the former with an adapter that converts warnings to info messages. Forms implementing doValidator2 should rename it to doValidator. Older forms implementing doValidator should change the parameter signature to below:
public void doValidate(ValidationAware2 validationAware, TextProvider textProvider) {
Form merges manualParameterConvert and manualParameterConvert2 functions and handles multiple parameters with the same name, since 2.0.0
Previously, Form defined manualParameterConvert2 for Actions that supported ValidationAware2 and kept manualParameterConvert for older implementations. This was clunky and for, older Actions, code now uses an adapter that converts warnings to info messages. Further, it presents Parameter for each request parameter name instead of a single String. Use getValue() to obtain a single value. Use getMultipleValues for multiple values. Forms implementing either should change its parameter signature to below:
public ManualParameterConversionResult manualParameterConvert(Map<String,Parameter> unprocessedParameters,
ValidationAware2 validationAware, TextProvider textProvider) {
FormattedListDisplay renamed selectedIndex to inPageIndex and selectedMasterIndex to selectedIndex, since 2.0.0
Previously, FormattedListDisplay defined selectedIndex as the index of the currently selected item in the current page and selectedMasterIndex as the index for the entire list in the list cache. These were poorly named and confused with a master list cache.
New Features
Processes multiple parameters with the same name, since 2.0.0
Previously, only single value fields were recognised, unless using a list converter, so only one request parameter matching the field name was read. Now, array and collection fields are recognised and the library creates the array or collection with an entry per request parameter. Adjusters are applied to each entry, then non-conversion validators, then converters, then post-conversion adjusters, then list post conversion adjusters, then post-conversion validators, then list post conversion validators.
This includes indexed field names, such as 'scores[2]'. This is useful for field errors.
New, built-in policies, since 2.0.0
| Policy | Type | Description |
|---|---|---|
| MinIntegerEntryCount | List post-conversion validator | Checks list size of integer array or collection |
| MinStringEntryCount | List post-conversion validator | Checks list size of string array or collection |
| RemoveEmptyStringEntries | List post-conversion adjuster | Removes null and empty string entries from string array or collection |
| RemoveNullIntegerEntries | List post-conversion adjuster | Removes null entries from integer array or collection |
| RequiredIntegerEntries | List post-conversion validator | Checks integer array or collection has no null entries |
| RequiredStringEntries | List post-conversion validator | Checks string array or collection has no null or empty string entries |
| SortIntegerEntries | List post-conversion adjuster | Sorts entries of an integer list |
| SortStringEntries | List post-conversion adjuster | Sorts entries of a string list |
| TrimEntries | List post-conversion adjuster | Trims individual entries of a string list |
Improvements
DefaultPolicyLookup reads config from struts.xml itself, since 2.0.0
Previously, DefaultPolicyLookup.getInstance() relied on a previous call of DefaultPolicyLookup.getInstance(configuration) configured by AnnotationValidationInterceptor2 or FormFormatterInterceptor. This was a kludge and meant these interceptors had to be invoked before any call to StrutsMiscellaneousLibrary.updateDisplay. Now, DefaultPolicyLookup reads configuration from struts.xml itself, rather than rely on dependency injection of interceptors.