Dive into Oracle ADF

Send me a mail
 Dive into Oracle ADF   Click to see the XML version of this web page.   (Updated: 2/3/2008; 9:14:40 PM.)
Tips and tricks from Steve Muench on Oracle ADF Framework and JDeveloper IDE

Search blog with Google:
 

Search BC4J JavaDoc:
 

October 2004
Sun Mon Tue Wed Thu Fri Sat
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Sep   Nov

Get Firefox!

Thursday, October 07, 2004

The ADF Toy Store Demo comes with a suite of JUnit tests to illustrate how to regression test an ADF application based on ADF Business Components. A customer reported to me today that the CreateAnOrderTest was failing. I actually noticed this in my own environment recently and didn't understand what had changed. The testing code sure hadn't. I downloaded the version again from OTN to make sure the problem wasn't related to my in-progress 10.1.2 version of the demo, and darnnit, that test failed in the same way. That hadn't happened before. What had changed?!

By setting an exception breakpoint for oracle.jbo.JboException and debugging the JUnit tests, I noticed that the credit card expiration date validation was failing, and sure enough, the CreateAnOrderTest has in it a test for a credit card that expires in 10/2004.

What had changed was not the code, but the calendar!

By changing the test to supply a year beyond 2004 (or any month/year combination in the future) the test succeeds as expected. I've bumped the test to 2008 in the 10.1.2 ToyStore version I'm working on this week.


10:52:57 PM    



It's been an awfully long time since I ran into a problem that turned out to a bug with the Oracle database itself. The database has evolved to become so rock-solid that it's a pretty rare event for me, although I'm constantly banging on it in my daily tasks to help customers make effective use of JDeveloper and our ADF framework. In fact, checking our internal bug database, the last database bug I filed was in June of 1997.

But yesterday I was looking into a user Fred's claim that ADF Business Components was mishandling TIMESTAMP-valued attributes using our Refresh-on-Insert or Refresh-on-Update feature.These are simple attribute properties that you set on those entity object attributes that you know will be updated by database-level application logic (like a BEFORE INSERT FOR EACH ROW or BEFORE UPDATE FOR EACH ROW trigger, for example). Fred had a CREATED_ON and MODIFIED_ON column of type TIMESTAMP whose values he was managing using database triggers. He decided against using the ADF entity object's built-in "history attributes" management -- where he could have indicated declaratively that he wanted ADF to manage the values of certain entity object attributes to remember things like CreatedBy, CreatedOn, ModifiedBy, or ModifiedOn -- since he had some other non-Java client applications modifying those same tables. So, for example, his FRED_TABLE had a trigger like this:

CREATE TRIGGER maintain_modified_by BEFORE UPDATE ON fred_table FOR EACH ROW
BEGIN
  :new.modified_on := SYSTIMESTAMP;
END;

Trouble is, after updating some data in his Fred entity and committing, the value of the ModifiedOn attribute was getting corrupted into some very weird-looking timestamp value. With a little bit of good ol' simplifying, I was able to reproduce the problem using only a simple SQL statement like this:

UPDATE fred_table
SET some_column = 'new value'
WHERE id = 1
RETURNING modified_on INTO :sqlplus_var;

ADF Business Components by default uses Oracle's RETURNING INTO clause to retrieve the Refresh-on-Insert and Refresh-on-Update attribute values without having to perform two round-trips to the database. It turns out that the particular combination of:

  • Updating a TIMESTAMP column with a BEFORE [INSERT | UPDATE] FOR EACH ROW trigger, and
  • Retrieving this newly assigned TIMESTAMP value using the RETURNING INTO clause

Was a recipe for somehow corrupting the value of the TIMESTAMP data. In fact, after performing my test SQL above, a simple:

SELECT modfied_on FROM fred_table WHERE id = 1

was giving me an ORA-1877 error, "String too long for buffer". So, I filed a bug to get the issue fixed in the database, and then explained to Fred how he could work around the problem by indicating that his entity should not use the RETURNING INTO clause.

The way to do this is:

  1. Add a custom EntityDefImpl class for your entity object on the "Java" panel of the EO Editor
  2. Override the method like this to return false:
      // In your custom YourEntityDefImpl.java class
      public boolean isUseReturningClause() { return false; }

That keeps the database-maintained timestamp values happy.

 


5:51:41 PM    


© Copyright 2008 Steve Muench.