| Oracle Repository API and Model Reference Guide |
CDAPI Activities for background explanation of the CDAPI activities mechanism.
The following example code illustrates the use of activity mechanism to handle the trapping and reporting of errors during a PL/SQL insert operation.
Notes:
Callers (clients) receive error messages from all three sources.
REM
***************************************************************************
REM Insert Business Object test script created on 29-JUN-99
REM
***************************************************************************
DECLARE
bob ciobusiness_object.data;
act_status varchar2 (100);
act_warnings varchar2 (100);
line varchar2 (240);
procedure o (text varchar2) is
begin
dbms_output.put_line (substr (text, 1,255));
end;
BEGIN
-- Initialize the API and establish a context container,
-- if not already done
-- assumes a context workarea has been set... --
if not cdapi.initialized then
o ('Initializing the API');
cdapi.initialize (upper ('&&context_container'));
end if;
-- Open a new activity
o ('Opening a new activity');
cdapi.open_activity;
-- Get the insert values into the property list of the new element
bob.v.ENTITY_OBJECT_REFERENCE := '&ENTITY_OBJECT_REFERENCE';
if bob.v.ENTITY_OBJECT_REFERENCE is not null then
bob.i.ENTITY_OBJECT_REFERENCE := true;
end if;
bob.v.GENERIC_CLASS_REFERENCE := '&GENERIC_CLASS_REFERENCE';
if bob.v.GENERIC_CLASS_REFERENCE is not null then
bob.i.GENERIC_CLASS_REFERENCE := true;
end if;
bob.v.IRID := '&IRID';
if bob.v.IRID is not null then
bob.i.IRID := true;
end if;
bob.v.IVID := '&IVID';
if bob.v.IVID is not null then
bob.i.IVID := true;
end if;
bob.v.NAME := '&NAME';
if bob.v.NAME is not null then
bob.i.NAME := true;
end if;
-- Nest all element operations in anonymous blocks to catch exceptions
-- Since all exceptions signal a fatal error with the operation, rollback
-- all database activity performed by the operation
-- Perform the INSERT operation within an anonymous block
declare
ci_savepoint varchar2 (10);
begin
ci_savepoint := 'CI' || to_char (sysdate,'HH:MI:SS');
-- Issue a savepoint to rollback to if an exception is raised
dbms_transaction.savepoint (ci_savepoint);
o ('Inserting a new Business Object');
ciobusiness_object.ins (null,bob);
-- CDAPI methods can cause the CI_VIOLATIONS view to be populated with
-- constraints violations caused by errors in the
-- make-up of the element (intra-element violations), so we could at
-- this point query the CI_VIOLATIONS view.
-- The view can be queried at any time, but only validate_activity
-- populates it with inter-element constraints
-- violation errors as well as intra-element constraints violation errors.
-- exception handler for inner block
exception
-- If an unhandled exception was raised during the operation, rollback
-- to the savepoint and print out any messages that are on the
-- PL/SQL and API stacks
when others then
-- Display PL/SQL errors
o ('1** Printing PL/SQL error stack ***');
o (dbms_utility.format_error_stack);
o ('***********************************');
o ('Operation aborted due to unhandled exceptions');
dbms_transaction.rollback_savepoint (ci_savepoint);
-- Display CDAPI errors
while cdapi.stacksize > 0 loop
o (cdapi.pop_instantiated_message);
-- Any errors would have been posted by the CDAPI code
end loop;
end;
-- Print the (interesting) properties in the property list which hold values
if bob.v.BUSINESS_OBJECT_TOP is not null then
o ('BUSINESS_OBJECT_TOP : '||bob.v.BUSINESS_OBJECT_TOP);
end if;
if bob.v.ENTITY_OBJECT_REFERENCE is not null then
o ('ENTITY_OBJECT_REFERENCE : '||bob.v.ENTITY_OBJECT_REFERENCE);
end if;
if bob.v.GENERIC_CLASS_REFERENCE is not null then
o ('GENERIC_CLASS_REFERENCE : '||bob.v.GENERIC_CLASS_REFERENCE);
end if;
if bob.v.ID is not null then
o ('ID : '||bob.v.ID);
end if;
if bob.v.IRID is not null then
o ('IRID : '||bob.v.IRID);
end if;
if bob.v.IVID is not null then
o ('IVID : '||bob.v.IVID);
end if;
if bob.v.NAME is not null then
o ('NAME : '||bob.v.NAME);
end if;
-- Validate the activity to reveal outstanding constraint violations. Validate_activity can be called at any time to
-- do an interim check on progress so far. This is one of the
-- advantages of the CDAPI activity mechanism over SQL transactions.
--
-- We are doing this here because we want to display (but not act on) ALL errors that have been placed in
-- the CI_VIOLATIONS view. That is, we are
--
-- validate_activity also traps inter-element constraint violations,
-- not just intra-element constraint violations
-- (that is, violations resulting from conflicts between the element we are
-- inserting and other elements - for example,
-- if we've given it a name that is not unique within its container).
cdapi.validate_activity (act_status,act_warnings);
-- The following loop queries the CI_VIOLATIONS view and reports all database violations.
-- act_status isn't actually tested here,
-- but should be. If = 'Y' on return, there are errors rows in the CI_VIOLATIONS view.
--
for viol in (select * from ci_violations) loop
if viol.warning='Y' then
line:='WNG: ';
else
line:='ERR: ';
end if;
o (line||cdapi.instantiate_message (viol.facility,viol.code,
viol.p0,viol.p1,viol.p2,viol.p3,viol.p4,viol.p5,viol.p6,viol.p7));
end loop;
-- Report any non-fatal messages that might have been posted on the CDAPI stack by the API code
while cdapi.stacksize > 0 loop
o (cdapi.pop_instantiated_message);
end loop;
--
-- Attempt to close the activity. close_activity is a request to try to close the activity.
-- The API does not close the activity if there are rows in the CI_VIOLATIONS view;
-- on return, the parameter act_status will contain 'N' to indicate that the activity could not be closed
-- and that CI_VIOLATIONS is not empty.
--
-- We are doing this here because since the call to validate_activity, the state of the
-- repository may have changed in such a way as to give rise to inter-element constraint violations.
-- (close_activity implicitly calls validate_activity. )
cdapi.close_activity (act_status);
-- If the status !=Y, then abort the activity.
-- We could do all manner of things here, but in this test we
-- choose to abort the attempt to insert the new element.
-- One strategy would be to continue to fix the errors
-- and continuously try to insert the object, testing for violations each time.
if act_status != 'Y' then
cdapi.abort_activity;
o ('Activity aborted with constraint violations');
-- Otherwise, the activity closed successfully
else
o ('Activity closed successfully');
end if;
-- exception handler for outer block
EXCEPTION
-- Catch all exceptions
when others then
-- Print the PL/SQL error stack
o ('2** Printing PL/SQL error stack ***');
o (dbms_utility.format_error_stack);
o ('***********************************');
-- Are there messages on the CDAPI stack?
if cdapi.stacksize > 0 then
-- Print all messages on the CDAPI stack
while cdapi.stacksize > 0 loop
o (cdapi.pop_instantiated_message);
end loop;
-- If there is currently an open activity, abort it now
if cdapi.activity is not null then
cdapi.abort_activity;
o ('Activity aborted with API errors');
else
o ('API Session aborted with API errors');
end if;
-- If there are no messages on the CDAPI stack, this was a non-CDAPI exception
else
-- If there is currently an open activity, abort it now
if cdapi.activity is not null then
cdapi.abort_activity;
o ('Activity aborted with ORACLE internal errors');
else
o ('API Session aborted with API errors');
end if;
end if;
END;
Note on the dbms_utility package:
dbms_utility is one of the standard PL/SQL supplied packages (see the section on Supplied Packages in the Oracle8 Application Developer's Guide ).
The format of a call to dbms_utility.format_error_stack is:
function format_error_stack return varchar2;
Format the current error stack. This can be used in exception handlers to look at the complete error stack.