Tips for APEX Application Constants
How to use Text Messages for Constants
It's very common for APEX application to have application level items (usually these are named APP_...
or G_...
and are defined in Shared Components > Application Items). For values that are unique to a given user/session application items are a logical place to store them (ex: APP_USER_ID
). When the item contains a value a new row is inserted into the apex_application_items
table (this is really a view but there's an underlying table that stores the value).
If an application item is constant for the entire application (regardless of user/session) then it may not make sense for a new row to be created to store a session state value. For example, suppose you had the following setup:
Application item called
APP_NAME
Set for each session based on a value in a lookup table
In dev you set to
Demo Dev
, test:Demo Test
, and production:Demo
This means that the following would occur for every session:
Computation or process
on new instance
to load value from lookup tableA new row is created in
apex_application_items
for every session
The above steps would happen for every session despite the fact that the value does not change. In smaller systems this may not matter however on higher volume systems or environments with lots of applications this may add additional overhead.
Solution
To avoid the additional overhead you can use a Text Message. Text Messages are primarily intended for translation purposes however they also allow developers to have configurable application constants. Text messages are different than Application Settings in the sense that they can be referenced in APEX as a substitution string.
The following example shows how to use text messages for this purpose.
Go to Shared Components > Text Messages
Click Create Text Message
and add the following:
On the login page (or this can be anywhere in the application where you want a dynamic application name) change the region title to: &APP_TEXT$APP_NAME.
More information about referencing text messages as substitution strings can be found in docs.
When the page is run it shows Demo Dev
as expected:
To change this in other environments it's unrealistic to set the value via the APEX application builder as most developers won't have access to Test and Prod instances. Instead it can be easily set through the API apex_lang.update_message
As part of your release process after the APEX application has been update the following code should be run to set the value:
declare
c_apex_app_id apex_application_translations.application_id%type := 200;
l_translation_entry_id apex_application_translations.translation_entry_id%type;
begin
select
aat.translation_entry_id
into
l_translation_entry_id
from apex_application_translations aat
where 1=1
and aat.application_id = c_apex_app_id
and aat.translatable_message = 'APP_NAME'
;
-- Detect if in APEX already
-- Usually necessary as this should be run as a post-install script in SQLcl
--
-- If you're not in an APEX application you'll get following error:
-- ORA-20001: Package variable g_security_group_id must be set.
--
-- May get ORA-20987: APEX - An API call has been prohibited.
-- If so go to Shared Components > Security Attributes
-- Check box: Runtime API Usage > Modify This Application
--
if apex_application.g_flow_id is null then
apex_session.create_session (
p_app_id => c_apex_app_id,
p_page_id => 1,
p_username => 'dummy'
);
end if;
-- Set text message:
apex_lang.update_message (
p_id => l_translation_entry_id,
-- Note: This value should come from a lookup table
p_message_text => 'Dev Test'
);
-- Commit is required for changes to take affect
commit;
end;
/
After running this script the login page will show the update application name:
Closing Remarks
I've used this technique in a very high-use application that can have between 300,000 ~ 500,000 sessions a day. The application has about 10 application constants. If Application Items were used for these constants it would result in 10 x 500,000
(5 Million) unnecessary extra writes occurring every day to store values that don't change.
I also found that there were some places "regular" substitution strings did not work (using an Application Item or Page Item) but worked for Text Messages. These were extreme edge cases.
When this technique is used you need to ensure that you have a good release process. I.e. right after the APEX application is installed/updated in each environments the text messages need to be updated as they will contain the "original" text message from the application export.