commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching <>
Subject Re: [Digester] Handling Null values
Date Tue, 23 Nov 2004 21:01:45 GMT
On Wed, 2004-11-24 at 03:38, Mike Zatko wrote:
> Simon Kitching wrote:
> >On Tue, 2004-11-23 at 07:06, Mike Zatko wrote:
> >  
> >
> >>I am trying to parse a document which has a Timestamp element which may 
> >>or may not be null. Does anyone know how to setup the addCallMethod to 
> >>handle this situation?
> >>
> >>The one i've tried is as follows:
> >>
> >>digester.addCallMethod(root + orderClass + 
> >>"/payments/payment/expiration-date", "setExpirationDate", 0, new 
> >>String[] {"java.sql.Timestamp"});
> >>    
> >>
> >
> >In most cases, if you call a method and the parameter data is not
> >present in the input, then null is passed to the target method.
> >
> >According to the javadoc for the ConvertUtils class in the BeanUtils
> >library,  String->java.sql.Timestamp is a supported conversion, so
> >things should just work.

> Ok, this is the full run log... it's long. I can see that its using the SqlTimestampConverter
which should handle a null value. But, apparently it does not? Any advice appreciated.


> 468 [main] DEBUG org.apache.commons.digester.Digester  -   Fire begin() for CallMethodRule[methodName=setCreateDate,
paramCount=0, paramTypes={java.sql.Timestamp}]
> 468 [main] DEBUG org.apache.commons.digester.Digester.sax  - endElement(,,create-date)
> 468 [main] DEBUG org.apache.commons.digester.Digester  -   match='com.boscovs.translator.dto.fulfillment.Comment/create-date'
> 468 [main] DEBUG org.apache.commons.digester.Digester  -   bodyText=''
> 468 [main] DEBUG org.apache.commons.digester.Digester  -   Fire body() for CallMethodRule[methodName=setCreateDate,
paramCount=0, paramTypes={java.sql.Timestamp}]
> 468 [main] DEBUG org.apache.commons.digester.Digester  -   Popping body text '
>     '
> 468 [main] DEBUG org.apache.commons.digester.Digester  -   Fire end() for CallMethodRule[methodName=setCreateDate,
paramCount=0, paramTypes={java.sql.Timestamp}]
> 468 [main] DEBUG org.apache.commons.beanutils.ConvertUtils  - Convert string '' to class
> 468 [main] DEBUG org.apache.commons.beanutils.ConvertUtils  -   Using converter org.apache.commons.beanutils.converters.SqlTimestampConverter@14c1103
> 484 [main] ERROR org.apache.commons.digester.Digester  - End event threw exception
> org.apache.commons.beanutils.ConversionException: Timestamp format must be yyyy-mm-dd

Ok, the problem is that it is the *body* of the xml element that is
being converted to an SqlTimestamp. 

If it were an *attribute* that was being passed, and the attribute were
not present then 'null' would be passed to the converter, and presumably
null would be the return value, which would then be passed to the setter
method on the target object.

But because it's the *body*, and the element is empty, an *empty string*
is being passed to the converter, not null, and an empty string cannot
be converted to a timestamp.

This also would occur if it were an *attribute* being converted to a
timestamp, and it were defined to be an empty string, eg <item
time=""/>. However it would be a little more obvious why the failure is

It's an interesting question as to whether Digester should regard the
body of <element/> as being NULL or an empty string. Maybe this should
be an option on CallMethodRule and CallParamRule.

Personally, I think the xml input is not well designed; if there is no
timestamp information, then the xml element providing timestamp info
should not be present, rather than being present with an empty body.
However I understand that these things are not always under the control
of the person *parsing* the xml...

I suggest the following. Of course these are only initial thoughts; no
guarantee any of these will work...

option 1: Register your own converter to SqlTimestamp using the
ConvertUtils class in the BeanUtils library, and have this converter
return null when passed an empty string. It could be a simple wrapper
around the existing class, or subclass of it, etc.

option 2: Create a custom Rule class to deal with the timestamp input
element, rather than using CallMethodRule. It should be *much* simpler
than CallMethodRule, ie just start from scratch rather than
copying/subclassing CallMethodRule. All you should need to do is
implement the body() method...

option 3: If you're feeling enthusiastic, you could consider adding a
feature to CallMethodRule/CallParamRule that allows the user to specify
whether an empty body should be treated as a null value or an empty
string. I haven't thought deeply about it, but I would expect this to
have a reasonable chance of being added to the digester core



To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message