ObjectExtender User's Guide and Reference


Appendix A. Restrictions

In addition to restrictions, this section documents workarounds and suggestions that may be useful to product users.

Home createFromKey:

When creating a new object, you can create it with the Home createFromKey: method. If that key contains relationships (really the keys of the related objects) then the related objects cannot be new objects. If you want to set a relationship to a new object, you should use create and then set the relationships with the new object (NOT the key), or use the createWith:with: helpers on the homes. The reason behind these restrictions is that the key of a new object is not guaranteed to be permanent, so we do not support lookup of a new instance by key, therefore a relationship to that new object by key alone can't be resolved. For example:

   | b1 newBranch c bc | 
   b1 := VapBankBranchHome singleton findByBranchNumber:'BR001'. 
   newBranch := VapBankBranchHome singleton createWithBranchNumber:'BR999'. 
   c := VapCurrencyHome findByCurrencyType: 'CRC01'.  
 
   "Relate two existing objects: Works OK" 
   bc := VapBranchCurrencyHome createForBranch: b1 currency: c.  
 
   "Relate one existing object and one new using helper: 	
   Sets relationshipvalue directly, Works OK" 
   bc := VapBranchCurrencyHome createForBranch: newBranch currency: c.   
 
   "Relate one existing object and one new using createFromKey:
   Does not work!" 
   bc := VapBranchCurrencyHome 
      createFromKey: (VapBankBranchKey with: newBranch key with: c key).  
 
   "also: until newBranch is committed to the data store and the 
   Shared Transaction, you can't find it by key, 
   ala: VapBankBranchHome singleton findByBranchNumber: 'BR999'. "     

Residual instance variables on model regeneration

If you delete class attributes in a model for which you have already generated code, and then regenerate the model, you may encounter the following problem: your instance variables represented by the attributes you deleted will still exist in the class, however their getter and setter methods will be properly deleted.

DBCS character text field entry

You cannot enter DBCS characters in ObjectExtender browsers and tools except for one case:

  1. Physical name for tables, columns, and keys.

    In addition to Physical name, there is a corresponding (optional) logical name field (Name) for tables. If you import a schema from a database, which has double-byte characters, enter logical names for each physical name, you must enter single-byte characters for the logical name.

Mapping, relationships, and preload limitations

Inheritance Mappings

  1. Disinheritance not supported.
  2. Remapping of superclass map ivar/relationship maps not supported.
  3. Mixing inheritance strategies within one mapped inheritance hierarchy is untested.
  4. Use of discriminators outside of inheritance mappings is untested.
  5. Multiple column discriminators is not supported.
  6. Discriminators that are also keys is untested.
  7. Relationships among classes within a mapped inheritance hierarchy has not been fully tested.
  8. Distinct table inheritance is not supported.
  9. Use of foreign key relationships that are not "primary key to primary key" in root/leaf inheritance mapping is untested

Abstract Mapped Classes

  1. Abstract mapped classes are supported only within inheritance mappings. We assume that the abstract class is mapped to an (abstract) table in the database. Otherwise abstract mapped classes are not supported.

Relationships

  1. Relationships across data stores are not (fully) supported
  2. Relationships involving "non-standard" foreign keys are not supported, for example:
    1. keys that do not match either with the number columns or column types
    2. keys involving transformations of the key data
    3. keys involving column or database functions
  3. Many to Many relationships with hidden tables are not fully supported

Class Mapped to Multiple Tables

  1. Foreign key relationships that not "primary key to primary key" (i.e. "backward" 1 to 1) are not tested
  2. Classes split over data stores are not directly supported

Preloading. There is a known bug with preloading relationships on a class whose target classes are mapped to the same class (or inheritance hierarchy). The query generated is incorrect. This occurs in the following scenarios:

  1. Class with relationship to self (or some other member of its own inheritance hierarchy).
  2. Class with two or more relationships to the same target class (or classes in the same inheritance hierarchy).
  3. Relationships between classes in the same inheritance hierarchy.

Single character data and vendor DB drivers

Various vendors' database drivers treat single-character data differently. Some will return a Character, some will return a String of length one. To be safe, if an application may run with multiple drivers, type Char(1) fields as strings, and the VapCharToString converter will guarantee that a string will always be returned.

IC instruction not preloaded

For all VisualAge users using ICs, they must load the following two config maps before using ICs, 1) Envy/Packager IC Instructions, and 2) VisualAge IC Instructions

For ObjectExtender users, you must load one more instruction: VisualAge Persistence IC Instructions

These instructions must be loaded in this order.

Composed object does not make aggregate dirty

When using composed objects, the aggregate object is not marked "dirty" in a partial update scenario. For example, TstCustomer object has a name which is a composed object. When an update partial name operation is performed (first name or last name) the object is not marked dirty, so the changed object will not be written into the data store. To force the change, you must change the other attribute of the object.

Global reset does not clean up database connections

If you attempt to clean up database connections using the "Global ObjectExtender Reset", and you get an unknown abtError, you may still have a dead connection to the DB. One workaround for this is to evaluate the following:

 
 
      AbtDbmSystem startUp
 
 
 

Generate models first before other code-gens

As a general rule, always generate code for models before generating services code or stub code for schema or local image persistence. If you generate code without a model present a walkback will occur stating that the model is missing.

Backwards 1:1 relationships

If you have backwards 1:1 relationships, you must always regenerate the services after generating the model. Model generation assumes that all 1:1 relationships are forwards, service generation uses the maps to correct those which were backwards.

When Changing composer types

If you have a complex attribute map, and you want to change the Composer type, you need to delete the Complex attribute map from the Map Browser and recreate it in the Property Map Editor.

Specialization for cascade delete

A specialization of BusinessObject>>#abtRemove is available for cascade delete operations. The cascade responsibility is divided between the two remove methods. #abtRemove is sent by the application to the root object being deleted. This method can be overridden to disconnect the root object from its parent object. The default implementation of #abtRemove just calls #markRemoved. #markRemoved should be specialized to perform any disconnects and cascades which an object should perform whether or not it is the root. It should not disconnect from its parent object here. It should not disconnect any connections to child objects, since these connections are required to perform operation sorting for referential integrity constraints. An example might go like this:

 
 
     VapCustomer>>#abtRemove 	
         self bankBranch: nil.	"disconnect from parent" 	
         super #abtRemove	"calls #markRemoved"  
 
 
     VapCustomer>>#markRemoved 	
        self accounts do: [:acc | acc markRemoved].	"cascades to transactions, etc."
        self homeAddress markRemoved. 
        self billingAddress markRemoved. 
       "you could also disconnect any non-aggregate associations here"

Foreign keys used in 1-1 relationships

If foreign keys are used for 1-1 relationships, the association must be navigable. For example, suppose you have the following :

      Model:
        Customer <-------> Address 
           1. homeAddress                         
           2. billingAddress  
      Schema:               
 
         Customer table contains homeAddress and billingAddress columns 
         which are foreign keys to Address table.

You must then define both model associations navigable. Otherwise, on inserting customer, it will not insert the address first, and you will get an insert customer error because the address parent key does not exist.

Service Generation should generate #executeSingleUpdate: for No key object

The problem occurs when a model class has only properties which are part of its OID.

An association object, modeling a join table, is a good example.

Say you have a model class called BranchToCurrency which is an association between Branch and Currency, its only properties are two associations, and these two associations make up the OID of the BranchToCurrency object. Since the database row only has key fields, there are no updatable fields, and our UPDATE query will not work properly.

The workaround is to override the service method #executeSingleUpdate: to do nothing. The application developer should structure their use of these kinds of objects so that the application never tries to update one, always adding or removing new instances rather than changing an existing one. The override above is just to catch a case where the app accidentally updates an object, maybe by disconnecting a related object.

Pre-req for user-defined composers

Model and service applications which use Composers need to make sure their pre-reqs are updated to include their application which define any user-defined model and composers. For example, if a model has a property which is a Name, and the maps specify that a composer called NameComposer should be used, then the generated model application must pre-req the application defining Name, and the generated service app must pre-req the application defining NameComposer.

No converter for AbtMonetaryAmount

A converter for AbtMonetaryAmount is not provided, use ScaledDecimal instead.

Workaround for Sun core exiting VisualAge ObjectExtender application

On Soliaris platforms, if you encounter a core dump on exiting VisualAge ObjectExtender application (runtime), the workaround is to comment the method #shutDown in class PlatformLibrary, then re-package the application.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]