A Java™2 Enterprise Edition(J2EE) application server has a highly multi-threaded execution profile that allows multiple transactions to be active simultaneously. The persistent application data associated with these transactions is held in a relational database management system (RDBMS). The application data held in the database is loaded into container managed Enterprise JavaBeans™ (EJBs) when needed by the application within the scope of a transaction. It is important that this data is correctly protected from the competing requirements of those transactions that require read access, and those that require update access. The EJB container, persistence manager and the relational resource adapter and database work together to control the concurrency. Application data integrity is essential, and is ensured by the application server engine. WebSphere Application Server takes care of these low-level details so the application developers do not need to.
To support different database access methods, WebSphere Application Server defines an extension to the EJB deployment descriptor that enables developers to customize the concurrency control settings specific to their applications' transactional needs. Different policies are implemented as declarative annotations that give WebSphere hints on how to access the data. These policies are referred to as Access Intents. WebSphere enables these to be configured manually and can provide performance benefits. Contention on transactional resources, such as a relational database in this case, can become a bottleneck. Tuning the way the application server accesses the persistent data could be used to improve throughput and response times, as well as lead to lower resource contention.
The access intent policies discussed in this article apply to Container Managed Persistence (CMP) 2.x beans only. We are assume the reader has experience with developing EJB applications using WebSphere Studio Application Developer. General knowledge of the SQL language will also make the content more understandable. The next section describes the different attributes of an access intent policy, followed by descriptions of the policies themselves. In the final part of the article, examples are provided to help you use access intents with WebSphere Studio Application Developer V5.1.1.
Attributes of an access intent policy
The following sections describe the main components that make up an access intent policy in WebSphere Application Server V5.1. Access intents are a combination of database-specific isolation levels, locking policies and, in some cases, read-ahead hints.
Each access intent policy defined is an aggregate of a set of properties used to control different aspects of the persistence and concurrency handling involved in dealing with EJB entities. The information described in this article is relevant to WebSphere Application Server V5.1. Although the intention is not to touch upon enterprise specific-concepts, WebSphere Application Server Enterprise Version 5.1 further extends the concepts that are discussed here.
A transaction processing system must support complete isolation of a transaction from other concurrently running transactions. Complete isolation, however, may have an impact on performance and throughput. If each transaction executes in a serial fashion, our multi-threaded application server would not perform very well. The ANSI SQL-92 standard defines four levels of database isolation that we can use to gain some form of parallelism in our transactions. They are identified with respect to what particular data access characteristics they allow (for example, dirty reads, non-repeatable reads or phantom reads). The isolation level is set on the database connection and, as we will see later, the access intent policy in use will determine how the application server will set this parameter. Different database vendors can use different techniques to ensure that the requirements of isolation level are met.
The four different JDBC™ isolation levels are listed below, with a description of how DB2® handles each one. Other database vendors may implement this differently, but the general idea will be the similar.
- TRANSACTION_SERIALIZABLE
This is the strongest isolation level. DB2's internal isolation level for this is referred to as Repeatable Read. All the rows in the database table that are affected by the current transaction will be locked; no other transaction can insert, delete or update a row in the selection set. Locking is also performed so that rows cannot be inserted in a way that would change the selection set used in other transaction. For example,SELECT * FROM orders WHERE Total > 2000would not only lock the rows that match the predicate condition, but also all rows in the table. This prevents the presence of phantom rows. Uncommitted changes from other transactions cannot be seen.
- TRANSACTION_REPEATABLE_READ
Phantom rows can appear with this isolation level. This is because the statementSELECT * FROM orders WHERE Total > 2000will only lock the rows that meet the condition. If the same statement is reissued within the transaction, the result could be different. It is ensured that the rows updated or read during the transaction cannot be changed by anyone else until the work commits. Repeatable Read maps to DB2's isolation level Read Stability.
- TRANSACTION_READ_COMMITTED
DB2 maps this to its Cursor Stability isolation level. If you issue the statementSELECT * FROM orders WHERE Total > 2000rows will only be locked as the resultset is traversed. Obviously, phantom rows can occur, but more importantly, non-repeatable reads can occur. This happens when a transaction reads the same data twice, while another transaction modifies the data between the two reads, resulting in in a different result for each read.
- TRANSACTION_READ_UNCOMMITED
Transactions are not isolated from each other, and can access uncommitted changes from each other. Currently, none of the access intents in WebSphere Application Server will use this isolation level.
Choosing the correct isolation level can be complex. However each access intent policy in WebSphere Application Server will choose an appropriate isolation level for supported databases, relieving the developer from this level of detail. (See Resources.) Knowing what level of isolation WebSphere Application Server puts on its connection to the database can be important if there are other external applications accessing the same database.
In conjunction with the isolation level, the application server can use two different locking strategies to further control the concurrency of transactions.
- Pessimistic locking
A pessimistic locking strategy is one where a lock is obtained early in the transaction and kept until either the transaction is committed or rolled back. Other transactions wanting access to this data wait until the lock is released.
Figure 1. Illustration of a pessimistic locking scenario.
Figure 1 shows the idea behind pessimistic locking. Transaction 1 (Tx1) reads the value 1000 from the database into the balance variable. When Transaction 2 (Tx2) wants access to the row that contains the balance for this account, Tx2 is blocked until Tx1 has updated the balance to 3000 and committed its changes. Tx2 can then proceed with reading the value 3000 and updating it to 4000. - Optimistic locking
The main problem with a pessimistic approach is that transactions have to wait for each other. A way to avoid this is to be more optimistic and believe that it is unlikely that another transaction would want to update the same entity at the same time. With this kind of thinking, locking the data in the beginning of the transaction can be avoided. Instead, it is only locked at the end of the transaction when it is updated. This method requires a way to ensure that the data has not been altered between the time it was read it and when it was updated. This is known as a WriteWriteConflict.
Figure 2. Illustration of a optimistic locking scenario.
Figure 2 shows the idea behind optimistic locking. Similar to Figure 1, Transaction 1 (Tx1) reads the balance value as 1000 without locking the row in the database. Transaction 2 (Tx2) is not prevented from doing the same thing, and reads the balance initially as 1000. Before committing the transaction it must check for conflict and finds that the value is now 3000, which is different from the initial value read. It must now abort the transaction and start the transaction again. The task of checking for a conflict can be done in several ways. An extra column can be used in the database to hold a version or a timestamp (see Resources for more information on conflict handling techniques). The update is then made with a conditional expression to only update if this field is the same as when the data was read. One or more fields could be used for the same purpose. It would have to be a field that is updated in each transaction.
The use of optimistic locking offers more concurrent access to the data. The drawback is the need for collision handling which will be very expensive if collision are frequent. For this reason it is only appropriate to apply optimistic locking when collisions are rare. If the application access pattern is predominately update access, then pessimistic approach might be advantageous in that it avoids optimistic concurrency update failures.
An access intent policy in WebSphere Application Server includes a few other properties which are only modifiable in the Enterprise edition, where policies can be customized. One such property is Collection Increment, which allows you to define the size of the collection returned when calling EJB entity multi-finder methods. We can be lazy and set this to a low value, which means that the database must be repeatedly queried to get data as we iterate over the collection. A high value would mean that it is more likely that all data will arrive in one database query, although the cost of maintaining the large collection is higher. To find out more about this and what the default values are for the different Access Intent policies, refer to the WebSphere Application Server Information Center (see Resources), which will also describe the concepts of Collection Scope and Resource Manager Prefetch, all applicable primarily to WebSphere Application Server Enterprise.
We will now look at the different Access Intents that exist in WebSphere Application Server.
The main identifier for a policy is its locking strategy and type. The type of an access intent can be either read or update. If you assign a read policy to an entity bean, an exception will be thrown if you attempt to update it. That is, you cannot call any setter methods. It is also interesting to consider what isolation level will be used, especially if you have other systems accessing the same database. It is important to realize that different database vendors can have their own meanings of the database isolation level. Most implementations are like that shown in the table below (except for Oracle which is mapped to different isolation levels; see Resources for more information on what isolation level is used with different database implementations). Table 1 shows the seven different policies currently defined in WebSphere Application Server V5.1. This data is based on using DB2 as the RDBMS.
Table 1. Access Intent policies in WebSphere
| Policy | Type | Locking strategy | Isolation level |
| wsPessimisticUpdate | Update | Pessimistic | Repeatable Read |
| wsPessimisticUpdateWeakestLockAtLoad | Update | Pessimistic | Repeatable Read |
| wsPessimisticUpdateNoCollision | Update | Pessimistic | Read Committed |
| wsPessimisticUpdateExlusive | Update | Pessimistic | Serializable |
| wsPessimisticRead | Read | Pessimistic | Repeatable Read |
| wsOptimisticUpdate | Update | Optimistic | Read Committed |
| wsOptimisticRead | Read | Optimistic | Read Committed |
As described previously, the intent of the pessimistic approach is to ensure that the data loaded into the entity bean is locked during the entire duration of a transaction. The normal
behaviour of a database access is to get a read lock on the queried data, which gets transformed into an update lock if data is updated. We
want to make sure that all the rows are locked when the data is fetched from the database. This can be done by using a specific SQL query referred to as SELECT..FOR UPDATE. The update clause will ensure that an update lock is held on the selected rows.
A subsequent transaction issuing the same statement on any of the rows will be blocked until the first transaction commits its changes. There are five different pessimistic
policies defined in WebSphere Application Server V5.1. They all have lock hints described by their name, wsPessimistic#hint#, where #hint# further describes our intention with the entity bean.
-
wsPessimisticUpdate
- No specific hint is specified. The isolation level will be set to Repeatable Read and a "SELECT..FOR UPDATE" SQL statement will be used to get an update lock on the row in the database. If you are looking to create a true pessimistic scenario, then this is the policy to use. A drawback is that you cannot have complex queries defined in your finder methods. This is because a
SELECT..FOR UPDATEdoes not support grouping and ordering, so you cannot create a finder that would get a set of rows from the database and order them by a specific column. -
wsPessimisticUpdateWeakestLockAtLoad
-
This is the default policy. If no access intent is specified in the deployment descriptor, WebSphere Application Server will use this hint. Compared to wsPessimisticUpdate, it will not use a
SELECT..FOR UPDATEclause to obtain an update lock. The container will load the data with the weakest lock available for the targeted database. This means that the rows will be locked as shared. When an attempt to update is made, the lock will be promoted to an update lock.
- wsPessimisticUpdateNoCollision
- Uses Read Committed, which is a lower isolation level. It will not use a
FOR UPDATEclause when loading the data, so the rows will not be locked. Using this policy, one must be sure that there will be no concurrent update to the same row or range of rows. That is, if concurrent transactions update an entity bean with same primary key, updates could get lost. Avoid using this policy.
- wsPessimisticUpdateExclusive
-
This will ensure that the transaction has exclusive access to the data being updated. Database isolation is set to Serializable and a
SELECT..FOR UPDATEstatement is used when loading the data. Both readers and writers must wait until the exclusive transaction has committed its changes. This policy should be used with caution since it can create serious bottlenecks in the application. It has the same limitation as wsPessimisticUpdate in that complex queries are not supported.
- wsPessimisticRead
- If you know that an entity bean will only ever be read and not updated, then this policy will simulate a read-only lock. If an attempt to update the data in the entity bean is made, then an exception will be thrown. Be careful and ensure that no other external applications are accessing the same table(s) with different intentions.
By applying an optimistic policy, data will not be locked when the entity bean is loaded. Instead, an overqualified update statement UPDATE .. WHERE will be used
when the entity bean is stored back into the database. We will see later how to configure this in WebSphere Studio. Situations where an entity bean is not updated very often
will benefit from an optimistic policy. Also if there are a lot more reads than updates on the entity bean, an optimistic locking strategy might improve performance.
- wsOptimisticUpdate
-
This is the only policy we can use if we choose to implement an optimistic locking strategy to update entity beans. It will issue a normal select statement to load the data into
the entity bean, perform its updates, and then issue an overqualified update statement when committing the data.
- wsOptimisticRead
- This only differs from wsPessimisticRead in that the isolation level is set to Read Committed.
An extra feature that can be applied to an access intent policy is a read-ahead hint. This is only applicable when there is a relation defined between entities. The idea is to minimize database calls by caching the related beans. For example, if bean A has a relation to B and C, we specify a read-ahead hint on these relations. Then, when A is loaded, one entity of C is loaded since it is a 1:1 relationship, and a matching number of Bs is loaded since it is a 1-M relationship. Read-ahead hints apply only to the findByPrimaryKey method on CMP 2.x entity beans. The application server will generate a more complex SQL query that will bring in the data from multiple tables. When we later request to access these beans, no database access is necessary.
Figure 3. Entity bean with container-managed relation
Read-ahead hints can be defined on more than one level. If D relates to E and E to F, a hint can be created so that when D is loaded the corresponding E and F entities are also loaded. One should not use read-ahead hints unless the corresponding Container Managed Relations (CMR) bean will be touched in the transaction. The hint does imply an extra cost on the database due to the join statement between tables that should be avoided if not needed.
Configuring access intents in WebSphere Studio
The section is a short guide on how to configure access intents in WebSphere Studio Application Developer Version 5.1.1.
A policy can be applied to either an entire bean or on a method in a bean. This article has not discussed access intent policies from a method-level perspective; this can have a complex impact on an application. It is quite easy to cause deadlocks or to prevent connection sharing if different isolation levels are used in the same transaction.
Access intent policy information for entity beans is described in the WebSphere extensions descriptor file, ibm-ejb-jar-ext.xml. Naturally, the intention is that you not have to edit this file, so all this is done for you by WebSphere Studio. To show you how, we will use a simple example of an application that accesses product catalogue data.
Figure 4 shows a class diagram of the scenario in which we will use our access intent.
Figure 4. Classdiagram for Example 1
The idea is that a stateless session bean, CatalogBrowser, is used to get a collection of products to display to the user. At the same time, a store administrator can update the product catalogue from an administrative interface. This is done through CatalogAdmin, which also is a stateless session bean. We know that product data is rarely updated, perhaps a few times each month, and customers frequently browse the catalogue for products. With this knowledge, we can optimize the locking strategy for obtaining product entities. Due to the low probability of a conflict in the database, we can confidently use an optimistic locking strategy. To configure an access intent on an Entity bean in WebSphere Studio Application Developer:
- In the J2EE Hierarchy, right-click on the EJB module that contains the entity to configure, and select Open with => Deployment Descriptor.
- In the main window, select the Access tab.
- Scroll down to the WebSphere Extensions section (Figure 5), and select the Add button to display the "Add Access Intent" dialog (Figure 6).
Figure 5. Deployment Descriptor Editor: Access tab - WebSphere Extenstions.
Figure 6. Add Access Intent dialog
- Select the Access intent name from the drop-down list. The read-ahead hint is not selectable since the Product bean in the example does not have any relations to other beans.
- Finally, we must specify what should be included in our overqualified update statement when modified data is committed. That is, what fields should be included
in the
WHEREclause in the SQLUPDATEstatement. This needs to be one or more fields in the Product entity that would indicate that an update has been made. In our case, it can be assumed that an update could include any field in the product, and so all fields must be included when doing the check. To do this, you should have database maps defined for your application. When this is done, open the Mapping Editor for the application (Figure 7).
Figure 7. Mapping editor for product entity bean.
- For each field in the CMP entity bean, we can specify if it should be used as an OptimisticPredicate or not by setting the value to either true or false. Java primitive fields are set to true by default. This will not be sufficient for our needs since name, description, and category may be the only field updated by a competing transaction. If they where not included in the overqualified update statement, we would not be able determine that a conflict has occurred.
Example 2. wsOptimisticRead with Read-ahead hint
Now, we will make a small modification to the class diagram from Example 1 that will change the access pattern for our entity bean. Figure 8 shows that we no longer have the CatalogAdmin stateless session bean used to update product data. It is assumed that product data is just read from the database and never updated. We have also introduced a new entity, called component. A product is made up of one or more components, which is realized with a one-to-many relationship between them.
Figure 8. Classdiagram for Example 2.
Since the product and component entity is not updated, a read access type is used. Instead, we can use wsOptimisticRead (Figure 8). When a product entity is loaded, it would be beneficial if the corresponding components could be fetched as well. Follow the steps from Example 1 to set up the access intent; there is no need to define any OptimisticPredicates since we will not update any fields. The read-ahead hint is enabled by checking the corresponding box when creating an access intent. In doing so, we must also specify a preload path to use. This will be the component role in our relationship (Figure 9).
Figure 9. Specify preload path dialog
This article described the ideas behind optimistic and pessimistic locking strategies in EJB entities, including the different terminology that relates to WebSphere Application Server access intents, database isolation level, read-ahead hints and locking strategy. There are seven different access intent policies defined in WebSphere Application Server that can be applied to CMP 2.x entity beans on either a bean or a method level. The examples in this article demonstrated only bean-level access intent. Assigning access intents at a method-level should be avoided unless you have a really good understanding of what the effects will be.
Using access intents can be important when tuning the performance of an EJB application, especially if it is database intensive. Do not over-tune an application; errors can be introduced if a policy is applied incorrectly. For this reason, the general thinking is that if the performance of an application is already acceptable, there is no need to tune entity bean access. Introducing access intents may make the application design less easy to understand. For example, putting a read type hint on a bean prevents it from being updated. In a multi-user development project, one must now ensure that no one will try to update this bean. However, if performance problems are experienced and database resource contention is high, then tuning the access intents could be useful.
I would like to thank John J Stecher and Graham Rawson for their contribution as reviewers.
- Enterprise Java Programming with IBM WebSphere 2nd Edition - Excerpts from Chapter 28: Transactions in WebSphere 5.0, from the WebSphere Developer Journal, offers very good insight into how the behaviour of Access Intents depends on the back-end database system.
- Optimistic Locking pattern for EJBs, from Java World, provides in depth information about different conflict handling techniques when using optimistic locking.
- Understanding JTS -- Balancing safety and performance will give additional insight into isolation levels.
- WebSphere Application Server Information Center is the ideal place to look-up everything that has to do with WebSphere Application Server. Search on "Access Intent" to find
information related to this article.
-
Enterprise Java Programming with IBM WebSphere 2nd Edition by Kyle Brown, Gary Craig, Greg Hester, Russell Stinehour, W. David Pitt, Mark Weitzel, JimAmsden, Peter M. Jakab, Daniel Berg (Addison-Wesley Pub Co, 2003).
- Browse for books on these and other technical topics.

Mattias Persson works in the Java Technology Centre, Hursley Park IBM in the UK. He is a member of Java Performance Team and has a personal focus on the measurement and optimization of application server environments. He is a Certified Enterprise Architect for J2EE and received an MSc in Computer Science from Vaxjo University, Sweden, in 2002. He then joined IBM as a graduate.
Comments (Undergoing maintenance)





