How to Run a Scheduled Task with Automations in Oracle APEX

Create a scheduled automation step by step, write its PL/SQL action, activate it, run it once, and check the automation log.

Many applications need work that nobody should have to remember: cancel orders that were never approved, close old tickets, send reminders, clean up temporary data. Doing it by hand is easy to forget, and a separate database job lives outside the application, where developers of the application rarely look.

Oracle APEX has Automations for this: a shared component that runs on a schedule, finds the rows to work on with a query, and runs PL/SQL actions for each row, with a log of every run. This guide creates an automation that runs daily and cancels orders that stayed NEW for more than seven days, goes through every wizard and edit step, runs it, and checks the log.

Step 1: The Tables

The automation works on ORDERS, whose STATUS column has a check constraint with the allowed values NEW, APPROVED, SHIPPED, and CANCELLED. Here are the order tables of the example with their keys:

Example:

create table customers (
    customer_id number generated by default as identity
                constraint customers_pk primary key,
    name        varchar2(100) not null,
    email       varchar2(120) not null
);

create table products (
    product_id number generated by default as identity
               constraint products_pk primary key,
    name       varchar2(60)  not null,
    category   varchar2(30)  not null,
    price      number(10, 2) not null
);

create table orders (
    order_id    number generated by default as identity
                constraint orders_pk primary key,
    customer_id number not null
                constraint orders_customer_fk references customers,
    order_date  date default sysdate not null,
    status      varchar2(12) default 'NEW' not null
                constraint orders_status_ck
                check (status in ('NEW', 'APPROVED', 'SHIPPED', 'CANCELLED')),
    approved_by varchar2(60),
    approved_on date
);

create table order_lines (
    line_id    number generated by default as identity
               constraint order_lines_pk primary key,
    order_id   number not null
               constraint order_lines_order_fk references orders on delete cascade,
    product_id number not null
               constraint order_lines_product_fk references products,
    quantity   number not null
               constraint order_lines_qty_ck check (quantity > 0),
    unit_price number(10, 2) not null,
    constraint order_lines_product_uk unique (order_id, product_id)
);

create index order_lines_order_ix on order_lines (order_id);
create index order_lines_product_ix on order_lines (product_id);

Before creating the automation, check which orders it will cancel: NEW orders with an order date more than seven days ago:

Example:

select count(*) as orders_to_cancel
from   orders
where  status = 'NEW'
and    order_date < trunc(sysdate) - 7;

Output:

   ORDERS_TO_CANCEL
___________________
                 40

In the sample data of this guide, 40 of the 42 NEW orders were older than seven days.

Step 2: Create the Automation

In App Builder, open Shared Components, click Automations, and click Create. In the first step:

  • Name: Cancel unapproved orders.
  • Type: Scheduled. On Demand automations run only when started from code or from App Builder.
  • Actions initiated on: Query, so the automation runs its actions for the rows of a query.
  • Execution Schedule: Daily at Midnight.
Create Automation wizard with name Cancel unapproved orders, Type Scheduled, Actions initiated on Query and Execution Schedule Daily at Midnight marked with red boxes
Wizard step 1: name, type, and schedule.

Click Next. Choose Source Type SQL Query, enter the query of the orders to cancel, and keep Execute Actions When Rows returned:

Example:

select order_id, order_date
from   orders
where  status = 'NEW'
and    order_date < trunc(sysdate) - 7
Create Automation wizard step 2 with Source Type SQL Query, the query on NEW orders older than 7 days and Execute Actions When Rows returned marked with red boxes
Wizard step 2: the rows the automation works on.

Click Create. APEX creates the automation in Disabled state, with a placeholder action named New Action whose code is only begin null; end;, and opens the edit page.

Step 3: Write the Action

In the Actions section, click the edit icon of New Action. Change its Name to Cancel order, keep Type Execute Code, and replace the code. Each column of the query is available as a bind variable, so :ORDER_ID is the order of the current row:

Example:

update orders
set    status = 'CANCELLED'
where  order_id = :ORDER_ID
and    status = 'NEW';

apex_automation.log_info('Order ' || :ORDER_ID || ' cancelled');
Automation Edit Action page with Name Cancel order and the PL/SQL code updating ORDERS and calling apex_automation.log_info marked with red boxes
The action that runs for each row.

The condition status = 'NEW' repeats the query's filter, so an order approved between the query and the update is not cancelled. APEX_AUTOMATION.LOG_INFO writes a message into the automation's log. Click Apply Changes.

Edit the placeholder rather than adding a second action: in a first test, a new action was added next to New Action, and the automation ran both, the empty one first.

Step 4: Activate the Automation

Back on the automation's edit page, set Schedule Status to Active in the Settings section. The schedule expression created by the wizard, FREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0, runs it every day at midnight:

Automation Settings section with Type Scheduled, the daily schedule expression and Schedule Status Active marked with a red box
Schedule Status Active turns on the schedule.

In the Action Execution section, set Primary Key Column to ORDER_ID, so the log records which row each message belongs to, and Commit to Each Row, so every cancelled order is committed on its own and an error in one row does not undo the others:

Automation edit page with the Cancel order action, Primary Key Column ORDER_ID and Commit Each Row marked with red boxes
The action list and how the actions are executed.

Action Error Handling decides what happens when an action fails: Ignore the error and continue, Terminate Automation for this run, or Disable Automation until someone looks at it.

Step 5: Run It and Check the Log

Click Save and Run to save the changes and run the automation at once, instead of waiting for midnight. Then check the log views:

Example:

select status,
       to_char(start_timestamp, 'HH24:MI:SS') as started,
       successful_row_count as ok_rows,
       error_row_count      as error_rows
from   apex_automation_log
where  automation_name = 'Cancel unapproved orders'
order  by start_timestamp desc
fetch  first 1 row only;

select message_type, message, pk_value
from   apex_automation_msg_log
where  automation_log_id = (select max(id)
                            from   apex_automation_log
                            where  automation_name = 'Cancel unapproved orders')
order  by message_timestamp
fetch  first 5 rows only;

Output:

STATUS        STARTED        OK_ROWS    ERROR_ROWS
_____________ ___________ __________ _____________
Successful    02:49:53            40             0

MESSAGE_TYPE    MESSAGE               PK_VALUE
_______________ _____________________ ___________
Info            Order 10 cancelled    10
Info            Order 12 cancelled    12
Info            Order 20 cancelled    20
Info            Order 21 cancelled    21
Info            Order 22 cancelled    22

The run was successful and processed 40 rows without errors, the same 40 orders the query found before. Each row's message has the order ID in PK_VALUE, from the Primary Key Column setting. The orders now look like this:

Example:

select status, count(*) as orders
from   orders
group  by status
order  by status;

Output:

STATUS          ORDERS
____________ _________
APPROVED            48
CANCELLED           55
NEW                  2
SHIPPED             45

The 15 cancelled orders became 55, and only the 2 recent NEW orders are left. From now on, the automation runs every night and cancels orders as soon as they are older than seven days.

Things to Know

  • Importing an application disables its automations, so a copy of the application in another environment does not start running them unnoticed. Enable them on the edit page or with APEX_AUTOMATION.ENABLE.
  • To stop an automation, set Schedule Status to Disabled, or call APEX_AUTOMATION.DISABLE with the application ID and the automation's static ID, here cancel-unapproved-orders.
  • Test the query on its own before activating the schedule: the automation acts on every row it returns.

Related Guides

Conclusion

To run a scheduled task in Oracle APEX, create a Scheduled automation with a query that returns the rows to work on, and write the work in its action, using the query's columns as bind variables and APEX_AUTOMATION.LOG_INFO for messages.

Set the Schedule Status to Active, choose the primary key and commit settings, run it once with Save and Run, and check the log before leaving it to run on its own.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted