You are here: Home ยป Blog

Programmatically iterating a RowSet

Posted on Thursday, July 24 2014 at 16:54 | Category: Oracle ADF & JDeveloper | 0 Comment(s)

I have some tool method which I have been using to dump the contents of a RowSet, especially for debugging and testing purposes. At the core, the method looks like this:

void listRowSet(RowSet rowSet) {
    while(rowSet.hasNext()) {
        Row row = rowSet.next();

        // ... dump the contents of the current row
    }
}

and the result looks similar to this, dumping all the attributes in each row:

CId        | CCreated              | CLastupdated          
-----------------------------------------------------------
0          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 
1          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 
2          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 

Now, in a larger application, I was using the RowSet at several places, and I thought it would be a good idea to have the method always start at the first entry, and not rely on the fact that the iterator is already at the beginning when calling the method. This is what the RowIterator.reset() method is for. So, that seems to be easy:

void listRowSet(RowSet rowSet) {
    rowSet.reset();
    while(rowSet.hasNext()) {
        Row row = rowSet.next();

        // ... dump the contents of the current row
    }
}

Now, the result looks like this:

CId        | CCreated              | CLastupdated          
-----------------------------------------------------------
1          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 
2          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 

Ehmmm... Wait ... Something's wrong here ... I have reset the iterator, but now the first row is missing? What is going on?

Lets review the documentation of RowIterator.reset():

After this method, the current slot status will be SLOT_BEFORE_FIRST [...]

Alright, I know that concept from JDBC - there, the method is called beforeFirst(), and subsequent calls to next() move the cursor to the next row, which is the first one when next() is called for the first time.

So, what is wrong here? Lets see - there is some additional information in the Javadoc:


...  except in cases where this iterator is associated to an iterator binding in an ADF
 application which sets the currency to the first row in the iterator if available.

Naturally, I skipped that part when I first looked up the documentation - but it looks like this is an important detail!

On a side note, the next sentence in the Javadoc says

A subsequent invocation of next() will cause the first row to become the current row.

which is confusing, since this is exactly not the case when "this iterator is associated to an iterator binding in an ADF application which sets the currency to the first row in the iterator if available.".

Now that I know the problem, a quick search showed up a nice posting from Michael Koniotakis: Iterating through View Object RowIterator Bug.(NOT ADF BUG, Development Bug), and the suggestion is to use a secondary row iterator whenever iterating through a RowSet programmatically:


void listRowSet(ViewObject vo) {
    RowSetIterator iter = vo.createRowSetIterator(null); 
    while(iter.hasNext()) {
        Row row = iter.next();

        // ... dump the contents of the current row
    }
    iter.closeRowSetIterator();
}

With that, I now get all rows again, starting at the first row:

CId        | CCreated              | CLastupdated          
-----------------------------------------------------------
0          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 
1          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 
2          | 2014-07-04 13:16:46.0 | 2014-07-04 13:16:46.0 

Instead of the ViewObject, we can also use a RowSet to create the new iterator (remember that a ViewObject is a RowSet), so that the method signature can remain unchanged:


void listRowSet(RowSet rowSet) {
    RowSetIterator iter = rowSet.createRowSetIterator(null); 
    while(iter.hasNext()) {
        Row row = iter.next();

        // ... dump the contents of the current row
    }
    iter.closeRowSetIterator();
}

Returning values from a bash function

Posted on Thursday, July 10 2014 at 16:09 | Category: Linux | 0 Comment(s)

bash does not provide a return statement to return custom values from a function. The return statement is only used to return a numeric status code to the calling function which can be retrieved with $?.

Long story made short, use a recent bash version (>= 4.3) and use the declare -n statement to declare a reference to the variable where the result will be stored, and pass the name of this variable as a parameter to the function:


#!/bin/bash

someFunction() {
    declare -n __resultVar=$1
    local someValue="Hello World"

    # The next statement assigns the value of the local variable to the variable
    # passed as parameter
    __resultVar=${someValue}
}

# call the function and pass the name of the result variable
someFunction theResult
echo ${theResult}

Name service request caching with nscd

Posted on Monday, July 07 2014 at 17:08 | Category: Linux | 0 Comment(s)

Sometimes it is still easiest (especially when there is only a command line terminal available) to directly edit files like /etc/passwd, /etc/hosts etc. with a plain text editor. When I today just wanted to change the login shell of a user on an Oracle Enterprise Linux installation, I simply changed /bin/csh to /bin/bash for the corresponding entry in /etc/passwd.

However, the surprise was that the new entry was not considered when re-logging in. This is where nscd comes into play. From the man page:

NSCD(8)                    Linux Programmer's Manual                   NSCD(8)

NAME
       /usr/sbin/nscd - name service cache daemon

DESCRIPTION
       Nscd  is a daemon that provides a cache for the most common name service requests.  ...

Among those most common name service requests are lookups into the /etc/hosts, /etc/group and /etc/hosts files.

Actually the nscd daemon also watches the respective files for changes, but it might take several minutes until it picks up the modified files.To clear the nscd cache immediately, simply call nscd with the -i switch and the name of the lookup database which needs to be reloaded:

$ /usr/sbin/nscd -i passwd

By the way, stopping and re-starting the nscd daemon through /etc/init.d/nscd is not enough - the daemon still remembers its cached entries afterwards.


Some background on optimistic locking in ADF

Posted on Tuesday, July 01 2014 at 14:44 | Category: Oracle ADF & JDeveloper | 0 Comment(s)

Configuring optimistic locking

ADFbc can be configured with different locking modes, in particular pessimistic and optimistic locking. Since pessimistic locking might create pending row-level locks on the database, the general recommendation is to use optimistic locking for web applications, to achieve a good performance. For more information, see Fusion Application Developers Guide, 40.11 Keeping Pending Changes in the Middle Tier.

To configure optimistic locking, either set the jbo.locking.mode property of your application module configuration to "optimistic" or configure the locking mode globally in .adf/META-INF/adf-config.xml:


...
<amconfig-overrides>
  <config:Database jbo.locking.mode="optimistic"/>
</amconfig-overrides>
...

If configured, the setting from adf-config.xml takes precedence over the application module property.

Detecting lost updates

With optimistic locking, when more than one user is working on the same set of data, it can happen that the same attribute is modified by more than one user at the same time. When the first user commits his transaction, the updated value is written back to the database - other users would never see these (probably important) modifications, and when the next user also commits the transaction, his modifications would be written back to the database, overwriting the modifications from the first user. This phenomenon is also known as "lost update". ADF has the ability to detect attempts to update data which has been modified in parallel. When the data is committed (e.g. by executing the "commit" action on the application module), ADF performs the following actions:

1. The row is locked on the database by executing an SELECT ... FOR UPDATE NOWAIT query, like

SELECT DATA, ID   
FROM SIMPLE SimpleEO   
WHERE ID=:1   
FOR UPDATE NOWAIT

2. ADF then compares the values selected through this query against the current values stored in the entity object. If any of the attribute values have changed, ADF will display an error dialog:

Improving performance by using a change indicator

Comparing all attributes in the EO in step 2 above can be time consuming, especially if the EO contains many attributes. To improve the performance, it is possible to define one of the attributes as a change indicator:

 

NOTE:
In several books, it says "one or more attributes can be selected as change indicator" - however, at least with JDeveloper 11.1.1.7, only one attribute of an EO can be selected as change indicator. If setting the flag on one attribute, JDeveloper automatically resets the flag on the other attribute where it has previously been set. This is also consistent with the Javadoc, where it says
"This method uses the ChangeIndicator attribute, if it is present, for the comparison. If ChangeIndicator is not present, then this method compares the data for overlapping columns between the entity and the given array."

When a change indicator is defined on the EO, the framework only performs the comparison for the attribute marked as such, instead of for every entity attribute. Note however that the SQL statement still queries all attributes!

An important detail is that the change indicator attribute needs to be a system field which is automatically updated in the background whenever the row in the database is modified, for example through an ON UPDATE database trigger. Do not use an attribute which can be edited by the user - otherwise, ADF assumes that the record has been modified by another user even though that is not the case. This check is not done when committing the data, but already when changing the attribute value (means, when calling the setAttribute() method on the EO). This might result in the following error message on the ADF rich client UI (note the different representation as a popup window, not as a dialog like above):

 

See also this article from Chris Muir for more information on optimistic locking: The case of the phantom ADF developer (and other yarns)


Displaying results 1 to 4 out of 82
<< First < Previous 1-4 5-8 9-12 13-16 17-20 21-24 25-28 Next > Last >>