gravatar

Does every master entity row has a seperate RowSet object

Yes every master entity row has a seperate RowSet object containing all its child rows...

Let us take the Department and Employee tables...Assume that the primary key of the department table is the "DepartmentName" and not the "DepartmentId"... Let us say that there is an association between the Department entity and the Employee entity based on the "DepartmentId" attribute, so that the Department entity is the master and the Employee entity is the child..

So for every department row, there should be a RowSet using which all the associated Employee's can be found...

Even if there are two deparment rows having the same "DepartmentId" values, each row will have a seperate RowSet object...but both the RowSet objects will be pointing to the same iterator...

So if multiple master rows have the same source attribute value , then ADF bc is clever enough to fetch all the rows from the middle tier instead of firing queries to the database to fetch the child rows...

This is true even if the association accessors are retained.

Does this mean anything?

This information is given just to explain that ADFbc is good at deciding when it has to go to database and whether it can fetch all the necessary information from the middle tier

gravatar

Retaining Association accessor

In BC4J its easy to create a parent-child relationships between entity objects. This is done using the entity association objects.

Every time when an entity association accessor is accessed, ADF bc by default creates a new RowSet object containing all the child rows associated to the current parent entity object. This does not mean that an sql query will be re-executed to fetch all the child rows . This only means that a new instance of a RowSet object will be created with its default iterator reset to the "slot" before the first row. To force the row set to refresh its rows from the database, executeQuery() method has to be called.

Since there is a small amount of overhead associated with creating the row set, if your code makes numerous calls to the same association accessor attributes, you can consider enabling the association accessor row set retention for the source entity object in the association. You can enable retention of the association accessor row set using the overview editor for the entity object that is the source for the association accessor. Select Retain Association Accessor Row Set in the Tuning section of the General page of the overview editor for the entity object.


When this feature is enabled for an entity object, since the association accessor row set is not recreated each time, the current row of the RowSet object is also retained as a side-effect. This means that inorder to reset the currency of the row set , the "reset" method has to be called on the row set object. A failure to call reset() each time before the rowset is iterated, can result in hard-to-detect error in your application.

So the best way to iterate through the rows is to have code as follows..

RowSet rs=.....

rs.reset();

while(rs.hasNext()){
Row row=rs.next();
}
So irrespective of whether the association accessor is retained or not, this code will help to scroll through all the rows of the row set...

The method "rs.hasNext()" might fire an sql query , if its the first time the row set is being called. So only the first time a rowset is being scrolled, the framework fires an SQL query and populates the row set..In other cases, the method "hasNext()" will just check if there is any row in the entity cache or not....

If you always want to access all the rows that have been created in the middle tier as well as all the rows from the database use the following piece of code..

RowSet rs=.....

rs.executeQuery();

while(rs.hasNext()){
Row row=rs.next();
}

This code works irrespecitive of whether the association accessors are retained or not...This code will fetch all the new rows from the middle tier and all the rows (even the new rows commited to the database from backend ) from the database...

Programmatically setting the association accessor retention

To programmatically set the association accessor retention do the following..

Generate the Entity Collection class...In this class, there should be a method like "init()"...In this method, after the line "super.init();" call the method "setAssociationAccessorRetained(true)", by passing "true" as parameter...

gravatar

Accessing the current locale context

In BC4J , every application module is associated to a locale context object. To access the locale context object associated to the application module use the code snippet given below.

ApplicationModule am=.....
am.getSession().getLocaleContext();

gravatar

Accessing Custom Propeties of Entities

BC4J allows custom properties to be associated to each entity/view object. This can be done declaratively using the overview editor of each object.

To access the value of a custom property (either translated one or the non-translated one), use the following piece of code..

Accessing the custom property value from an entity class

this.getEntityDef().getProperty("propertyName");

The "propertyName" is the name of the property whose value is needed. The property can also be a translatable property. If the property is a translatable property, the above piece of code will fetch the translated value of the LocaleContext associated to the session of the application module..

If the translated value of some other LocaleContext is required then use the following piece of code.

this.getEntityDef().getProperty("propertyName", localeContextObject);

where "localeContextObject" is a java object of type oracle.jbo.LocaleContext.

Accessing the custom property value in viewobject class

In the Impl class just use the method "getProperty"..This takes the same parameters as explained above..

gravatar

Alternate Keys of Entities

All database tables related to functional products, generally have a primary key. In many cases there will be alteast one surrogate key (also called the Alternate key or the Unique key) for each table.

For example , if Employee table is considered, generally "employeeId" will be the primary key. But there can be other columns like "employeeEmail" which has to be unique for each and every employee. Even though this restriction may not be present in the database (i.e database constraint may not be present), functionally it may be required to implement the unique constraint in the middle tier.

BC4J allows you to setup such unique constriants for each entity. This can be done using the Alternate Keys feature.

Using this feature, a set of attributes (of the entity) can be marked to form on alternate keys. Every entity can have more than one alternate key.

So when should alternate keys be created? And what are the advantages of using alternate keys? The following are some of the advantages of using alternate keys.

  1. Business functionality might require a unique key constraint on a set of attributes, and the unique key constraint may not be present at the database level. Then the requirement can be satisfied creating alternate keys. (NOTE: Alternate keys can be created even if there are database constraints)..
  2. Alternate keys are useful for direct row lookups via the "findByAltKey" of the Entity definition.
  3. When alternate keys are created, it becomes easy to check that all entities have unique values for the set of attributes marked as alternate key. Declarative validators can be used to perform this check and to provide appropriate error message. (Even if there are no declarative validators, BC4J framework by default checks whether multiple rows have the same alternate key or not. If its the case, it simply throws an error, which cannot be handled programmatically.)
Primary Key attributes and Alternate Key attributes

The difference between the primary key attributes and the alternate key attributes is that, primary key attributes cannot be null and the alternate key attributes can be null.

Usage of findByAltKey method

The following is a code snippet showing how to find a row(s) using the "findByAltKey"...

Using the "findByAltKey" method from the Entity class
getEntityDef().findByAltKey(this.getDBTransaction(),"alternateKeyName",new Key(new Object[]{"",""}), false,false);
The findByAltKey in the Entity class takes 5 parameters.
  1. The current database transaction.
  2. The name of the alternate key.
  3. The Key object
  4. A boolean value which represents, whether the sub classes (inherited classes) have to be searched or not.
  5. Another boolean value which represents whether to hit the database if no row is found in the entity cache.
Using the "findByAltKey" method from the ViewObject class
findByAltKey("alternateKeyName",new Key(new Object[]{"",""}),true);
The findByAltKey in the ViewObject class takes 3 parameters
  1. The name of the alternate key
  2. The Key object
  3. A boolean value which represents a flag that controls whether, when a db query is issued to get the matching row(s), the view object's current where-clause is to be included in the query or not.

gravatar

font-size

font-size is always inherited by default, i.e every html element gets the font-size of the parent element... The following link from W3C site confirms this..
http://www.w3.org/TR/CSS2/propidx.html

font-size relative values are always relative to the font-size of the parent element.
http://www.w3.org/TR/CSS2/fonts.html#value-def-relative-size

If no font-size is specified then the default font size specified by the browser is considered(and this value can be changed by the end user)...

So setting the font-size to relative units should not cause any problems interms of accessiblity or cross browser compatability.

gravatar

Making an Entity Readonly

In BC4J all the entities that are created are updatable by default. In some cases, entities have to be readonly. To mark an entity as readonly (or non-updatable), do the following.

  • Open the Entity in the design view (i.e open the overview editor)
  • Open the property inspector
  • In the property inspector expand the "Type" tab.
  • There will be a dropdown with the label "Updatable:". Change its value to "false".