<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Declarative Diaries]]></title><description><![CDATA[Writing about Oracle APEX, low-code, and the art of keeping things simple.]]></description><link>https://www.aleskravos.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 29 Apr 2026 12:49:21 GMT</lastBuildDate><atom:link href="https://www.aleskravos.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Organising Oracle APEX Apps]]></title><description><![CDATA[Introduction
As time passes, multiple applications are created inside an APEX workspace. This often happens because we structure our solutions into separate applications per module, but also because we tend to create additional applications for proto...]]></description><link>https://www.aleskravos.com/organising-oracle-apex-apps</link><guid isPermaLink="true">https://www.aleskravos.com/organising-oracle-apex-apps</guid><category><![CDATA[Apex Tips]]></category><category><![CDATA[orclapex]]></category><dc:creator><![CDATA[Aleš Kravos]]></dc:creator><pubDate>Sat, 13 Dec 2025 17:18:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765645765774/5ebd0c8c-10ee-4e0e-8a6e-56b15a0f220b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>As time passes, multiple applications are created inside an APEX workspace. This often happens because we structure our solutions into separate applications per module, but also because we tend to create additional applications for prototyping and backups. If we add some utility applications that support the development process, the Application Builder can soon start to look something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765639487209/87b0d5c5-bdd1-4dd7-a7ff-294ee4a6e641.png" alt class="image--center mx-auto" /></p>
<p>Like an average Windows desktop. Cluttered, making you lose time searching for the application you want to edit or run.</p>
<p>I’m not the most patient guy around, so I get frustrated quickly when I see someone moving their mouse around, trying to pick the right application. That’s why I decided to share with the community how I organise my APEX applications.</p>
<h1 id="heading-application-groups">Application Groups</h1>
<p>If my workspace has more than five applications, I start assigning them to Application Groups. You can find this feature under Workspace Utilities.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765639872589/440ca049-3cf0-480b-a632-e32f4540eb1b.png" alt class="image--center mx-auto" /></p>
<p>I prefix each group name with a number for sorting purposes and add a descriptive title that represents the associated applications.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765644955027/2552372f-9634-4d54-befb-79ab38481bee.png" alt class="image--center mx-auto" /></p>
<p>I create application groups based on the environment or project context, but there are two groups I use consistently:</p>
<h2 id="heading-10-development">10 Development</h2>
<p>This group contains all applications that are in active development. These are typically the applications most frequently accessed by developers.</p>
<p>If more than five applications are being actively developed, I split this group further — either by database schema or by functional area (for example: <em>10 Development Finance</em>, <em>20 Development Inventory</em>, …).</p>
<h2 id="heading-20-tools">20 Tools</h2>
<p>This group contains utility applications that support the development process. Some examples of applications I often use:</p>
<h3 id="heading-master-and-template-applications">Master and template applications</h3>
<p>With these two applications, I enable centralised management of Shared Components that are used across multiple applications.</p>
<p>The template application also contains configuration common to all applications. This way, I don’t need to set everything up from scratch when creating a new application. I simply create it as a copy of the template. By copying the application, Shared Component subscriptions to the master application are included automatically.</p>
<h3 id="heading-apex-project-eyehttpswwwunited-codescomproductsapexprojecteye"><a target="_blank" href="https://www.united-codes.com/products/apexprojecteye/">APEX Project Eye</a></h3>
<p>This product by UNITED CODES is my companion on all development projects. We use it as a team to boost development productivity by extending application insights and enforcing Quality Assessments before delivering to the test environment.</p>
<h3 id="heading-domehttpsgithubcomzoranticadome"><a target="_blank" href="https://github.com/zorantica/dome">DOME</a></h3>
<p>This open-source utility, delivered by my colleague Zoran Tica, helps the team prepare installation packages and manage releases.</p>
<h3 id="heading-project-management-applications">Project Management Applications</h3>
<p>On some projects, we use our own custom application to manage work, in addition to classic tools like JIRA. Sometimes, we create advanced reporting on top of these tools by importing data from tickets using REST APIs</p>
<h2 id="heading-other-application-groups">Other Application Groups</h2>
<p>Other application groups vary from project to project. Here are some examples I’ve used in the past.</p>
<h3 id="heading-prototypes-and-sandboxes">Prototypes and Sandboxes</h3>
<p>These are playground applications used to try out new implementation concepts, prepare demonstrations, or redesign features without the risk of breaking the main applications.</p>
<p>Application Working Copies are also a valid option for such scenarios, but I prefer to use them primarily for new development.</p>
<p>Applications in this group should be removed regularly if they are no longer needed.</p>
<h3 id="heading-published-applications">Published Applications</h3>
<p>If applications are no longer actively developed, I move them to this separate group. This keeps the <em>10 Development</em> group clean and focused, as developers don’t need to access these applications frequently anymore.</p>
<h3 id="heading-education-materials">Education Materials</h3>
<p>Applications which are used mainly for training sessions. I keep these applications because they are often helpful when onboarding new developers.</p>
<h3 id="heading-backups-and-snapshots">Backups and Snapshots</h3>
<p>I don’t usually create application copies solely for backup purposes, but I often see workspaces cluttered with multiple copies.</p>
<p>I recommend removing all unnecessary copies and keeping only the latest or important milestone snapshots. For backups, I strongly prefer using Git repositories where application source code is exported and versioned.</p>
<p>That said, on a recent APEX migration project, I deliberately kept old application versions so we could compare behaviour and look before and after the migration.</p>
<h3 id="heading-generated-applications">Generated Applications</h3>
<p>I created this group during an Oracle Forms to APEX migration project where we used <a target="_blank" href="https://pitss.com/products/forms2apex-modeler/"><strong>PITSS.CON Forms2APEX Modeler</strong></a> to generate APEX applications based on Oracle Forms Code.</p>
<p>We typically keep the generated applications unchanged and copy relevant generated components into the applications under active development.</p>
<h1 id="heading-private-report-in-the-application-builder">Private Report in the Application Builder</h1>
<p>After creating application groups and assigning applications to them, I create my own <strong>private report</strong> in the Interactive Report on the Application Builder page.</p>
<p>Steps:</p>
<ol>
<li><p>Switch from <strong>Cards View</strong> to <strong>Report View</strong></p>
</li>
<li><p>Add the <strong>Group</strong> column</p>
</li>
<li><p>Create a <strong>Control break</strong> on the Group column</p>
</li>
<li><p>Sort primarily by <strong>Group</strong>, and secondarily by <strong>Application ID</strong> or <strong>Last Updated</strong> (based on preference)</p>
</li>
<li><p>Save the Report</p>
</li>
</ol>
<p>After this, the Application Builder becomes much easier to navigate.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765644374338/794058d8-6066-48fa-a1db-89c59b132954.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-page-groups">Page Groups</h1>
<p>The same concept can be used to organise pages as well. This functionality is a bit more hidden and can be found under Application Utilities.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765823737061/9a668909-b63a-47af-b8e7-7f37cb5cd4af.png" alt class="image--center mx-auto" /></p>
<p>I use Page Groups in the majority of my projects instead of relying on page ID ranges, as I find them easier to manage and much more flexible when restructuring applications later on. I also use Page Groups when building custom reports based on APEX dictionary views (ie. grouping issues in Quality Assessments or analysing user activity reports)</p>
<p>As with Application Groups, I like to prefix Page Group names with numbers to control their ordering. My main functional modules are usually prefixed with 10, 20, and so on, while administration-related pages typically go under 99.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765825343304/99ac18d1-a24d-464f-95b2-a49755dcb1c9.png" alt class="image--center mx-auto" /></p>
<p>I would expect more native functionality in APEX around Application and Page Groups, especially when it comes to reporting capabilities and mass updates.</p>
<h1 id="heading-summary">Summary</h1>
<p>I always try to remove things I no longer need in my development environment and organise what remains in a meaningful way. If only I were as consistent with my things back at home, my wife would probably be a happier person 😅</p>
<p>I hope this tip helps you organise your Application Builder better and saves you a second or two every day.</p>
]]></content:encoded></item><item><title><![CDATA[Is There a Real Alternative to APEX_ITEM in Oracle APEX?]]></title><description><![CDATA[Introduction
This blog was inspired by a conversation with my dear colleague, Zoran Tica. While tackling a random technical challenge in Oracle APEX, we made the following assumption: there is no alternative for APEX_ITEM. I decided to investigate fu...]]></description><link>https://www.aleskravos.com/apex-item-alternatives-in-oracle-apex</link><guid isPermaLink="true">https://www.aleskravos.com/apex-item-alternatives-in-oracle-apex</guid><category><![CDATA[apex_item]]></category><category><![CDATA[template components]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Low Code]]></category><dc:creator><![CDATA[Aleš Kravos]]></dc:creator><pubDate>Mon, 24 Nov 2025 16:09:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764164786547/9ddac597-4416-4a52-ac36-b55b6eab457d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>This blog was inspired by a conversation with my dear colleague, Zoran Tica. While tackling a random technical challenge in Oracle APEX, we made the following assumption: there is no alternative for APEX_ITEM. I decided to investigate further to determine if this assumption holds true.</p>
<h2 id="heading-about-apexitem">About APEX_ITEM</h2>
<p>APEX_ITEM is a <strong>PL/SQL API</strong> that generates the HTML needed to add various types of input fields to your report regions. By looping through the returned records, you can process user input during page processing using custom PL/SQL code.</p>
<p>This API was widely used by developers to introduce interactivity into their reports or to support more dynamic, custom-built input forms. For example, the following region source:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span>
  apex_item.checkbox(<span class="hljs-number">1</span>) sel,
  apex_item.hidden(<span class="hljs-number">2</span>, empno) ||
  apex_item.text(<span class="hljs-number">3</span>, ename, <span class="hljs-string">'size=10'</span>) ename,
  job,
  apex_item.date_popup(<span class="hljs-number">4</span>, <span class="hljs-keyword">rownum</span>, hiredate, <span class="hljs-string">'DD.MM.YYYY'</span>) hiredate,
  apex_item.text(<span class="hljs-number">5</span>, sal, <span class="hljs-string">'size=6'</span>) || <span class="hljs-string">' €'</span> sal,
  apex_item.select_list(
    p_idx         =&gt; <span class="hljs-number">6</span>,
    p_value       =&gt; deptno,
    p_list_values =&gt; <span class="hljs-string">'ACCOUNTING;10,RESEARCH;20,SALES;30,OPERATIONS;40'</span>,
    p_show_null   =&gt; <span class="hljs-string">'YES'</span>,
    p_null_text   =&gt; <span class="hljs-string">'-Select-'</span>,
    p_item_id     =&gt; <span class="hljs-string">'f06_#ROWNUM#'</span>
  ) department
<span class="hljs-keyword">FROM</span> emp
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> empno;
</code></pre>
<p>would render like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762800302731/4b60b2c4-0346-4562-8c0b-6852b807a18d.png" alt class="image--center mx-auto" /></p>
<p>and can be handled with the following PL/SQL process:</p>
<pre><code class="lang-sql">FOR i IN 1 .. apex_application.g_f01.count LOOP
  <span class="hljs-keyword">UPDATE</span> emp
     <span class="hljs-keyword">SET</span> ename    = apex_application.g_f03(i),
         hiredate = <span class="hljs-keyword">TO_DATE</span>(apex_application.g_f04(i), <span class="hljs-string">'DD.MM.YYYY'</span>),
         sal      = apex_application.g_f05(i),
         deptno   = apex_application.g_f06(i)
   <span class="hljs-keyword">WHERE</span> empno    = apex_application.g_f02(i);
<span class="hljs-keyword">END</span> <span class="hljs-keyword">LOOP</span>;
</code></pre>
<h2 id="heading-this-api-is-marked-as-legacy">This API is marked as legacy</h2>
<p>Many of us raised our eyebrows when the API was marked as <strong>legacy</strong> in the APEX 20.2 release.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762796782664/17313471-6d88-4848-a291-0e06e747ff0f.png" alt="APEX 20.2 API Documentation" class="image--center mx-auto" /></p>
<p>This means the API can still be used, but it should not be used for new development. Existing applications will continue to work, as backward compatibility has always been a high priority for APEX. However, there are several reasons why you should consider replacing it:</p>
<ul>
<li><p>It bypasses important security features, such as XSS protection and session state protection.</p>
</li>
<li><p>It sidesteps APEX’s validation and dynamic action framework.</p>
</li>
<li><p>Its output is not aligned with Universal Theme styling.</p>
</li>
</ul>
<p>Given how commonly it was used, you might have expected a clearly documented alternative, right? But until now, there hasn’t been an officially defined replacement.</p>
<p>That still doesn’t mean no alternatives exist.</p>
<p>As my colleague Zoran likes to say on (too) many occasions: <em>“It depends.”</em> And indeed, it really does depend on the use case.</p>
<h2 id="heading-use-case-1-multiline-editing">Use Case 1 - Multiline editing</h2>
<p>APEX_ITEM was one of the building blocks of the now-desupported Tabular Forms. These forms were the predecessor of the Interactive Grid when it came to multiline editing. So if you need a report where users can edit multiple records directly, then in most cases you should either:</p>
<ul>
<li><p><strong>Use an Interactive Grid</strong>, which is the official successor to Tabular Forms, or</p>
</li>
<li><p><strong>Abandon multiline editing for the region</strong> and use a modal form page on top of your Interactive or Classic Report. I often see developers force multi-line editing instead of single record editing without any real business case behind it. Single record editing can be handled a lot more easily and is often more user-friendly and convenient to the end user.</p>
</li>
</ul>
<h2 id="heading-use-case-2-dynamic-forms">Use Case 2 - Dynamic forms</h2>
<p>Some developers used APEX_ITEM to generate input fields dynamically based on context — for example, flexible forms driven by product category or metadata.</p>
<p>APEX still does not offer a native, declarative equivalent for <em>fully dynamic</em> input generation.</p>
<p>If you need this pattern, one option is a commercial plugin:<br /><strong>FlowForms by United Codes</strong><br /><a target="_blank" href="https://www.united-codes.com/ords/r/pip/flowforms/2">https://www.united-codes.com/ords/r/pip/flowforms/2</a></p>
<h2 id="heading-use-case-3-row-selection-in-reports">Use Case 3: Row Selection in Reports</h2>
<p>I could be wrong, but my assumption is that in most cases developers use APEX_ITEM to add checkboxes to their Classic and Interactive Reports so they can provide <strong>row selection</strong> capabilities. That has certainly been the case in many APEX applications I have encountered.</p>
<p>For this use case, Oracle APEX now offers several native alternatives. Let’s take a look at the built-in options and walk through each one.</p>
<h2 id="heading-dropdown-page-items-with-multiselect"><strong>Dropdown Page Items with Multiselect</strong></h2>
<p>I know that using page items for multi-selection isn’t the same as selecting rows in a report. However, I’ve seen many scenarios where a simple multiselect dropdown solved the requirements just as well. And with recent APEX versions, the available options are actually quite good. Three page item types can serve as alternatives to a multi-select report.</p>
<p>The <strong>Popup LOV</strong>, which was redesigned in APEX 19.2, continues to improve in later versions. It is still the only item type that supports multiple columns in the inline dialog. Selecting multiple values can feel a bit cumbersome because the user has to reopen the dialog after each selection.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763494356525/17481e58-e1f2-45f4-b65f-58acea8f1b22.png" alt class="image--center mx-auto" /></p>
<p>The <strong>Combobox</strong> item, introduced in APEX 23.2, handles multiple selection much more conveniently. The user can select multiple records directly by clicking the checkboxes. If records were pre-selected when the page was rendered, those rows are already marked as selected. The display value can also be formatted using HTML expressions and template directives.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763908439527/ba6eb616-6b8d-4990-bc03-1b8a5fc099ce.png" alt class="image--center mx-auto" /></p>
<p>The <strong>Select-Many</strong> page item type, introduced in APEX 24.1, is very similar to the Combobox. I had to look quite closely to understand the differences. Select-Many does not allow the user to add new values that are not part of the LOV source query, while the Combobox does. On the other hand, Select-Many is a bit more user-friendly because it shows a badge with the total number of selected records, and clicking that badge filters the list to display only the selected items.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763909163978/e0d089db-53c3-4460-b187-291f58f8967e.png" alt class="image--center mx-auto" /></p>
<p>For all three page item types you can define how the multiple values are stored in the session state. They can be stored as comma-separated values (for example: <code>APEX,SQL,PL/SQL</code>), which you can process with the APEX_STRING API:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">column_value</span> <span class="hljs-keyword">from</span> apex_string.split ( :ITEM_NAME, <span class="hljs-string">','</span> );
</code></pre>
<p>Or they can be stored in JSON format (for example: <code>["APEX", "SQL", "PL/SQL"]</code>), which you can handle using the JSON_TABLE SQL function:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span>
    <span class="hljs-keyword">element</span>
<span class="hljs-keyword">from</span>
    json_table ( :ITEM_NAME, <span class="hljs-string">'$[*]'</span>
        <span class="hljs-keyword">columns</span>
            <span class="hljs-keyword">element</span> <span class="hljs-built_in">varchar2</span> <span class="hljs-keyword">path</span> <span class="hljs-string">'$'</span>
    );
</code></pre>
<h3 id="heading-interactive-grid-row-selector">Interactive grid - row selector</h3>
<p>In APEX 24.1 it became easier to use the native row selector in the Interactive Grid to achieve multiselect functionality. You can define the page item where the selected values are stored by updating the Interactive Grid’s Initialization JavaScript Function in the Attributes tab:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> config </span>) </span>{
  config.defaultGridViewOptions = {
    <span class="hljs-attr">selectionStateItem</span>: <span class="hljs-string">"P3_SELECTED_IDS"</span>,
    <span class="hljs-attr">multiple</span>: <span class="hljs-literal">true</span>
  };
  <span class="hljs-keyword">return</span> config;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763910983663/1e37a489-0c13-4bde-b4d7-d280288a7931.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-template-components">Template components</h3>
<p>Declarative row selection options were added to Template Components in APEX 24.1. From a user experience point of view, this is similar to the Combobox and Select-Many items, but it allows for more customization and flexibility.</p>
<p>To enable row selection, you first define which column in the report serves as the primary key. After that, you can turn on row selection in the Attributes tab.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763911614725/c614131e-bd53-4202-9ec0-09b19b1278c9.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763911600377/fb4f63d2-89a6-4de7-ad44-35c5b88bf52d.png" alt /></p>
<p>The only thing I am missing in Template Components is the ability to define column headers. Because of that limitation, Template Components may not be a suitable alternative when you need a multi-column report where you previously used APEX_ITEM for row selection. Without column headers, it is difficult to achieve a simple, traditional tabular layout.</p>
<h2 id="heading-when-is-it-hard-to-say-goodbye-to-apexitem"><strong>When Is It Hard to Say Goodbye to APEX_ITEM</strong></h2>
<p>As mentioned earlier, APEX_ITEM is still very useful when you need to build dynamically generated input forms, and this is an area where native APEX features cannot fully replace it.</p>
<p>The same applies to dynamic reports. Sometimes you need to squeeze an input field directly into a column’s output, or conditionally show a checkbox only for certain rows. These patterns are difficult to reproduce with purely declarative components. Here is a simple example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763998791737/a548c8a3-3de7-403b-88d7-d83b6cd1812b.png" alt class="image--center mx-auto" /></p>
<p>Region source:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span>
    <span class="hljs-keyword">CASE</span>
        <span class="hljs-keyword">WHEN</span> job = <span class="hljs-string">'SALESMAN'</span> <span class="hljs-keyword">THEN</span>
            APEX_ITEM.CHECKBOX(<span class="hljs-number">1</span>)
        <span class="hljs-keyword">ELSE</span>
            <span class="hljs-literal">NULL</span>
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">AS</span> sel,
    APEX_ITEM.HIDDEN(<span class="hljs-number">2</span>, empno)
    || APEX_ITEM.TEXT(<span class="hljs-number">3</span>, ename) <span class="hljs-keyword">AS</span> ename,
    job,
    APEX_ITEM.DATE_POPUP(<span class="hljs-number">4</span>, <span class="hljs-keyword">ROWNUM</span>, hiredate, <span class="hljs-string">'DD.MM.YYYY'</span>) <span class="hljs-keyword">AS</span> hiredate,
    <span class="hljs-keyword">CASE</span>
        <span class="hljs-keyword">WHEN</span> job = <span class="hljs-string">'SALESMAN'</span> <span class="hljs-keyword">THEN</span>
            sal || <span class="hljs-string">' € --&gt; '</span> || APEX_ITEM.TEXT(<span class="hljs-number">5</span>, <span class="hljs-literal">NULL</span>) || <span class="hljs-string">' €'</span>
        <span class="hljs-keyword">ELSE</span>
            sal || <span class="hljs-string">' €'</span>
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">AS</span> sal
<span class="hljs-keyword">FROM</span> emp
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> empno;
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>While it will be difficult to remove APEX_ITEM for every use case, it has never been easier to achieve row selection declaratively in Oracle APEX. In the past this was often a cumbersome task, but today the platform offers several native ways to handle it without falling back to APEX_ITEM. For row selection use cases, these options are more than capable, and I see no reason to continue using APEX_ITEM for that purpose alone. In most scenarios there is already a suitable replacement in the APEX toolbox.</p>
<p>You should definitely evaluate the alternatives and replace APEX_ITEM wherever possible, rather than burden your future self with legacy components.</p>
<p>That said, I am sure it will take time before APEX_ITEM disappears from our applications entirely. And unless the APEX team introduces a direct, one-to-one equivalent, it will likely remain present in legacy code for quite a while.</p>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Quality Assurance in APEX Project Eye (APE)]]></title><description><![CDATA[Introduction
One of the wonderful things about Oracle APEX is that all the metadata of our applications is stored in the database and accessible through the APEX dictionary views. It would almost be a crime to avoid taking advantage of this for all s...]]></description><link>https://www.aleskravos.com/getting-started-with-quality-assurance-in-apex-project-eye-ape</link><guid isPermaLink="true">https://www.aleskravos.com/getting-started-with-quality-assurance-in-apex-project-eye-ape</guid><category><![CDATA[APEX Project Eye]]></category><category><![CDATA[orclapex]]></category><category><![CDATA[Quality Assurance]]></category><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Aleš Kravos]]></dc:creator><pubDate>Sun, 08 Jan 2023 12:29:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/5fNmWej4tAA/upload/928d4e270cfefc52f997fce915e6cabc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>One of the wonderful things about Oracle APEX is that all the metadata of our applications is stored in the database and accessible through the APEX dictionary views. It would almost be a crime to avoid taking advantage of this for all sorts of possibilities.</p>
<p>We all follow coding guidelines or organizational policies to keep our solutions secure, consistent, and easy to maintain. Or at least we <strong>should</strong> follow them, but we all know this is only sometimes the case, especially in larger teams.</p>
<p>With APEX applications, it’s a walk in the park to validate if our standards are followed just by writing simple queries on the dictionary views.</p>
<h2 id="heading-writing-quality-rules">Writing Quality Rules</h2>
<p>Let’s take one commonly known security measure to prevent broken authentication in your application: Protecting your pages with authorization schemes.</p>
<p>If you want to check which pages are not protected with authorization schemes, you can just run this simple SQL statement:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
  <span class="hljs-keyword">from</span> apex_application_pages
 <span class="hljs-keyword">where</span> authorization_scheme <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>
</code></pre>
<p>When looking at the results, we realize that it makes no sense to include publicly accessible pages like our login page, and also, page 0 cannot be protected with an authorization scheme. In the end, our statement should look something like this:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
  <span class="hljs-keyword">from</span> apex_application_pages
 <span class="hljs-keyword">where</span> authorization_scheme <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>
   <span class="hljs-keyword">and</span> page_id != <span class="hljs-number">0</span>
   <span class="hljs-keyword">and</span> page_requires_authentication = <span class="hljs-string">'Yes'</span>
</code></pre>
<p>And this is how to get a list of all our pages that could cause an unnecessary security risk, so we fix them one by one. Easy right? But of course, it doesn't stop here. We could query to see if all our SAVE buttons are labelled and formatted consistently throughout the application if naming conventions are being followed, and all sorts of best practice guidelines.</p>
<h2 id="heading-creating-quality-rules-and-standards-in-ape">Creating Quality Rules and Standards in APE</h2>
<p>Not all developers are familiar with the APEX Dictionary views, and the library can be overwhelming. Also, running SQL statements one by one is time-consuming, so we want to validate our application code with a Quality Assurance framework that makes our lives even easier.</p>
<p>APEX Project Eye (APE) is one of a handful of available tools which can comprehensively support your Quality Assurance management.</p>
<p>With the Rule Builder Wizard, anyone who does not know all properties by heart can easily browse through the APEX dictionary views and get a preview of the most common values in their metadata to help find the correct attribute.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673179859106/fc72324c-b550-497a-a5c8-73d4a467f9f8.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673179819345/7156f0d5-9bc9-4a4f-8329-51310c8e9967.png" alt class="image--center mx-auto" /></p>
<p>The Rule Builder generates the SQL statement for you with the component key attribute, which is the only required field for APE Quality rules:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180261212/5a709d3f-16e5-4bcc-991c-55a06df97c38.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180164176/41fec316-2edb-4271-8664-2a867d9c99a5.png" alt class="image--center mx-auto" /></p>
<p>Each rule can and should be described with its own metadata, giving the QA practitioner vital information about the rule, its justification, and steps to resolve the issue.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180278007/04eda9e1-f125-4870-a60a-6484147a97e4.png" alt class="image--center mx-auto" /></p>
<p>Quality rules are listed in Quality Standards, which represent your organizational guidelines, with a severity level for each rule defining how significant a violation of that rule is for you and your organization. And in case you lack some inspiration, APEX Project Eye delivers over 40 prebuilt rules included in the UNITED CODES Way of Working Quality Standards, which you can use or copy as templates. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180288059/dc63d6b4-eafc-44f4-8b98-2394a7e3c8f6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-running-quality-assessments">Running Quality Assessments</h2>
<p>Before running Quality Assessments, you need to define where the Assessments should be run and which Standards should be assessed. APE offers the following scope levels:</p>
<ul>
<li><p>Workspace</p>
</li>
<li><p>Application</p>
</li>
<li><p>Page Group</p>
</li>
<li><p>Page</p>
</li>
<li><p>Database Schema</p>
</li>
</ul>
<p>It’s also possible to combine multiple scope levels:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180295881/42a2c148-02fb-44bb-80a9-44165c60b100.png" alt class="image--center mx-auto" /></p>
<p>After that, you're ready to roll! Sit back, relax, and wait for your assessment to finish.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180654204/cb36cbe7-e4ae-4884-bf29-65fdbf2fba24.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-browsing-through-the-assessment-results">Browsing Through the Assessment Results</h2>
<p>When the assessment is finalized, you'll need to navigate a vast sea of found issues. APE helps you by offering three different browsing angles: By Rules, By Components, or By Severity:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180629920/cd2fc0e7-a094-481d-8a3f-5a11e42ff67c.png" alt class="image--center mx-auto" /></p>
<p>And here are your issues waiting for you to analyze them and react as you see appropriate. You can mark the issue as an exception to exclude it from this and future assessments or immediately resolve it by clicking the Fix button, which takes you directly to the component in the APEX Page Designer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673180696901/4041a452-a5cb-47b7-a3aa-b418c030769e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Designing and aligning internally in your team which guidelines must be followed, can require quite some time and patience. But with a Quality Management Framework, it’s simple to implement and make QA Assessments part of your development lifecycle. </p>
<h2 id="heading-useful-links">Useful links</h2>
<p><a target="_blank" href="https://www.apexprojecteye.com/">APEX Project Eye</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=ZY4UkqDTIDQ&amp;t=14s">https://www.youtube.com/watch?v=ZY4UkqDTIDQ&amp;t=14s</a></div>
]]></content:encoded></item></channel></rss>