commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Craig R. McClanahan" <craig...@apache.org>
Subject RE: [Design Discussion] DynaBeans - Round 2
Date Thu, 27 Dec 2001 21:19:57 GMT


On Thu, 27 Dec 2001, Paulo Gaspar wrote:

> > From: Rey Francois [mailto:Francois.Rey@capco.com]

> >
> > I had to crate a similar interface in a data mapper framework I developed,
> > however in the signature of the conversion method I included an additional
> > parameter for the Locale. Without it, support for internationalized
> > conversions is difficult.
>
> The method I use is to have a different converter for each Locale where such
> distinction is necessary (which happens quite often).
>
> Notice that I have the option of assigning a converter per DynaBean and not
> per DynaClass as Craig wrote in his proposal exactly because of situations
> like this. The converter often needs some kind of contextual information.
>

I'm planning on ripping the getConverter() back out of DynaClass -- it's
too restrictive.

Paulo, did you ever run into a scenario where you had to be accessing the
same Record with different Converters at the same time ... perhaps even on
separate threads?  This would cause some grief with the idea of assigning
a Converter to a DynaBean instance.

> This situations also made me implement my converters in a hierarchical way,
> meaning that converter may just add or override a few conversion rules to a
> "parent" converter. Some of those conversion rules may add context
> information like "Locale" or "Base directory".
>

That makes a lot of sense.

> > Perhaps this could be added in a new method of the
> > Converter interface, or perhaps it can be included in another interface
> > extending the Converter, e.g. LocalizedConverter extends Converter.
>
> You only need to place that kind of thing in the implementation. The
> interface can stay as it is.

That's certainly obvious in retrospect :-).

I like Converter-per-Locale (or for whatever extra context information it
needs).  I'm still thinking about explicitly tying converters to DynaBean
instances ...

Paulo, do you normally design your Converters to go both directions (i.e.
so you can use them in the getters *and* the setters), or just one way?
In the latter case, you'd probably need two.

>
> > What do you think?
> >
> > Actually the more I think about this, the more I'm wondering if it makes
> > sense to include a conversion feature into DynaBeans. My gut feeling would
> > be to restrict DynaBeans to be only dynamic data containers, and handle
> > conversions separately.
>
> Notice that my DynaBean (actually called IRecord) interface does not know
> anything about converters - only my most used implementation does so.
>

Ah ... so you really could use two one-way Converters if you wanted to ...
but the key is that support for conversion is a feature of a particular
DynaBean implementation class -- not of the top-level interface.

I'd like to keep the top-level interfaces as simple as possible, to allow
for variations in the implementations underneath.

> I found that I am converting types most of the time, like when I read to the
> DynaBean things like:
>  - Servlet parameters;
>  - ResultSet columns;
>  - XML attributes;
>  - A big etc.
>
> Using a helper class instead of a simple set() method all the time becomes a
> pain in the ass, especially because it would involve also getting property
> type information. So, you would need something like:
>
>     DynaClass myBeanClass = myBean.getDynaClass();
>     PropertyDescriptor propDesc =
> myBeanClass.getPropertyDescriptor("myprop");
>     myBean.set("myprop", cvt.convert(propDesc.getPropertyType(), newValue));
>
> instead of
>     myBean.set("myprop", newValue);
>
> Notice also that:
>  - You have the opportunity to make a much more efficient implementation
>    inside the DynaBean;
>  - The DynaBean implementation can default (as mine) to the use of a
>    NoOpConverter that performs no conversion at all.
>
>
> > First not all situations require the use of conversions.
>
> The above NoOpConverter solves that. And notice that I am talking about an
> implementation - I agree that the converter should be kept away from the
> interface.
>

You could of course also implement a DynaBean base class that doesn't
support the conversion functionality at all for cases where it's not
needed.

> > Secondly if conversions need to be done, I'd probably handle it
> > separately from the original bean. Most of the time conversions are
> > necessary because of a specific usage situation requiring a different and
> > specific format, and you cannot or do not want to change the
> > original format
> > to accommodate this new usage situation (either because you do not own
> > the original format specification, or because you don't want to make
> > it specific and prefer to keep it generic and reusable).
> > Supposing we have an EJB backend that provides a value object. Should the
> > value object be coded to support String conversions for GUI display? You
> > can do this, but that means all your client have to follow the same
> > formatting conventions.
>
> That is why, as above, the Converter should be DynaBean specific and not
> DynaClass specific.
>
> > To avoid this you either convert on-the-fly (e.g. using some
> > kind of wrapper), or you create another data container that stores the
> > converted values.
>
> Or you assign a new Converter to the DynaBean.
>
> > Either way the conversion are handled outside the original
> > bean itself. In the case of Struts we use a separate data container (there
> > are good reasons for this), ActionForms, and conversions are either custom
> > coded or handled by the ConvertUtils class.
>
> > If we had to use DynaBeans in Struts for implementing
> > ActionForms, we could
> > make a case for making these "DynActionForms" able to perform some
> > conversions. We could implement transparently the use of converters in the
> > set() method like Paulo Gaspar suggests in order to populate a
> > DynActionForm
> > from a value object (or business object). However we would probably need
> > to do the reverse conversion in the get() method so that we can populate a
> > value object with a DynActionForm. This would require some ways of passing
> > the target type to the get() method so it can select the appropriate
> > converter.
>
> It is too messy to have such a get() method. What I do is to wrap the value
> object with another DynaBean implementation.
>
> I have a kind of DynaBeanWrapper class which also uses a Converter and that
> can wrap any object with "properties" (or "fields" or "columns"). Only bits
> of the DynaClass need to change depending of what kind of object you are
> wrapping - the setter and getter implementations.
>
> Then there is a "DynaIntrospector" that examines the object to be wrapped
> (e.g. a bean or a ResultSet) and builds an appropriate DynaClass. (For beans
> such instrospection provides a nice place to hold an introspection cache.)
>
> Of course that you do not need such thing if you just want to convert all
> the fields of a DynaBean into text. You might use a Converter for that too
> but it is simpler to do it outside the bean, as in:
>
>   String s = cvt.convert(java.lang.String.class, myDynaBean.get("myProp"));
>
> and the "cvt" Converter can hold the appropriate conversion rules to format
> each data type.
>
>
> I also have a converter helper tool for the "asThis" and "asThat" stuff.
> Just to give you an idea, it is used like this:
>
>    CvtHelper cvt = new CvtHelper(myConverter);
>
>    int i  = cvt.asInt(toIntValue, -1);
>    Integer io  = cvt.asInteger(toIntValue);
>
>    String s = cvt.asString(toStrValue);
>
> So, it is a class that allows you to specify a converter to be used to
> perform the most frequent conversions to primitive and "java.lang" types.
>
> I think using such tool is much simpler and flexible that having the usual
> getSomeType() helper methods hanging in every other class. And the
> implementation is obvious. Like:
>
> public class CvtHelper
> {
>     private final Converter m_cvt;
>
>     public CvtHelper(final Converter i_cvt)
>     {   m_cvt = i_cvt;
>     }
> ...
>
>     public final String asString(final Object i_value)
>     {
>         return (String)(m_cvt.convert(String.class, i_value));
>     }
>
> ...
> }
>
>
> > Such design would also mean that we must easily differentiate
> > between the various input/output types: it should be possible for
> > a JSP page
> > to ensure it gets an appropriate display value as a String, while on the
> > other side it should be possible to get an appropriate "business" value.
> > Using the same getter method for these two scenario seems to
> > introduce some complications.
>
> As mentioned above (different converters, only one getter, etc.).
>
>
> > What if the business value is already a String, which has to
> > be properly converted to another String for display (e.g. > O<->Open)?
> > In such case you cannot really use the Class as a discriminant between
> > the different types, since both are Strings. Should we use two get methods
> > instead?
>
> That only depends on the Converter implementation. Remember that Converter
> is an interface.
>
>
>
> > Seems like an overkill... Also doing such conversion in an ActionForm is
> > in some cases introducing some overlap with validation.
>
> It is complementary to Validation. For an input value to be valid it must
> be possible to convert it to the destination type.
>

In my Struts-based designs, I tend to check for convertability in my
ActionForm validate() methods -- conversion success is necessary but not
sufficient for validity, so you're checking for other stuff there anyway.

>
> > Sometimes being able to successfully convert a display String to a
> > business value is enough to validate it, at least partially: a String
> > successfully parsed by SimpleDateFormat is a valid date, no need to
> > validate each character, and on
> > the resulting Date object further validation can be performed (is it a
> > future date, etc.).
>
> So, this means that you also find out that it is a complementary issue.
>
>
> > Finally add the internationalization issue I started with...
>
> Again, a converter per Locale and DynaBean specific converters.
>
>
> > Ok, I will conclude here because my written thinking is getting
> > too long ;)
>
> I suffer of the same "problem".
> =;o)
>
>
> > My conclusion would be to leave aside the conversion feature and
> > focus only on the data container aspect.
>
> Containing the data is the simple bit. A Map would do.
>
> The usefulness from the DynaBean comes from it being able to help us
> performing the most usual tasks with this kind of data with less
> routine coding and with similar or improved quality (data validation
> and other).
>
>
> > Fr.
>
> Have fun,
> Paulo Gaspar
>

Craig


--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message