You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Pierre Thibaudeau <pi...@gmail.com> on 2008/06/26 20:39:34 UTC

[S2] TypeConversion and generics

I am aware that, when applying request parameters to an action, Struts
cannot guess the actual type of parameters determined by a generic type
(because of erasure at compile time).

However, I am assuming that if a non-generic action class extends an
abstract generic one, it should be possible in the non-generic child to
force the type conversion explicitely.  Isn't that the case?  At the moment,
I seemingly cannot get Struts to realize that I did specify a type
conversion and I keeping getting the following exception (whether my forced
conversion is in place or not):
java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to
java.lang.Integer

Underneath are the relevant parts of my setup.
*What am I forgetting?*  (For example, am I missing an interceptor
somewhere?)*
Can anyone suggest how to trace what's happening at the point when a
converter should be applied (and is clearly not)?
*

In web.xml, I specify the location of the action package:

    <filter>
        <filter-name>action2</filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
        <init-param>
            <param-name>actionPackages</param-name>
            <param-value>com.mywebapp.actions2</param-value>
        </init-param>
    </filter>


In struts.xml, here's the bit about the concrete (non-generic) child:

    <package name="contrib" extends="struts-default" abstract="false"
namespace="/contrib" >
        <interceptors>
            <interceptor name="autoLogin"
class="com.mywebapp.interceptors.AutoLoginInterceptor" />
            <interceptor-stack name="contribStack">
                <interceptor-ref name="autoLogin"/>
                <interceptor-ref name="paramsPrepareParamsStack"/>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="contribStack" />
        <action name="groupContrib" class="groupContribAction">
            <result>/struts2/groupContrib2.jsp</result>
        </action>
    </package>


The previous reference to "groupContribAction" is in fact a Spring bean:

    <bean id="groupContribAction"
class="com.mywebapp.actions2.GroupContribAction"
parent="abstractContribAction" scope="prototype">
        <property name="contrib" ref="groupContrib" />
        <property name="contribService" ref="groupContribService" />
    </bean>


Here is an excerpt of the concrete action class itself.  Notice the
conversion annotations.  (I also half-heartedly tried without annotations,
using instead GroupContribAction-conversion.properties.)

@Conversion
public class GroupContribAction extends ContribAction<Integer> {
    private Integer propertyId;

    @Override
    public Integer getPropertyId() { return propertyId; }

    @Override
    @TypeConversion(converter =
"com.mywebapp.converters.StringToIntegerConverter")
    public void setPropertyId(Integer propertyId) { this.propertyId =
propertyId; }
}


And finally, here is an excerpt of the abstract generic parent:

public abstract class ContribAction<K extends Serializable>
            extends ActionSupport implements ServletRequestAware, Preparable
{

    public abstract void setPropertyId(K propertyId);
    public abstract K getPropertyId();
}

Re: [S2] TypeConversion and generics

Posted by Pierre Thibaudeau <pi...@gmail.com>.
Hi Lukasz

I don't know why you use such generic action class?

;)
Well, I haven't shown you the purpose of any of the objects. (In fact, the
full hierarchy is highly more complex than what is shown in my previous
post;  there are 29 objects involved...)


> And as I know OGNL support generics and it will try to convert to given
> type without TypeConversion
>

I wish it did, except that I keep getting an exception (as mentioned in
previous post)...
http://struts.apache.org/2.1.2/docs/type-conversion.html#TypeConversion-GenericsandErasure

Re: [S2] TypeConversion and generics

Posted by Lukasz Lenart <lu...@googlemail.com>.
Hi,

I don't know why you use such generic action class? And as I know OGNL
support generics and it will try to convert to given type without
TypeConversion


Regards
-- 
Lukasz
http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] TypeConversion and generics

Posted by Pierre Thibaudeau <pi...@gmail.com>.
2008/6/27 Lukasz Lenart <lu...@googlemail.com>:

> Right now, I don't have any other suggestions, I will try to test
> something like you during weekend, maybe then I will come back to you
> with some idea ;-)
>

Thanks Lukasz!

What I just did---and it worked---was to remove the abstract property setter
from the abstract generified parent class.  While the abstract getter is
essential in the abstract parent  (because used by other methods in the
parent), the setter was not.   (I should have seen that one earlier!!!)

In other words, at my end, the pressure's off my back.  Though I am still
puzzled by the fact that the presence of an explicit converter wouldn't have
solved the situation...

Re: [S2] TypeConversion and generics

Posted by Lukasz Lenart <lu...@googlemail.com>.
Hi,

Right now, I don't have any other suggestions, I will try to test
something like you during weekend, maybe then I will come back to you
with some idea ;-)


Regards
-- 
Lukasz
http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] TypeConversion and generics

Posted by Chris Pratt <th...@gmail.com>.
On Thu, Jun 26, 2008 at 3:04 PM, Pierre Thibaudeau
<pi...@gmail.com> wrote:
> 2008/6/26 Chris Pratt <th...@gmail.com>:
>
>> How does your case differ from the example on the Type Conversion page
>> you referenced?  It seems to me you're trying to do exactly what that
>> page says you can't?
>>
>
> My understanding of
> http://struts.apache.org/2.1.2/docs/type-conversion.html#TypeConversion-GenericsandErasure
> is that Struts cannot *infer* the actual type of a generified type.  (And
> that was the very first statement I made at the beginning of this thread.)
> Which is exactly why I intend to *specify* the conversion (and not let
> Struts attempt to do something which it can't do).
>
> It's obvious from the erasure of generics that Struts could not (even in
> theory) deduce the correct conversion.  But if I specify my own converter,
> why does it fail to make use of it?  I don't see that the reference I quoted
> makes any comment about that...
>

Ahhh, that's the piece I missed.  Seems like that should work, but I
haven't had to try anything like that.  Sorry.
  (*Chris*)

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] TypeConversion and generics

Posted by Pierre Thibaudeau <pi...@gmail.com>.
2008/6/26 Chris Pratt <th...@gmail.com>:

> How does your case differ from the example on the Type Conversion page
> you referenced?  It seems to me you're trying to do exactly what that
> page says you can't?
>

My understanding of
http://struts.apache.org/2.1.2/docs/type-conversion.html#TypeConversion-GenericsandErasure
is that Struts cannot *infer* the actual type of a generified type.  (And
that was the very first statement I made at the beginning of this thread.)
Which is exactly why I intend to *specify* the conversion (and not let
Struts attempt to do something which it can't do).

It's obvious from the erasure of generics that Struts could not (even in
theory) deduce the correct conversion.  But if I specify my own converter,
why does it fail to make use of it?  I don't see that the reference I quoted
makes any comment about that...

Re: [S2] TypeConversion and generics

Posted by Chris Pratt <th...@gmail.com>.
How does your case differ from the example on the Type Conversion page
you referenced?  It seems to me you're trying to do exactly what that
page says you can't?
  (*Chris*)

On Thu, Jun 26, 2008 at 12:56 PM, Pierre Thibaudeau
<pi...@gmail.com> wrote:
> I tried your suggestion.  Unfortunately, the exception is exactly as before.
> (In practice, it would not have been a good idea to put the autoLogin
> interceptor after the prepare interceptor, but I am definitely willing to
> try anything!)
>
> 2008/6/26 Lukasz Lenart <lu...@googlemail.com>:
>
>> Try to change order of your interceptors as below
>>
>>           <interceptor-stack name="contribStack">
>>               <interceptor-ref name="paramsPrepareParamsStack"/>
>>               <interceptor-ref name="autoLogin"/>
>>           </interceptor-stack>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] TypeConversion and generics

Posted by Pierre Thibaudeau <pi...@gmail.com>.
I tried your suggestion.  Unfortunately, the exception is exactly as before.
(In practice, it would not have been a good idea to put the autoLogin
interceptor after the prepare interceptor, but I am definitely willing to
try anything!)

2008/6/26 Lukasz Lenart <lu...@googlemail.com>:

> Try to change order of your interceptors as below
>
>           <interceptor-stack name="contribStack">
>               <interceptor-ref name="paramsPrepareParamsStack"/>
>               <interceptor-ref name="autoLogin"/>
>           </interceptor-stack>
>

Re: [S2] TypeConversion and generics

Posted by Lukasz Lenart <lu...@googlemail.com>.
Try to change order of your interceptors as below

           <interceptor-stack name="contribStack">
               <interceptor-ref name="paramsPrepareParamsStack"/>
               <interceptor-ref name="autoLogin"/>
           </interceptor-stack>


Regards
-- 
Lukasz
http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: [S2] TypeConversion and generics

Posted by Pierre Thibaudeau <pi...@gmail.com>.
I realize that I may have been stingy on the exception stack trace.  Here is
more of it.
Notice that, nowhere in there is my StringToIntegerConverter actually
called.  (It would have logged the occurrence.)

15:22:37,762 DEBUG ParametersInterceptor:58 - Setting params propertyId => [
295 ]
15:22:37,777 DEBUG XWorkConverter:58 - key from method name... propertyId -
setPropertyId
15:22:37,778 DEBUG XWorkConverter:58 - propertyId:propertyId
15:22:37,862 DEBUG XWorkConverter:58 -
propertyId:com.mywebapp.converters.StringToIntegerConverter@7e86b8
15:22:37,869 DEBUG XWorkConverter:58 - Class:
com.mywebapp.actions2.GroupContribAction
15:22:37,873 DEBUG XWorkConverter:58 - key from method name... propertyId -
setPropertyId
15:22:37,875 DEBUG XWorkConverter:58 - propertyId:propertyId
15:22:37,906 DEBUG XWorkConverter:58 -
propertyId:com.mywebapp.converters.StringToIntegerConverter@c5a196
ognl.MethodFailedException: Method "setPropertyId" failed for object
com.infloox.contrib.actions2.NaturalizationContribAction@f3bed9[java.lang.ClassCastException:
[Ljava.lang.String; cannot be cast to
java.lang.Integer]
    at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:823)
    at ognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:964)
    at
ognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:75)
    at
ognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:131)
    at
com.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:27)
    at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:1656)
    at
com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor.setProperty(CompoundRootAccessor.java:59)
    at ognl.OgnlRuntime.setProperty(OgnlRuntime.java:1656)
    at ognl.ASTProperty.setValueBody(ASTProperty.java:101)
    at ognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:177)
    at ognl.SimpleNode.setValue(SimpleNode.java:246)
    at ognl.Ognl.setValue(Ognl.java:476)
    at com.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:197)
    at
com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:150)
    at
com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:138)
    at
com.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters(ParametersInterceptor.java:205)
    at
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:162)
    ... and 40 more lines
/-- Encapsulated exception ------------\
java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to
java.lang.Integer
    at
com.mywebapp.actions2.GroupContribAction.setPropertyId(GroupContribAction.java:1)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:517)
    ...
\--------------------------------------/
expr: propertyId val: [Ljava.lang.String;@76a247 context:
ognl.OgnlContext@6aa88a90root:[com.mywebapp.actions2.GroupContribAction@f3bed9,
com.opensymphony.xwork2.DefaultTextProvider@3e162d] value:
[Ljava.lang.String;@76a247
15:22:37,949 ERROR ParametersInterceptor:24 - ParametersInterceptor -
[setParameters]: Unexpected Exception caught setting 'propertyId' on 'class
com.infloox.contrib.actions2.NaturalizationContribAction: Error setting
expression 'propertyId' with value '[Ljava.lang.String;@76a247'


2008/6/26 Pierre Thibaudeau <pi...@gmail.com>:

> I am aware that, when applying request parameters to an action, Struts
> cannot guess the actual type of parameters determined by a generic type
> (because of erasure at compile time).
>
> However, I am assuming that if a non-generic action class extends an
> abstract generic one, it should be possible in the non-generic child to
> force the type conversion explicitely.  Isn't that the case?  At the moment,
> I seemingly cannot get Struts to realize that I did specify a type
> conversion and I keeping getting the following exception (whether my forced
> conversion is in place or not):
> java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to
> java.lang.Integer
> ...
>