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:11:36 PM.)
Tips and tricks from Steve Muench on Oracle ADF Framework and JDeveloper IDE

Search blog with Google:
 

Search BC4J JavaDoc:
 

January 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
Dec   Feb

Get Firefox!

Tuesday, January 13, 2004

Wanted to give folks a heads up that I've been working on migrating the BC4J Toy Store Demo to use our new ADF Binding Layer and new ADF Data Action. The BC4J components are now known as ADF Business Components, but the upgrade required no mandatory changes to the BC4J layer. Even the Struts/BC4J layer would have worked with zero changes in JDeveloper 10g as well, however I want to illustrate the use of the new JSTL support we offer through the ADF Binding layer, and how even less code is required in the controller layer by using our new ADF DataAction. These concepts are described in the Oracle ADF Binding Primer I wrote for OTN. The goal is that I'll release this updated version of the demo and whitepaper together with the production release of JDeveloper 10g. We're still targeting production release in Q1 of calendar 2004.
4:41:29 PM    



The JavaDoc for the findByKey method covers its use with some examples, but in recent interactions with customers using BC4J I've found there was still some confusion on what kind of support exists for finding a row by a "partial key". So I'll try to clarify.

Recall that a view object can be based on zero or more entity object usages.

When a view object is based on at least one entity usage, the findByKey() method finds rows by turning around and doing a findByPrimaryKey() on the entity cache the first non-null entity key. If the primary key of that entity is comprised of multiple attributes, all of those attribute must have a non-null value for the findByPrimaryKey() to find the row.

If a view object is based on a single entity object, the key for each view object row will be comprised of the underlying entity object's key attribute(s). The "Key Attribute" property for the view object attributes corresponding to these underlying entity object primary key attributes will be set to "true" and the checkbox will be disabled because you cannot unselect them.

The corollary of the above two paragraphs is that when you perform a findByKey() on a view object with a single entity object usage, you must provide an oracle.jbo.Key object which has non-null values for all of the attributes in the view row key.

If a view object is based on N entity usages, where N > 1,  then the view row key is by default comprised of all of the primary key attributes from all of the participating entity usages. Only the ones from the first entity object are required to participate in the view row key, but by default all of them do.

If you allow the key attributes from some second or subsequent entity usage to remain "Key Attributes" at the view row level, then you should leave all of the attributes that form the primary key for that entity object as part of the view row key. Assuming you have left the one or more key attributes in the view row for M of the N entity usages, where (M <= N) then you can use findByKey() to find rows based on any subset of these M entity "bases", but for each entity base for which you provide values in the Key object, you must provide non-null values for all of the attributes in that entity's primary key.

As a concrete example, imagine that you have a view object Employees with an Emp entity as its primary entity usage, and a Dept entity as secondary (by reference) entity usage. Furthermore, assume that you leave the Empno attribute (primary key for the Emp entity) and the DeptDeptno view row attribute (mapped to the Dept entitiy's Deptno attribute which is its primary key) as "Key Attributes" in the Employees view object.

The view row key will therefore be the (Empno, DeptDeptno) combination.

When you do a findByKey(), you can provide a Key object that provides:

  • A completely specified key for the underlying Emp entity -- which in this case means providing a value for the Empno attribute in the Key object passed to findByKey()
  • A completely specified key for the underlying Dept entity -- in this case, this means a value for the DeptDeptno attribute in the Key object passed to findByKey()
  • A completely specified key for both underlying Emp and Dept entities.

Assuming that we've imported oracle.jbo.domain.Number into our class, we would create an example of each key combination above like this:

  • Key k = new Key(new Object[]{new Number(7839), null});
    /* Val for Emp EO part of view row key */

    This would find the row with employee id 7839, regardless of department she works in.
  • Key k = new Key(new Object[]{null, new Number(10)});
    /* Value for Dept EO part of view row key */


    This would find the row(s) with employees in deparment number 10.
  • Key k = new Key(new Object[]{new Number(7839), new Number(10)});
    /* Value for both */

    This would find the row with employee 7839 in department 10 only.

If a view object is based on zero entity usages, then it's view row key is determined by the ordered set of view attributes that have the "Key Attribute" property checked on/true. Alternatively, this set of one or more key attributes can be provided programmatically through the call to setKeyAttributeDefs() in your ViewObjectImpl subclass.

A findByKey() performed on a view object with no entity usage, must be done using the complete key for the view row, so no partial searching is possible. Also, in order to enable the findByKey() to work at all for such a view object, the method setManageRowsByKey(true) must be called from the create() method of your view object implementation class.


4:32:42 PM    


Over the holidays we republished the JDeveloper documentation and JavaDoc in a format that was more Google-friendly. I've added an extra search box to the "Dive Into BC4J" homepage that lets you type in a search term that you want to find in the JDeveloper documentation and it shows you Google's results.

It takes advantage of the Google query terms inurl:jdeveloper and site:oracle.com to narrow your search under the covers to just the oracle.com site where jdeveloper appears in the URL.


3:34:47 PM    


Laszlo writes in to ask, "We would like to change the View Attribute Updateable property at runtime. Is this possible and if so, how?"

By design, the client cannot programmatically set this property, which explains why there is no setUpdatableFlag() method in the oracle.jbo.ViewObject interface used by clients. However, code contained in your BC4J components' implementation classes have full access to set it. Here's one way to achieve this functionality by adding a custom method to your appliation module implementation class.

Suppose my application module is named test.MyService. I can add a method like the following to the test.MyServiceImpl class:

  public void setAttrUpdatability(ViewObject vo, String attrName, byte flag) {
    AttributeDefImpl def = (AttributeDefImpl)vo.lookupAttributeDef(attrName);
    if (def != null) {
      def.setUpdateableFlag(flag);
    }
  }

Then, I can use the application module editor to shuttle the setAttrUpdatability method into the list of methods that will be accessible to clients on my custom application module interface. You do this on the Client Methods panel of the editor.

This results in the creation (or update) of the test.common.MyService interface, which extends the oracle.jbo.ApplicationModule interface and contains the extra custom methods that you've exposed for this particular application module.

Finally, your client code can then cast its application module to this custom MyService interface and call our new setAttributeUpdatability() method to accomplish the job. A sample client that illustrates this method in use might look like this:

package test;
import oracle.jbo.*;
import oracle.jbo.ReadOnlyAttrException;
import oracle.jbo.client.Configuration;
import test.common.MyService;
public class TestClient {
  public static void main(String[] args) {
    String        amDef = "test.MyService";
    String        config = "MyServiceLocal";
    MyService am = (MyService)
    Configuration.createRootApplicationModule(amDef,config);
    ViewObject vo = am.findViewObject("DeptView");
    Row r = vo.first();
    String valueBefore = (String)r.getAttribute("Dname");
    r.setAttribute("Dname","XXXX");
    System.out.println("Set attribute succeeded");
    am.setAttrUpdatability(vo,"Dname",AttributeDef.READONLY);
    try {
      r.setAttribute("Dname","XXXX");
      System.out.println("Set attribute succeeded");       
    }
    catch (ReadOnlyAttrException ex) {
      System.out.println("Attribute is read only.");
    }
    am.setAttrUpdatability(vo,"Dname",AttributeDef.UPDATEABLE);
    r.setAttribute("Dname",valueBefore);
    System.out.println("Set attribute succeeded again");   
    am.getTransaction().rollback();
    Configuration.releaseRootApplicationModule(am,true);
  }
}

The output of this sample illustrates that at first the attribute is updateable, then it's not, then it is again.


1:56:47 PM    


© Copyright 2008 Steve Muench.