Skip Headers
Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g Release 3 (10.1.3.0)
B25947-01
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

9.4 Assigning Programmatically-Derived Attribute Values

When declarative defaulting falls short of your needs, you can perform programmatic defaulting in your entity object:

9.4.1 Defaulting Values for New Rows at Create Time

The create() method provides the entity object event you can handle to initialize default values the first time an entity row is created. Example 9-3 shows the overridden create method of the ServiceHistory entity object in the SRDemo application. It calls the attribute setter methods to populate the SvhType, CreatedBy, and LineNo attributes in a new service history entity row.

Example 9-3 Programmatically Defaulting Attribute Values for New Rows

// In ServiceHistoryImpl.java in SRDemo sample
protected void create(AttributeList nameValuePair) {
  super.create(nameValuePair);
  setSvhType(getDefaultNoteType());
  setCreatedBy(getCurrentUserId());
  setLineNo(new Number(getServiceRequest().getMaxHistoryLineNumber()+1));
}

9.4.1.1 Choosing Between create() and initDefaults() Methods

If an entity row has New status and you call the refresh() method on it, if you do not supply either the REFRESH_REMOVE_NEW_ROWS or REFRESH_FORGET_NEW_ROWS flag, then the entity row is returned to an Initialized status. As part of this process, the entity object's initDefaults() method is invoked, but not its create() method again. So override the initDefaults() method for programmatic defaulting logic that you want to fire both when the row is first created, as well as when it might be refreshed back to initialized status.

9.4.1.2 Eagerly Defaulting an Attribute Value from a Database Sequence

Section 6.6.3.7, "Synchronization with Trigger-Assigned Values" explained how to use the DBSequence type for primary key attributes whose values need to be populated by a database sequence at commit time. Sometimes you may want to eagerly allocate a sequence number at entity row creation time so that the user can see its value and so that this value does not change when the data is saved. To accomplish this, use the SequenceImpl helper class in the oracle.jbo.server package in an overridden create() method as shown in Example 9-4. It shows code from the custom Java class of the SRDemo application's Product entity object. After calling super.create(), it creates a new instance of the SequenceImpl object, passing the sequence name and the current transaction object. Then it calls the setProdId() attribute setter method with the return value from SequenceImpl's getSequenceNumber() method.

Example 9-4 Eagerly Defaulting an Attribute's Value from a Sequence at Create Time

// In ProductImpl.java
import oracle.jbo.server.SequenceImpl;
// Default ProdId value from PRODUCTS_SEQ sequence at entity row create time
protected void create(AttributeList nameValuePair) {
  super.create(nameValuePair);
  SequenceImpl sequence = new SequenceImpl("PRODUCTS_SEQ",getDBTransaction());
  setProdId(sequence.getSequenceNumber());
}

9.4.2 Assigning Derived Values Before Saving

If you want to assign programmatic defaults for entity object attribute values before a row is saved, override the prepareForDML() method and call the appropriate attribute setter methods to populate the derived attribute values. In order to perform the assignment only during INSERT, UPDATE, or DELETE, you can compare the value of the operation parameter passed to this method against the integer constants DML_INSERT, DML_UPDATE, DML_DELETE respectively.

Example 9-5 shows the overridden prepareForDML() method used by the ServiceHistory entity object in the SRDemo application to automatically change the status of a service request when a service history note of certain types are created. When a new service history entry is inserted, this code changes the status of:

  • A pending or closed service request to open if the new history note is added by a customer

  • An open service request to pending if the new history note is added by a technician

Example 9-5 Assigning Derived Values Before Saving Using PrepareForDML

// In ServiceHistoryImpl.java
protected void prepareForDML(int operation, TransactionEvent e) {
  super.prepareForDML(operation, e);
  // If we are inserting a new service history entry... 
  if (operation == DML_INSERT) {
    ServiceRequestImpl serviceReq = getServiceRequest();
    String historyType = getSvhType();
    // If request is pending or closed and customer adds note, status => Open
    if ((serviceReq.isPending() || serviceReq.isClosed())
        && CUSTOMER_TYPE.equals(historyType)) {
        serviceReq.setOpen();
    }
    // If request is open & technician adds a non-hidden note, status => Pending
    if (serviceReq.isOpen() && TECHNICIAN_TYPE.equals(historyType)) {
        serviceReq.setPending();
    }
  }
}

9.4.3 Assigning Derived Values When an Attribute Value is Set

To assign derived attribute values whenever another attribute's value is set, add code to the latter attribute's setter method. Example 9-6 shows the setter method for the AssignedTo attribute in the SRDemo application's ServiceRequest entity object. After the call to setAttributeInternal() to set the value of the AssignedTo attribute, it uses the setter method for the AssignedDate attribute to set its value to the current date and time.

Example 9-6 Setting the Assigned Date Whenever the AssignedTo Attribute Changes

// In ServiceRequestImpl.java
public void setAssignedTo(Number value) {
  setAttributeInternal(ASSIGNEDTO, value);
  setAssignedDate(getCurrentDateWithTime());
}

Note:

It is safe to add custom code to the generated attribute getter and setter methods as shown here. When JDeveloper modifies code in your class, it intelligently leaves your custom code in place.