views:

136

answers:

1

For a simple action class with these member variables:

...
private TestConverterEnum test;
private TestConverterEnum[] tests;
private List<TestConverterEnum> tList;
...

And a simple enum:

public enum TestConverterEnum {
    A,
    B,
    C;
}

Using the default struts2 enum conversion, when I send the request like so:

TestConterter.action?test=&tests=&tList=&b=asdf

For test I get a null value, which is expected. For the Array and List, however, I get and Array (or list) with one null element. Is this what is expected? Is there a way to prevent this.

We recently upgraded our struts2 version, and we had our own converters, which also don't work in this case, so I was hoping to use the default conversion method. We already have code that is validating these arrays for null and length, and I don't want to have to add another condition to these branches. Is there a way to prevent this bevavior?

+1  A: 

Yes, it is expected behaviour IMO.

Http parameters are in principle multivalued (typically used in multivalued select lists), hence the struts2 param interceptor asks (by reflection) for setters that accept arrays or (as a second option) a single value. Your action probably has a setTests(TestConverterEnum[] a) setter, so, when Struts2's interceptor has to map tests= he founds that setter, and thinks to himself: "I must set this 'tests' property with an array, let's see how many parameters were passed... only one (empty), then let's create an array of length one and fill it with the convertion..." etc.

I find it reasonable: your request included one 'tests' parameter (though empty), hence a one-sized array was created.

I'd bet that if you try TestConterter.action?tests=&tests= an array of length 2 will be created.

Updated:

Let's see if we agree in this : to pass an empty parameter in a request is (in principle) not the same as not passing it... though frequently one wants to treat both cases as equivalent.

If you'd want to tell Struts2: "ignore completely the empty parameters"... I don't think (supposing it is an acceptable idea) this behaviour can be enforced by some global setting. You could always write your own interceptor (or extend the Parameters interceptor) so that it cleans out the empty parameters from the request before mapping them.

BTW, note that this issue is unrelated to Enums or to Arrays, is totally general.

Now, the case of multivalued parameters requires extra consideration. I assume that if your Action has a public property of type array, it's because it can be set with several parameters, (a SELECT MULTIPLE typically) - if not, there is some design problem here. Now, what would be your expected behaviour for this request?

TestConterter.action?tests=&tests=A&tests=&tests=B&tests=B

Should this generate an array of length 5 [null, A, null, B, B] or 3 [A, B, B] or 2 [A, B] or what? It's difficult to give general criteria; that's why this is better dealt with in your setter method, in general.

leonbloy
partkyle
I updated my answer
leonbloy