Command History Beans What do they do? Command history beans record the store and remove events which have occurred with respect to a set of bean types called "trail beans." They also record the points at which multi-bean transactions were begun. A command history bean is only generated when a bean is successfully stored in or removed from persistent storage, or when a transaction involving more than one bean is committed. It is not possible for a command history bean to exist for a store or remove which never took place or as part of a rolled back transaction. It is possible for there to be a command history bean marking the beginning of a single-bean transaction which was subsequently rolled back, but this is not a difficulty, because begin commands are markers with no semantics. What are they for? Command history beans are intended for use in order to provide either: 1. Perpetual audit trails. 2. Event trails to be consumed by consumer daemons running in the server container. A typical use of such an event trail would be to provide a persistent storage replication function. While it would only be useful to provide one command history bean type for purpose 1, there may be a need for many bean types for purpose 2- one per consumer. How do I define them? There may be many types of command history beans, but the defining abstract entity bean class, local object interface and local home interface must be subtypes of HistoricCommand, HistoricCommandObject and HistoricCommandHome respectively. Typically you will not add any further methods to these classes and interfaces, so your subtype definitions will be empty. What do the sequence numbers mean? Each command history bean has a sequence number, where lower numbers of the same sign indicate a previous command, and higher numbers of the same sign indicate a subsequent command. Sequence numbers are only guaranteed to be contiguous within a single transaction, except for the case where the sequence has wrapped around to negative numbers after reaching the highest representable positive. If you ever read a command history bean with a primary key of Long.MAX_VALUE, Java will increment this to Long.MIN_VALUE, so this discontinuity will not be a problem in Java code. If you are interacting with the server using a non-Java veneer, you may need special code to deal with this case. How can I retrieve or consume them? Command history beans themselves should never be trail beans, as this would lead to unterminated recursion. Also, it customary for command history beans to be inaccessible from client containers, and not generally used in the server container. Command history beans should only be retrieved through the following mechanism: 1. Perform a findWhereFieldsEqual(Command.Command_Begin) on an instance of the command history bean home. If you are consuming a transaction, open a transaction to contain the remove commands. 2. For any bean objects in the resulting collection, you may call findByPrimaryKey(sequence+1) where sequence is the number of such an object. A FinderException may be taken to indicate that the transaction contained no trail beans or was rolled back. In either case, if you are consuming the contents of the transaction, call remove() on the begin command history bean. 3. For any bean object resulting from findByPrimaryKey(sequence+1) which is not a begin command history bean, you may call findByPrimaryKey(sequence+1) where sequence is the number of such an object. The resulting object, provided it is also not a begin command history bean, belongs to the same committed transaction. This instruction may be applied recursively to obtain all beans belonging to a single transactions. A FinderException may be taken to indicate that a transaction has no further elements. If you are consuming the transaction, call remove() for each object belonging to the transaction. Call commit() upon reaching a discontinuity (i.e. FinderException) or a begin command history bean (but do not remove that bean). A consumer which is replicating to another persistent storage should not commit() on the source container until it is sure the transaction in the destination storage has succeeded. A semaphore may be needed in the destination storage to cope with the case where the destination storage was updated, but the command history beans were not removed due to a system failure before or during the commit on the source container. For example, the sequence number of the begin marker could be stored somewhere in the destination storage so that any subsequent attempt by the command history bean consumer to render that transaction could be short- circuited so that it merely attempted to remove those beans from the source container and not reperform the successful actions on the destination storage. What do they mean? The CommandCode determines which type of command the command history bean records. Currently this value is one of: Command.Command_Begin (0) Marks the beginning of a transaction. All non-begin command history beans with consecutive sequence numbers immediately following the sequence number of the begin marker constitute a single committed transaction. Command.Command_Store (6) Indicates the storage of a trail bean. Call getBeanObject() in order to extract the bean object which was stored. (The bean object returned cannot be accidentally stored or removed- it is merely a placeholder for the data which was stored at the time of the command.) Command.Command_Remove (7) Indicates the removal of a trail bean. Call getBeanObject() in order to extract the bean object which was removed. (The bean object returned cannot be accidentally stored or removed- it is merely a placeholder for the data which was removed at the time of the command.) In some situations, a removed bean may contain data which was never present in persistent storage. What overhead do they carry? Some work is needed to allocate the sequence numbers to each of the command history beans, proportional to the number of command history bean types. This work is carried on by threads of control other from those used to process user requests so that this has minimal effect of total transaction time from the user's point of view. For example, it is likely that the users sequence numbers were allocated during idle server time except in the most extreme cases (when more than 50 trail beans are stored as part of the currently executing concurrent transactions.) Some space is needed to furnish each command history bean type's command pool, its sequence allocation control thread and also the command history beans currently claimed by currently executing concurrent transactions. This is proportional to the number of command history bean types added to the average number of concurrently executing transactions. During a user transaction, the time taken to commit each store or remove operation is proportional to the number of command history bean types. Therefore, the number of command history bean types should be kept to an absolute minimum.