You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Daniel Baldes <db...@open.ch> on 2008/02/19 15:00:10 UTC
Type conversion questions
Hello,
I have a web form where you can, generally speaking, assign objects to
groups. This is done via a multiple select box which displays an
object's name and uses its ID property as value.
So, usually, my action would get back a String array containing the IDs
of the selected objects. I want the framework to load the corresponding
objects from the database and pass them as a Collection to my action's
setObjects(Collection<Object> objects) method, so that my action doesn't
have to deal with loading objects.
So I wrote a type converter. The "convertFromString" method takes the
String array with the IDs, determines the target element type using
ObjectTypeDeterminer, loads the objects and returns them in a
collection. In this direction - form to action - it works quite well.
Now my questions:
1. extending StrutsTypeConverter forces me to implement String
convertToString(Map context, Object o). I think there is no common sense
way of converting a collection back to a String in this context. It
would, maybe, make sense to convert it to a String[]. But what I
actually want is to have access to the unconverted collection in the
JSP. This might seem strange from some point of view, and I could live
without it, but is there a way to do this? Example:
<s:select multiple="true"
name="myObjects"
list="myObjects" listKey="id" listValue="name" />
This way I could use getMyObjects() for displaying my objects and
setMyObjects() for setting them (using only their IDs).
2. Is there a way to define a type converter application wide, like
"always use this type converter for setting types which are subclasses
of X" and "for setting types which are Collection<subclass-of-X>"? This
way I could define the type converter once for all persistence-capable
classes.
Thanks in advance,
Daniel
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Jeromy Evans <je...@blueskyminds.com.au>.
> Now the funny thing is that this seems to work. I got all sorts of
> exceptions at first, but they don't seem to be related to conversion.
>
> Thanks for all your help, and I'm sorry for wasting your time on this
> one. I'll get back when I find the real problem, should it be related
> to struts.
>
> Daniel
>
No problem, no time wasted. Your technique has given me some ideas.
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Daniel Baldes <db...@open.ch>.
Hi Jeromy,
Jeromy Evans wrote:
> Ah, I see the problem better now. In your select:
>
> <s:select multiple="true"
> name="myObjects"
> list="myObjects" listKey="id" listValue="name" />
> you're trying to access myObjects as both a list of objects (list=) and
> as a string (name=). You can't do what you're describing because
> convertToString needs to provide the currently selected value for the
> select.
>
> I presume you don't really mean that, but rather want:
> <s:select multiple="true"
> name="mySelectedObject"
> list="myObjects" listKey="id" listValue="name" />
>
> where mySelectObject is the same class as the elements in the list, and
> type conversion ensures that the select contains id:name and sees just
> the selected object loaded from persistence and provides a list of
> objects loaded from persistence (no handling of strings what-so-ever).
Sorry, now I see that my example was misleading. Let me try again:
F.e. I would want to display a list of myObjects, and a "multiple"
select box where you can modify the list.
List:
<s:iterator value="myObjects" var="o" >${o.name}</s:iterator>
Select:
<s:select multiple="true" name="myObjects" list="availableMyObjects"
listKey="id" listValue="name" />
This way, the iterator would need to get a collection from
getMyObjects() (without type conversion), but the select would send IDs
which needed to be converted.
Now the funny thing is that this seems to work. I got all sorts of
exceptions at first, but they don't seem to be related to conversion.
Thanks for all your help, and I'm sorry for wasting your time on this
one. I'll get back when I find the real problem, should it be related to
struts.
Daniel
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Jeromy Evans <je...@blueskyminds.com.au>.
Daniel Baldes wrote:
>
>
> the problem here is that convertToString only allows returning .. a
> String. Accessing "myObjects" in a JSP would always call
> converter.convertToString(context, myaction.getMyObjects()) (as far as
> I can tell). So this way I can't return a collection of objects where
> I could, for example, iterate over.
>
> Daniel
>
Ah, I see the problem better now. In your select:
<s:select multiple="true"
name="myObjects"
list="myObjects" listKey="id" listValue="name" />
you're trying to access myObjects as both a list of objects (list=) and
as a string (name=). You can't do what you're describing because
convertToString needs to provide the currently selected value for the
select.
I presume you don't really mean that, but rather want:
<s:select multiple="true"
name="mySelectedObject"
list="myObjects" listKey="id" listValue="name" />
where mySelectObject is the same class as the elements in the list, and
type conversion ensures that the select contains id:name and sees just
the selected object loaded from persistence and provides a list of
objects loaded from persistence (no handling of strings what-so-ever).
If I've misunderstood let me know.
Posting to your action:
When the params interceptor is invoked, it calls your custom converter
with the selected id value. Your converter looks up the entity in the
convertFromString method and returns the Object. The params interceptor
sets this object in your action. Perfect
Rendering the view:
The options in the select are populated by calls to convertToString on
each element in the list.
The currently selected value is also populated by a call to
convertToString on mySelectedObject
So, you definitely can't mix purposes here.
---
There has been talk on the developer list about providing a better model
for selects so your action doesn't have to provide the list of possible
values, and more importantly, the list of values is available after a
validation error without any further effort by your action. Nothing has
progressed AFAIK though.
Hope that was helpful and on track.
regards,
Jeromy Evans
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Daniel Baldes <db...@open.ch>.
Jeromy Evans wrote:
[...]
>> Now my questions:
>>
>> 1. extending StrutsTypeConverter forces me to implement String
>> convertToString(Map context, Object o). I think there is no common
>> sense way of converting a collection back to a String in this context.
>> It would, maybe, make sense to convert it to a String[]. But what I
>> actually want is to have access to the unconverted collection in the
>> JSP. This might seem strange from some point of view, and I could live
>> without it, but is there a way to do this? Example:
[...]
> It does really follow the intended contract of the interface, but I
> don't see why convertFromString can't return a different view of the
> object than convertToString. Have you tried it? This effectively gives
> you the "databinding" feature of ASP.net (which I personally cringe at,
> but can't argue with how productive it is to work with)
Hi Jeromy,
the problem here is that convertToString only allows returning .. a
String. Accessing "myObjects" in a JSP would always call
converter.convertToString(context, myaction.getMyObjects()) (as far as I
can tell). So this way I can't return a collection of objects where I
could, for example, iterate over.
Daniel
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Daniel Baldes <db...@open.ch>.
Hi Jeromy,
Jeromy Evans wrote:
> Daniel Baldes wrote:
[...]
>> 2. Is there a way to define a type converter application wide, like
>> "always use this type converter for setting types which are subclasses
>> of X" and "for setting types which are Collection<subclass-of-X>"?
>> This way I could define the type converter once for all
>> persistence-capable classes.
>>
> classpath:xwork-converters.properties allows you to define global
> converters by class name. You may be able to the the element_ feature
> for collections.
> Otherwise visitor validation will have to do
I found out that this line in xwork-conversion.properties is sufficient
to define my custom converter for all subclasses AND collections of
subclasses:
com.acme.SuperClass = com.acme.CustomConverter
Perfect - this is what I need.
Thanks for your Help,
Daniel
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Jeromy Evans <je...@blueskyminds.com.au>.
> Hi Jeromy
> I'm not clear what the performance problem you mention could be. This
> is what I'm doing myself and while my app's performance is OK, I would
> love to improve it. What do you mean by (e.g. select n+1 due to
> iteration)?
>
>
> All the best
> Adam
>
> ---
Actually, I've assumed you're using ORM like JPA/Hibernate/TopLink If
not it's not as relevant, but still could be.
The select n+1 problem is well described over at Hibernate:
http://www.hibernate.org/118.html
Basically, the problem occurs when you use lazy fetching and iterate
through a collection. Instead of retrieving the entire collection from
the database in one efficient query, the implementation performs a query
for the parent object and then one query for each item in the collection
in each pass of the iteration (hence n+1 selects). It's one of the
risks of lazy fetching and using the session-in-view pattern.
Developers often don't realise it until they analyse the queries because
it seems slow. Caching can avoid it and also complicates it.
As you're accessing objects and hiding the fact they're loaded from a
database, it's very easy to accidentally trigger this problem. If your
converter is performing the query itself or through a service you can
easily avoid it.
Hope that make sense.
regards,
Jeromy Evans
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Adam Hardy <ah...@cyberspaceroad.com>.
Jeromy Evans on 19/02/08 22:23, wrote:
> Daniel Baldes wrote:
>> Hello,
>>
>> I have a web form where you can, generally speaking, assign objects to
>> groups. This is done via a multiple select box which displays an
>> object's name and uses its ID property as value.
>>
>> So, usually, my action would get back a String array containing the
>> IDs of the selected objects. I want the framework to load the
>> corresponding objects from the database and pass them as a Collection
>> to my action's setObjects(Collection<Object> objects) method, so that
>> my action doesn't have to deal with loading objects.
>>
>> So I wrote a type converter. The "convertFromString" method takes the
>> String array with the IDs, determines the target element type using
>> ObjectTypeDeterminer, loads the objects and returns them in a
>> collection. In this direction - form to action - it works quite well.
>>
>
> Great. I've never tried this myself. I suppose you run the risk of
> some performance penalties doing it here (eg. select n+1 due to
> iteration) and the conversion error exception is probably not ideal, but
> otherwise I'm impressed.
Hi Jeromy
I'm not clear what the performance problem you mention could be. This is what
I'm doing myself and while my app's performance is OK, I would love to improve
it. What do you mean by (e.g. select n+1 due to iteration)?
All the best
Adam
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Daniel Baldes <db...@open.ch>.
Hello Martin,
this would be ok, but that method doesn't exist in StrutsTypeConverter
as of struts 2.0.11, and most likely the framework won't call it when I
implement it. Or am I missing something?
Daniel
Martin Gainty wrote:
> package org.apache.struts2.showcase.conversion
> public class EnumTypeConverter extends StrutsTypeConverter
> {
> //old methods..
>
> //new method to convert map contents to Strings..
> @Override
> public String[] convertToStrings(Map context, Object o)
> {
> int j=0;
> Strings[] s;
> List l = (List) o;
> String result ="<";
> for (Iterator i = l.iterator(); i.hasNext(); )
> {
> s[j++]=i.next();
> }
> return s;
> }
> //...other methods..
> }
>
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Martin Gainty <mg...@hotmail.com>.
package org.apache.struts2.showcase.conversion
public class EnumTypeConverter extends StrutsTypeConverter
{
//old methods..
//new method to convert map contents to Strings..
@Override
public String[] convertToStrings(Map context, Object o)
{
int j=0;
Strings[] s;
List l = (List) o;
String result ="<";
for (Iterator i = l.iterator(); i.hasNext(); )
{
s[j++]=i.next();
}
return s;
}
//...other methods..
}
FWIW
Martin--
----- Original Message -----
From: "Jeromy Evans" <je...@blueskyminds.com.au>
To: "Struts Users Mailing List" <us...@struts.apache.org>
Sent: Tuesday, February 19, 2008 5:23 PM
Subject: Re: Type conversion questions
> Daniel Baldes wrote:
> > Hello,
> >
> > I have a web form where you can, generally speaking, assign objects to
> > groups. This is done via a multiple select box which displays an
> > object's name and uses its ID property as value.
> >
> > So, usually, my action would get back a String array containing the
> > IDs of the selected objects. I want the framework to load the
> > corresponding objects from the database and pass them as a Collection
> > to my action's setObjects(Collection<Object> objects) method, so that
> > my action doesn't have to deal with loading objects.
> >
> > So I wrote a type converter. The "convertFromString" method takes the
> > String array with the IDs, determines the target element type using
> > ObjectTypeDeterminer, loads the objects and returns them in a
> > collection. In this direction - form to action - it works quite well.
> >
>
> Great. I've never tried this myself. I suppose you run the risk of
> some performance penalties doing it here (eg. select n+1 due to
> iteration) and the conversion error exception is probably not ideal, but
> otherwise I'm impressed.
> > Now my questions:
> >
> > 1. extending StrutsTypeConverter forces me to implement String
> > convertToString(Map context, Object o). I think there is no common
> > sense way of converting a collection back to a String in this context.
> > It would, maybe, make sense to convert it to a String[]. But what I
> > actually want is to have access to the unconverted collection in the
> > JSP. This might seem strange from some point of view, and I could live
> > without it, but is there a way to do this? Example:
> >
> > <s:select multiple="true"
> > name="myObjects"
> > list="myObjects" listKey="id" listValue="name" />
> >
> > This way I could use getMyObjects() for displaying my objects and
> > setMyObjects() for setting them (using only their IDs).
> >
>
> It does really follow the intended contract of the interface, but I
> don't see why convertFromString can't return a different view of the
> object than convertToString. Have you tried it? This effectively gives
> you the "databinding" feature of ASP.net (which I personally cringe at,
> but can't argue with how productive it is to work with)
> >
> > 2. Is there a way to define a type converter application wide, like
> > "always use this type converter for setting types which are subclasses
> > of X" and "for setting types which are Collection<subclass-of-X>"?
> > This way I could define the type converter once for all
> > persistence-capable classes.
> >
> classpath:xwork-converters.properties allows you to define global
> converters by class name. You may be able to the the element_ feature
> for collections.
> Otherwise visitor validation will have to do
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Jeromy Evans <je...@blueskyminds.com.au>.
Daniel Baldes wrote:
> Hello,
>
> I have a web form where you can, generally speaking, assign objects to
> groups. This is done via a multiple select box which displays an
> object's name and uses its ID property as value.
>
> So, usually, my action would get back a String array containing the
> IDs of the selected objects. I want the framework to load the
> corresponding objects from the database and pass them as a Collection
> to my action's setObjects(Collection<Object> objects) method, so that
> my action doesn't have to deal with loading objects.
>
> So I wrote a type converter. The "convertFromString" method takes the
> String array with the IDs, determines the target element type using
> ObjectTypeDeterminer, loads the objects and returns them in a
> collection. In this direction - form to action - it works quite well.
>
Great. I've never tried this myself. I suppose you run the risk of
some performance penalties doing it here (eg. select n+1 due to
iteration) and the conversion error exception is probably not ideal, but
otherwise I'm impressed.
> Now my questions:
>
> 1. extending StrutsTypeConverter forces me to implement String
> convertToString(Map context, Object o). I think there is no common
> sense way of converting a collection back to a String in this context.
> It would, maybe, make sense to convert it to a String[]. But what I
> actually want is to have access to the unconverted collection in the
> JSP. This might seem strange from some point of view, and I could live
> without it, but is there a way to do this? Example:
>
> <s:select multiple="true"
> name="myObjects"
> list="myObjects" listKey="id" listValue="name" />
>
> This way I could use getMyObjects() for displaying my objects and
> setMyObjects() for setting them (using only their IDs).
>
It does really follow the intended contract of the interface, but I
don't see why convertFromString can't return a different view of the
object than convertToString. Have you tried it? This effectively gives
you the "databinding" feature of ASP.net (which I personally cringe at,
but can't argue with how productive it is to work with)
>
> 2. Is there a way to define a type converter application wide, like
> "always use this type converter for setting types which are subclasses
> of X" and "for setting types which are Collection<subclass-of-X>"?
> This way I could define the type converter once for all
> persistence-capable classes.
>
classpath:xwork-converters.properties allows you to define global
converters by class name. You may be able to the the element_ feature
for collections.
Otherwise visitor validation will have to do
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Daniel Baldes <db...@open.ch>.
Laurie Harper wrote:
> Daniel Baldes wrote:
>> [...]
[...]
>> <s:select multiple="true"
>> name="myObjects"
>> list="myObjects" listKey="id" listValue="name" />
>>
>> This way I could use getMyObjects() for displaying my objects and
>> setMyObjects() for setting them (using only their IDs).
>
> Doesn't this imply that the myObjects property represents both the set
> of values that can be selected *and* the set of values that is / has
> been selected? What would happen if the user made their selection(s) and
> submitted the form, and the form was re-displayed due to a validation
> error?
>
> Maybe I'm missing the pattern, but this doesn't seem right to me :=)
>
> L.
This example was actually misleading, I'm sorry. Please just ignore this
part of my post, the problem may be non-existent ;-)
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org
Re: Type conversion questions
Posted by Laurie Harper <la...@holoweb.net>.
Daniel Baldes wrote:
> [...]
>
> 1. extending StrutsTypeConverter forces me to implement String
> convertToString(Map context, Object o). I think there is no common sense
> way of converting a collection back to a String in this context. It
> would, maybe, make sense to convert it to a String[]. But what I
> actually want is to have access to the unconverted collection in the
> JSP. This might seem strange from some point of view, and I could live
> without it, but is there a way to do this? Example:
>
> <s:select multiple="true"
> name="myObjects"
> list="myObjects" listKey="id" listValue="name" />
>
> This way I could use getMyObjects() for displaying my objects and
> setMyObjects() for setting them (using only their IDs).
Doesn't this imply that the myObjects property represents both the set
of values that can be selected *and* the set of values that is / has
been selected? What would happen if the user made their selection(s) and
submitted the form, and the form was re-displayed due to a validation error?
Maybe I'm missing the pattern, but this doesn't seem right to me :=)
L.
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org