Detect Oracle auto-generated keys

The WebLogic deployment descriptors for container managed persistent beans allows applications to use a feature for automatic database sequence (key) generation. When using this feature, a WebLogic application does not have to include code for generating the next sequence key when creating CMP EJB objects. When migrating WebLogic applications that include automatic sequence generation, application code must be added to generate the sequence identifier for new entries.

The weblogic-cmp-rdbms-jar.xml file contains information for entity EJBs that use WebLogic RDBMS based persistence. This rule scans for configuration of the WebLogic automatic-key-generation elements and provides migration information for the Oracle generator type. This example shows an element that will be flagged by this rule:

<weblogic-rdbms-bean>
<ejb-name>Card</ejb-name>
<data-source-name>MyDataSource</data-source-name>
<table-name>MY_TABLE</table-name>
...
<automatic-key-generation>
<generator-type>Oracle</generator-type>
<generator-name>sequence_id</generator-name>
<key-cache-size>10</key-cache-size>
</automatic-key-generation>
...
</weblogic-rdbms-bean>

The generator-name entry indicates the name from the Oracle DUAL table to use to generate the next sequence. For example, given a generator_name of sequence_id, the following SQL statement can be used to get the next sequence number.

select sequence_id.NEXTVAL from dual;

If this rule flags entries in your weblogic-cmp-rdbms-jar.xml deployment descriptor, you will need to take steps to manually modify your EJB code to create keys. These steps need to be taken before regenerating your EJB stubs for WebSphere Application Server. The following examples outline a potential migration path.

The following high-level examples show how to replace the functionality of the Oracle auto-generated key logic. You will need to write similar code for each CMP bean that uses Oracle auto-generated sequence numbers. You can create utility help classes to combine common logic that generates the sequence numbers for each bean.

Add a parameter for the sequence number to the ejbCreate and ejbPostCreate methods of the entity bean.

Before:

public Integer ejbCreate(String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException
...

public Integer postCreate(String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException
...

After:

public Integer ejbCreate(Integer sequenceID, String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException
...

public Integer postCreate(Integer sequenceID, String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException
...

Set the sequence number in the proper field of the EJB in the ejbCreate method.

public Integer ejbCreate(Integer sequenceID, String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException
{
...
setCardID(sequenceID);
...
}

Add a parameter for the sequence number to the create method of the EJB Home.

Before:

public Card create(String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException;

After:

public Card create(Integer sequenceID, String cardNumber, String lastName, String firstName,
java.sql.Date issueDate) throws CreateException;

Add logic to get the next sequence number for the CMP entity bean.

String sqlQuery = "select sequence_id.NEXTVAL from dual";
PreparedStatement prepStmt = con.prepareStatement(sqlQuery);

ResultSet rs = prepStmt.executeQuery();
if(rs != null) {
rs.next();
nextKey = rs.getInt("NEXTVAL");
}

Modify the code where the EJB home create() method is called to pass the next sequence number.

Card card = cardHome.create(nextKey, cardNumber, lastName, firstName, newDate);