Showing posts with label ADFbc Performance. Show all posts

gravatar

Storing non-serializable objects

In many cases there are requirements, where every user session needs a seperate object to be used throughout the session.
For example, let us take the example where there is requirement to access the SOA related data from the Application Module. To access the data from the SOA server, a connection has to be established to the SOA server and then appropriate data has to be queried. The same connection cannot be used by all users (or cannot be used in all user sessions). Every user session should have a seperate connection, so that when queries are executed, only the data related to the user are fetched. So for every user session, a seperate connection object is required.

So how can we make evey user have a seperate unserializable object?

The simplest way to achieve this is to re-create the object every time it is required. But in many cases, recreating such objects can have serious performance implications. So what else can be done?

The only other thing that can be done is to minimize the number of times the object is re-created.
This can be achieved by storing the non-serializable objects in the session of the DB transaction associated to the Application module.

The following piece of code shows how to do that..

getDBTransaction().getSession().getUserData().put("key",non_serializable_obj_instance);

So the overall procedure should be as follows..

  • Check whether the require object is present in the user session
  • If the object is present , just it
  • If the object is not present, create an instance of the object. Put a reference of the object in the session and use the reference.
The session associated to the transaction, gets re-initialized whenever passivation/activation happens. So all the objects placed in the session will be gone after the passivation/activation cycle.

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

BC4J batch update feature

This blog tells you the basic information about the batch update feature provided by the BC4J framework .

During the commit phase, BC4J framework by default executes a seperate sql statement for each entity instance that has been either updated or marked as deleted. So if there are 1000 entity instances (of an entity class) which have been either updated or marked as deleted, BC4J framework will execute 1000 appropriate sql statements.

For example, say you have an Employee entity object type for which multiple instances are modified during typical use of the application. If two instances were created, three existing instances modified, and four existing instances deleted, then at transaction commit time the framework issues nine DML statements (2 INSERTs, 3 UPDATEs, and 4 DELETEs) to save these changes.

This can lead to performance problems if the number of changes are huge and if the enity objects are changed very frequently.

To minimize the performance problem, developers need to use the batch update feature of the BC4J framework.

When the batch update feature is enabled, BC4J framework will not execute a seperate sql statement for each and every entity instance during the commit phase. Instead it performs inserts, updates and deletes in batches.

In the example, update batching (with a threshold of 1) causes the framework to issue just three DML statements: one bulk INSERT statement processing two inserts, one bulk UPDATE statement processing three updates, and one bulk DELETE statement processing four deletes.

To enable this feature the only thing that needs to be done is to select the "Use Update Batching" checkbox in the design view of all entity objects as shown below..


Also the input text box with the label "When Number of Entities to Modify Exceeds" has to be set to 1.

Batch operations mean, sending multiple insert/update/delete sql statements in one shot to the sql engine from the middle tier, instead of firing each sql statement.

This feature cannot be used under the following cases..

  • If the entity object has any attributes that are set to Refresh After Insert or Refresh After Update
  • If the Entity has any attributes of type CLOB of BLOB
  • If the entity methods related to performing DML operations, are overridden..(PL/SQL entity objects fall in this category)..