Nullable values - dates

5 views
Skip to first unread message

Nando

unread,
Jan 3, 2007, 9:22:43 AM1/3/07
to transf...@googlegroups.com
I'm looking into how transfer handles typing and nullable values, and am running into a little snafu.

Since any incoming value from an HTML form is a string - no such thing as type there - i've typically been using beans that accept strings in the argument tags for all values. This allows me to let anything in and validate it once it's in the bean. So i've been exploring to what extent i can get Transfer to behave in this manner, especially for dates, which in my mind are the most problematic to deal with.

First, i tried setting the nullable value for date to "",

  <nullValues>
    <date value="" />
    <boolean value="0" />    
  </nullValues>

And found out that ColdSpring doesn't like that. Here's the error i get:

 Bean creation exception during init() of transfer.TransferFactory
"" is an invalid date or time string.
 
The error occurred in C:\CFusionMX7\wwwroot\coldspring\beans\DefaultXmlBeanFactory.cfc: line 539
Called from C:\CFusionMX7\wwwroot\coldspring\beans\DefaultXmlBeanFactory.cfc: line 332
Called from C:\CFusionMX7\wwwroot\Unity\trunk\ModelGlue\unity\loader\XmlConfigurationLoader.cfc: line 293

Ok, no problem, let's try something else:

<property name="dateLastFeatured" type="date" nullable="true" nullvalue="" />

When i use this, ColdSpring doesn't complain, but a new transfer object defaults to a datetime of now() instead of "", and i get an error if i try to set the date to "".  OK, that's not going to work if i can't set the null value i've chosen.

I'm not sure if there's a bug there or not.

So it seems i need to use a magic value of some sort that is a date to represent null, rather than an empty string. So let's forget about trying to set a different nullable value and use the default value of 1/1/100.

<property name="dateLastFeatured" type="date" nullable="true" />

Ok, so now when i create a new transferObject, the default date value is Now(). Hmmm,  i'm still wondering if it should be the null value rather than Now().

******

In a web form, an null date is of course an empty string. There's no other way to represent it to the user that would make sense to them. Numerics are a similar situation, but many times a 0 will do when the intention is "nothing".

This is the main reason i've come to the conclusion that beans that accept values from web forms shouldn't use typed arguments, particularly typed date arguments. In the world of HTML, dates are strings, and if i want to validate a date in this world, i'm looking for either an empty string or a date. If my bean doesn't accept an empty string, then it can't accept a valid value for a date from a form when the user's intention is no date.

So far, my point of translation from the untyped world of HTML to the typed world of the database has been at the cfqueryparam tag in the insert or update to the db, setting the value to null if it's an empty string (and the field is nullable). Don't know if that's good or not, but i've found it easier to allow my objects to work in an untyped world until it's time for the data to enter the database.

So then i started thinking that it would be very nice if transfer had a method where i could create a dumb, untyped bean that would accept any value from a form. Then, i could pass that bean to my validation object, and then if it validated, pass that on to the TransferObject to persist it. I'm wondering if that would be a useful enhancement, because then my dumb beans would automatically be updated with any change to the transfer.xml.

But even with a dumb bean, i'm still left with the problem that to a user, a null date is an empty string. And on occasion, it may be that a null numeric would be the same, an empty string. I can of course work around this issue, setting my magic null value on any dates immediately after any transfer.new() calls, looking for that magic value in the form and resetting it to "", creating my own dumb bean to accept the values from the form, looking for "" and resetting it to the magic value, and proceeding from there. But i'm hoping there's an easier way.

And even if null support is implemented in CF, it doesn't mean that this translation problem will go away. HTML forms will still represent null dates as empty strings.

I'm not sure what the specific question is at this point. I could have run across a bug in the nullable mechanism. If not, i might be asking if an enhancement would be possible to more easily reconcile the typeless world of the web with the typed world of databases. The possibility for Transfer to generate dumb beans? An attribute on the object tag to specify whether or not the TransferObject should type it's arguments and returntypes? (Not sure if you would run into problems on the DB end with that?) Something more intelligent?

thanks,
Nando

Sean Corfield

unread,
Jan 3, 2007, 3:23:41 PM1/3/07
to transf...@googlegroups.com
Use a decorator. The decorator overrides the get/set for the date
field and accepts *string* arguments instead. If the decorator set
receives an empty string, call the Transfer object set with the "null"
date value. If the decorator get is given a "null" date from the
Transfer object, return an empty string.

Hope that helps?

Nando

unread,
Jan 3, 2007, 6:39:09 AM1/3/07
to transfer-dev
I'm looking into how transfer handles typing and nullable values, and
am running into a little snafu.

Since any value coming in from an HTML form is a string .. no such
thing as type there, i've been using beans that accept strings for all


values. This allows me to let anything in and validate it once it's in
the bean.

So i tried setting the nullable value for date to "",

<nullValues>
<date value="" />
<boolean value="0" />
</nullValues>

And found out that ColdSpring doesn't like that. So it seems there's a
minor incompatibility there. Here's the error i get:

Bean creation exception during init() of transfer.TransferFactory
"" is an invalid date or time string.

The error occurred in
C:\CFusionMX7\wwwroot\coldspring\beans\DefaultXmlBeanFactory.cfc: line
539
Called from
C:\CFusionMX7\wwwroot\coldspring\beans\DefaultXmlBeanFactory.cfc: line
332
Called from
C:\CFusionMX7\wwwroot\Unity\trunk\ModelGlue\unity\loader\XmlConfigurationLoader.cfc:
line 293

Ok, no problem, let's try something else:

<property name="dateLastFeatured" type="date" nullable="true"
nullvalue="" />

When i use this, ColdSpring doesn't complain, but a new transfer object
defaults to a datetime of now() instead of "", and i get an error if i
try to set the date to "". OK, that's not going to work if i can't set
the null value i've chosen.

So it seems i need to use a magic value of some sort that is a date to


represent null, rather than an empty string. So let's forget about
trying to set a different nullable value and use the default value of
1/1/100.

<property name="dateLastFeatured" type="date" nullable="true" />

Ok, so now when i create a new transferObject, the default date value

is Now(), which is OK, but a little useless from a certain perspective
because i can't easily test if the intention of the user is "null" or
not when they fill out the form.

I think everyone is familiar with this difficulty. In a web form, an
null date is an empty string. There's no other way to represent it to
the user that would make sense to them. Numerics are in a similar


situation, but many times a 0 will do when the intention is "nothing".

This is the main reason i've come to the conclusion that beans that
accept values from web forms shouldn't use typed arguments,
particularly typed date arguments. In the world of HTML, dates are
strings, and if i want to validate a date in this world, i'm looking
for either an empty string or a date. If my bean doesn't accept an
empty string, then it can't accept a valid value for a date from a

form, none.

And then of course on insert or update to the db, I'll use cfqueryparam
to set the value to null if it's an empty string.

So then i started thinking that it would be very nice if transfer had a

method where i could create a dumb bean that would accept any value


from a form. Then, i could pass that bean to my validation object, and
then if it validated, pass that on to the TransferObject to persist it.

I'm still thinking that would be a good enhancement, because then my


dumb beans would automatically be updated with any change to the

transfer.xml. But maybe it's beyond Transfer's scope.

But even with a dumb bean, i'm still left with the problem that to a

user, a null date is an empty string. I can of course work around this


issue, setting my magic null value on any dates immediately after any

transfer.new() call, looking for that magic value in the form and


resetting it to "", creating my own dumb bean to accept the values from
the form, looking for "" and resetting it to the magic value, and
proceeding from there.

But perhaps life would be easier if Transfer would accept an empty
string as a null value for a date?

Or maybe i'm not seeing a better solution to reconcile the typeless
world of the web with the typed world of databases?

thanks,
Nando

Mark Mandel

unread,
Jan 3, 2007, 5:33:53 PM1/3/07
to transf...@googlegroups.com
Nando... stupid question but what is so hard about going -

if(isDate(form.value))
{
obj.setDate(form.value);
}
else
{
obj.setDateNull();
}

?

Or is that too tricky? :oD

But yes - if you want to do it how you just described, with empty
strings, decorators are the key.

Mark

On 1/3/07, Nando <d.n...@gmail.com> wrote:
>


--
E: mark....@gmail.com
W: www.compoundtheory.com

Nando

unread,
Jan 3, 2007, 5:52:19 PM1/3/07
to transf...@googlegroups.com
Hi Mark,

Is there a setDateNull() method in the transferObject? Didn't see that! Tricky indeed, if that is the case.

What about Now() being the default value in the date fields of a new transfer object instead of the null value. Is there a good reason for that?

I can manage in one direction with the above approach, from the form toward Transfer, but in the other direction, from Transfer toward the form, i'd still need to employ the decorator approach in kind of a funky way, looking for Now() or something close or the magic null value and converting it to an empty string.

Can do, but i thought i'd bring this up and see your response.

thanks,
Nando

Nando

unread,
Jan 3, 2007, 5:55:56 PM1/3/07
to transf...@googlegroups.com
That's a good idea. I'll give it a go.

Mark Mandel

unread,
Jan 3, 2007, 6:01:23 PM1/3/07
to transf...@googlegroups.com
If you have a look at:
http://www.compoundtheory.com/transfer/documentation/methods.html#property

You can see the generated methods for handling NULL values.

Now() was just the arbitrary value for Date fields. If you want to
change default values, create a configure() method either in your
decorator, or in the config XML, and set it to whatever value you
wish.

Details on that, can be seen here:
http://www.compoundtheory.com/transfer/documentation/custommethods.html
and
http://www.compoundtheory.com/transfer/documentation/decorators.html

> I can manage in one direction with the above approach, from the form toward
> Transfer, but in the other direction, from Transfer toward the form, i'd
> still need to employ the decorator approach in kind of a funky way, looking
> for Now() or something close or the magic null value and converting it to an
> empty string.

Not sure what you mean here.

Does this solve your problem?

if(obj.getDateIsNull())
{
value = "";
}
else
{
value = obj.getDate();
}


Mark

Nando

unread,
Jan 3, 2007, 6:06:39 PM1/3/07
to transf...@googlegroups.com
Ah ha! i just found this sentence hidden in the docs:

The shorthand way to set the TransferObject's property to the configured NULL value is by calling the 'setproperty[@name]Null()' method on the TransferObject.

So i have a few more tricks to experiment with tomorrow, setMyDateNull() and the decorator idea. Thanks for pointing this out.

Nando

Nando

unread,
Jan 3, 2007, 6:19:54 PM1/3/07
to transf...@googlegroups.com
Ok, i'm pretty sure it will solve with the ability to set the default null. I'll play with it all tomorrow and see where i get. I tried setting it to an empty string like i initially wanted but ran into typing issues. anyway, i'm setting myself to null for the night and transferring myself to bed. it's past midnight here. Thanks for your help.

setNandoNull( ;-)

Sean Corfield

unread,
Jan 3, 2007, 8:08:42 PM1/3/07
to transf...@googlegroups.com
This has been helpful for me too - I didn't realize there were
get{field}IsNull() and set{field}Null() methods!

Mark Mandel

unread,
Jan 3, 2007, 8:12:00 PM1/3/07
to transf...@googlegroups.com
Looks like I should have been clearer in the documentation!

I'll look into it.

Oops.

Mark

Nando

unread,
Jan 4, 2007, 5:47:54 PM1/4/07
to transf...@googlegroups.com
Does this look about right for my decorator? I believe i'm overriding the get/set for the date fields here, at least these methods are named the same. I'm not sure if

<cfset getTransferObject().setDateLastFeatured( arguments.dateLastFeatured) />
and
<cfreturn getTransferObject().getdateLastFeatured() />

are correct. I'm guessing. Couldn't find any documentation to confirm my attempt.


<cfcomponent name="MeditationDecorator" extends=" transfer.com.TransferDecorator">
   
    <cffunction access="public" output="false" name="configure">
        <cfset setDateLastFeaturedNull() />
    </cffunction>
       
    <cffunction name="setDateLastFeatured" output="false" returntype="void">
        <cfargument name="dateLastFeatured" type="any" required="true">
       
        <cfif Len(arguments.dateLastFeatured) EQ 0>
            <cfset setDateLastFeaturedNull() />
        <cfelseif isDate(arguments.dateLastFeatured)>
            <cfset getTransferObject().setDateLastFeatured( arguments.dateLastFeatured) />
        </cfif>
       
    </cffunction>
   
    <cffunction name="getDateLastFeatured" access="public" output="false" returntype="any">
       
        <cfif getDateLastFeaturedIsNull()>
            <cfreturn "" />
        <cfelse>
            <cfreturn getTransferObject().getdateLastFeatured() />
        </cfif>
       
    </cffunction>

</cfcomponent>

thanks much!

Nando

On 1/3/07, Sean Corfield < seanco...@gmail.com> wrote:

Mark Mandel

unread,
Jan 4, 2007, 6:03:25 PM1/4/07
to transf...@googlegroups.com
Nando, that looks good.

When you said;


> are correct. I'm guessing. Couldn't find any documentation to confirm my
> attempt.

Couldn't find documentation on what exactly? On the generated methods?

Just wanted to know where the confusion was so I can either point you
in the right direction, or update the documentation.

Mark

Nando

unread,
Jan 4, 2007, 6:22:57 PM1/4/07
to transf...@googlegroups.com
I couldn't find anything on overriding the generated methods with a decorator. Wasn't sure if i should be using getTransferObject().get/set{prop}(), if that was kosher or even the right way to do this, after my run-in with the get/set memento() methods yesterday. ;-)

Finding out about the set {prop}Null and get{prop}IsNull methods really helped, BTW. Those are great!

Nando

Mark Mandel

unread,
Jan 4, 2007, 6:27:28 PM1/4/07
to transf...@googlegroups.com
No problem.

I'm guessing this section:
http://www.compoundtheory.com/transfer/documentation/decorators.html

Needs to be fleshed out a little more then?

An explanation or example under:
--
If a method exists in the Decorator, it will overwrite the method of
the generated TransferObject's method.
--

Would probably be good, wouldn't it?

Or maybe break up the sections inside the documentation?

Just looking to make the documentation better.

Nando

unread,
Jan 4, 2007, 6:38:18 PM1/4/07
to transf...@googlegroups.com
Yes, that's where i was looking for guidance before and didn't quite find it. All in all i'm very happy with Transfer. Thanks for your effort in building it!

Mark Mandel

unread,
Jan 4, 2007, 6:55:29 PM1/4/07
to transf...@googlegroups.com
I've attached the update to the decorator help page I just commited to SVN.
http://transfer.riaforge.com/index.cfm?event=page.svnhistory&file=decorators%2Ehtml&path=%2Ftrunk%2Ftransfer%2Fdocumentation

Let me know if that explains it a bit better.

decorators.html
Reply all
Reply to author
Forward
0 new messages