Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / JavaBeans / May 2004

Tip: Looking for answers? Try searching our database.

null return values for property getters for primitive types?

Thread view: 
Robert Klemme - 30 Apr 2004 17:19 GMT
Hi all,

I'm remotely trying to debug a customer problem.  The scenario is,
primitive type (int and double) properties are read via reflection and
then stored in the database.

Strangely enough, there are NULL's in the database which - as far as I can
see at the moment - can only happen, if the property reader method returns
null for such a property.  Now the million dollar question:

Can anybody imagine circumstances that lead to such behavior?

From documentation and all common sense it seems impossible, yet it might
be since the java.lang.reflect.Method.invoke() has return value Object.

I've done a test that uses unsynchronized reads via Method.invoke() in
order to figure whether there might be a thread related problem but to no
avail.

Any ideas?

Puzzled

   robert
Thilo Schmalfuss - 06 May 2004 21:26 GMT
> Can anybody imagine circumstances that lead to such behavior?

Could you post some code? The only case i can imagine is of a caught
exception. something like this :

Object returnValue = null;

try {

   returnValue = method.invoke(bean, null);

}
catch(Exception anException) { // unhandled ... }

But I think you would have mention this.

regards
thilo
Robert Klemme - 07 May 2004 09:56 GMT
> > Can anybody imagine circumstances that lead to such behavior?
>
> Could you post some code?

Hm, not the complete thing but here's the method that does the writing:

protected void writeProperty(PreparedStatement ps, int id, Object bean,
PropertyDescriptor pd) throws
   IllegalAccessException,
   InvocationTargetException,
   SQLException,
   InstantiationException {
   final String propertyName = pd.getName();
   Method reader = pd.getReadMethod();

   Object value = reader.invoke(bean, BeanPersister.EMPTY_ARRAY);

   Class propertyType = pd.getPropertyType();

   final boolean orderingProperties = isOrderingProperties();

   if (Collection.class.isAssignableFrom(propertyType)) {
       /*
        *  assume association to other bean OR id collection
        */
       final boolean isIdCollection = isIdCollectionProperty(pd);

       Iterator valueIter = ((Collection)value).iterator();
       int count = 0;

       while (valueIter.hasNext()) {
           Object element = valueIter.next();

           if (element != null) {
               Object elementToSet = isIdCollection
                   // write the id directly if it is an id collection
                   ? element
                   // otherwise use the element's id
                   : reverseLookup(element);

               ps.setInt(1, id);
               ps.setString(2, propertyName);

               ps.setString(3, (elementToSet == null
                                ? element
                                : elementToSet).toString());

               if (orderingProperties) {
                   ps.setInt(4, count);
                   ++count;
               }

               ps.executeUpdate();
           }
       }
   }
   else {
       // standard types
       ps.setInt(1, id);
       ps.setString(2, propertyName);

       if (value == null) {
           ps.setNull(3, Types.VARCHAR);
       }
       else {
           // convert non null values
           PropertyEditor pe = getPropertyEditor(pd);

           ps.setString(3,
                        pe == null
                        // default conversion
                        ? value.toString()
                        // use editor
                        : convertPropertyValueToString(value, pe));
       }

       if (orderingProperties) {
           ps.setInt(4, 0);
       }

       ps.executeUpdate();
   }
}

> The only case i can imagine is of a caught
> exception. something like this :
[quoted text clipped - 9 lines]
>
> But I think you would have mention this.

I can assure you that I don't write such code.

Thanks for replying anyway.  Apparently nobody can image how this can come
about. *sigh*  We have to believe customers that they didn't fiddle with
the database, yet this is the only explanation I have at the moment.

Regards

   robert
rpnman - 17 May 2004 01:38 GMT
No there is no way a primitive can hold a null value, and there's only one
way a Method.invoke() can return a null. From the documentation on Method:

"If the underlying method return type is void, the invocation returns null."

A reflection from a primitive method returns an object or throws an
exception. So, as I figure things, when your invoke returns a non-collection
object, your if (value == null) clause should never  be triggered unless
your passed PropertyDescriptor returns a handle to a nonbean property method
which is of type void. That would be very difficult to do, even if it is
possible. A good design should preclude even the remotest possibility, but I
can't say based on the code you posted.

One possible source of the "null" might be your
convertPropertyValueToString(...) method, which is also not given in your
posting.

Another more obscure possibility arises because the code just re-throws the
exception instead of checking it around the invoke method. That way you
leave yourself vulnerable to the handling further down the call stack where
less is known about what to do. I generally find that at least some
Reflection exceptions are screened out and handled at the method call or
rethrown as NestableRuntimeExceptions because they're extremely rare or
impossible (based on the design) and/or because there's nothing to do about
them in any case.

If the null field is part of an object that is already instantiated and on
the way to the database, then an exception here (e.g. at the invoke()) would
leave it null and it might be persisted elsewhere.

An aside: in the collection handling part of the if (Collection...) clause,
you have an "if (!element != null) clause without an else clause. Is
ignoring null collection members really what you intend?

In the debugger, you should trap a "null" string at the update() and a null
value, and see what else you can learn about the circumstances.

Signature

ROGER NEYMAN

> > > Can anybody imagine circumstances that lead to such behavior?
> >
[quoted text clipped - 103 lines]
>
>     robert
Robert Klemme - 17 May 2004 09:36 GMT
> No there is no way a primitive can hold a null value,

Well, *that's* for sure. :-)

> and there's only one
> way a Method.invoke() can return a null. From the documentation on Method:
[quoted text clipped - 6 lines]
> your passed PropertyDescriptor returns a handle to a nonbean property method
> which is of type void.

... or the member is not a primitive type and it's null.  Not the case for
that scenario we're investigating.

> That would be very difficult to do, even if it is
> possible. A good design should preclude even the remotest possibility, but I
> can't say based on the code you posted.

Since I use only standard mechanims to get at the PropertyDescriptors I
think we can rule that out.

> One possible source of the "null" might be your
> convertPropertyValueToString(...) method, which is also not given in your
> posting.

It's handled via a special PropertyEditor for primitive type wrappers
(java.lang.Integer and the like) that either converts to a legal string or
throws.  So there should be no 'null's returned here either because the
conversion is only triggered for non null values.

> Another more obscure possibility arises because the code just re-throws the
> exception instead of checking it around the invoke method.

Where did you see the re-throw?  Exceptions are just thrown and not caught
by this method.  But they are caught and rethrown as another exception
type in the invoking method.

> That way you
> leave yourself vulnerable to the handling further down the call stack where
> less is known about what to do.

It's still handled in the same instance, so all is fine.

> I generally find that at least some
> Reflection exceptions are screened out and handled at the method call or
> rethrown as NestableRuntimeExceptions because they're extremely rare or
> impossible (based on the design) and/or because there's nothing to do about
> them in any case.

Yes, that's done even further up the call stack.

> If the null field is part of an object that is already instantiated and on
> the way to the database, then an exception here (e.g. at the invoke()) would
> leave it null and it might be persisted elsewhere.

No, this is the only place that does the persisting.  It's a general
mechanism so it would make no sense to have other code that duplicates
this functionality.  Apart from that the 'value' is a local variable, so
the value is lost in case of an exception any way.

> An aside: in the collection handling part of the if (Collection...) clause,
> you have an "if (!element != null) clause without an else clause. Is
> ignoring null collection members really what you intend?

Yes.

> In the debugger, you should trap a "null" string at the update() and a null
> value, and see what else you can learn about the circumstances.

Done - to no avail. :-(  I'm still suspecting that someone was fiddling
with the database, although I can't prove it.  This seems the only way to
me that these NULL's could have shown up in that table.

Thank you very much for your time!

Kind regards

   robert


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.