<?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[Dimitri Gielis writing about Oracle APEX]]></title><description><![CDATA[Passionate about bringing ideas to life with code. Founder and CEO of United Codes and APEX R&D. Love the Oracle Database and Oracle Application Express (APEX).]]></description><link>https://dgielis.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 02:20:22 GMT</lastBuildDate><atom:link href="https://dgielis.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Setting Up Your APEX Developer Environment for the AI Era]]></title><description><![CDATA[In the previous post I talked about how the role of the Oracle APEX developer is changing. AI is changing how we write code, how we think about problems, and how fast we can move. But before we can sh]]></description><link>https://dgielis.com/setting-up-your-apex-developer-environment-for-the-ai-era</link><guid isPermaLink="true">https://dgielis.com/setting-up-your-apex-developer-environment-for-the-ai-era</guid><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Wed, 15 Apr 2026 17:16:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/62cf5116466c6ad9ff5d7d6e/1ebab7dd-7dc8-4eac-93fa-6f929a0a8680.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the <a href="https://dgielis.com/the-apex-developer-reinvented">previous post</a> I talked about how the role of the Oracle APEX developer is changing. AI is changing how we write code, how we think about problems, and how fast we can move. But before we can show any of that in action, we need a proper setup.</p>
<p>My mentor in my early career, <a href="https://www.rittmanmead.com/blog/2005/04/tom-kyte-in-search-of-the-truth/">Tom Kyte's, mantra</a> was, don't just believe what "experts" say, ask for proof. As things change so fast, especially with AI, it's important to test if things are still valid when you read this article.</p>
<p>So in this post I want to walk through the development environment I use today, which you can 100% reproduce and follow along on your own machine. It is a bit different than what I had back <a href="https://dgielis.blogspot.com/2017/08/from-idea-to-app-or-how-i-do-oracle.html">in 2017</a>, but it is also way more powerful.</p>
<p>Let me go through it step by step.</p>
<h2>The Editor: VS Code</h2>
<p>I use <strong>Visual Studio Code</strong> as my main editor. It is free, fast, and has a huge ecosystem of extensions. For <a href="https://apex.oracle.com">Oracle APEX</a> development, these are the extensions I have installed:</p>
<ul>
<li><p><strong>Oracle SQL Developer Extension for VS Code</strong> is the one I start with. It gives you database connections, SQL execution, object browsing, and a lot more, all from inside VS Code.</p>
</li>
<li><p><strong>dbLinter</strong> helps you keep your SQL and PL/SQL clean. It catches issues early and helps you stay consistent across a project.</p>
</li>
<li><p><strong>QuickSQL Preview</strong> is one of my favorites. If you have never heard of QuickSQL, it is a shorthand language developed by Oracle that lets you describe your data model in plain text and generate ready-to-run SQL from it. We at United Codes <a href="https://github.com/United-Codes/quicksql">forked it</a> and made many enhancements to it. The VS Code extension gives you a live preview as you type and even a visual ERD. You can <a href="https://github.com/dgielis/apex-developer-reinvented/blob/main/quicksql-preview-0.1.5.vsix">download</a> the open source version.</p>
</li>
<li><p><strong>Claude Code</strong> and <strong>Codex</strong> as AI coding assistant. Both Claude and Codex are super good, and within <a href="https://www.united-codes.com">United Codes</a> we use both (and even others). Pick one and continue.</p>
</li>
</ul>
<h2>The Terminal</h2>
<p>I use <strong>iTerm2</strong> on macOS. It supports split panes, profiles, and a lot of shortcuts that make life easier when you are switching between the AI Assistant, SQLcl, and Git all day.</p>
<h2>Claude Code CLI (or app)</h2>
<p><strong>Claude Code</strong> runs as a CLI and works directly in your terminal, in your project directory, with your files. It understands context, it can read your codebase, and it can take real actions.</p>
<p>You install it via npm:</p>
<pre><code class="language-shell">npm install -g @anthropic-ai/claude-code
</code></pre>
<p>This is more than autocomplete. Claude Code can browse your files, run commands, write SQL, generate PL/SQL packages, create APEX export scripts, update GitLab issues, and a lot more. We will use it heavily throughout this series.</p>
<p>The most important file for Claude Code in any project is the <strong>CLAUDE.md</strong> file. I will do a dedicated post on that, but in short: it is a markdown file you put at the root of your project repo. It tells Claude Code what the project is about, what conventions to follow, what tools to use, and what not to do. Without a good CLAUDE.md, Claude Code is just a smart tool. With a good one, it becomes a real team member that knows your project. We will also add skills, basically other .md files, to Claude, which will give it specific knowledge about the Oracle database, APEX and our way of working.</p>
<h2>Codex CLI (or app)</h2>
<p>An alternative to Claude is <strong>Codex</strong>. Similarly, Codex runs as a CLI and works directly in your terminal, in your project directory, with your files. It understands context, it can read your codebase, and it can take real actions.</p>
<p>You install it via npm:</p>
<pre><code class="language-shell">npm install -g @openai/codex
</code></pre>
<p>Similary to Claude, you also have a file to define everything, in Codex this is the <strong>AGENTS.md</strong> file. Skills are also used to give Codex more specific knowledge.</p>
<h2>AI Skills for the Oracle Database and APEX</h2>
<p>One thing I find really useful is the <strong>oracle-db-skills</strong> project by Kris Rice, which you find <a href="https://github.com/krisrice/oracle-db-skills">here</a>.</p>
<p>This is a curated library of 100+ practical guides covering Oracle Database topics, from SQL and PL/SQL development to security, migrations, and DevOps, organized into skill files by domain.</p>
<p>Another one not released yet, but foreseen by Oracle, are the APEXLang skills. APEXLang is the new format of an Oracle APEX app, which makes it much easier for any AI Assistant to produce APEX apps (APEXLang files).</p>
<p>With United Codes we also developed our own skills, for example we define our conventions, to always use utPLSQL to create PL/SQL tests, use the <a href="https://github.com/Grisselbav/dbLinter/releases">dbLinter</a> CLI to check the code etc.</p>
<h2>Source Control</h2>
<p>Use <strong>GitLab</strong> or <strong>GitHub</strong> for source control.</p>
<p><strong>GitHub Desktop</strong> gives me a visual view of what has changed in my local repos. Even though I use GitLab/GitHub for the actual remote, GitHub Desktop works fine as a local Git GUI.</p>
<p>The <strong>glab</strong> CLI tool lets you interact with GitLab from the terminal: create issues, link commits, open merge requests, and more. This matters because the AI Assistant can use <a href="https://gitlab.com/gitlab-org/cli">glab</a> to manage your project as part of its workflow. It creates issues when it finds something to fix, it links commits to issues, and it keeps your project board up to date.</p>
<h2>SQLcl</h2>
<p><strong>SQLcl</strong> is Oracle's command-line interface for the database. It is lightweight, scriptable, and supports Liquibase-based database change management out of the box through <strong>SQLcl Projects</strong>. I use it for everything from quick queries to deploying schema changes. Download <a href="https://www.oracle.com/database/sqldeveloper/technologies/sqlcl/">here</a>.</p>
<p>SQLcl Projects is how we manage database changes in a structured way. It tracks what has been applied, keeps your DDL in version control, and integrates nicely with CI/CD pipelines. Our AI assistant knows how to work with SQLcl, which makes this combination really powerful.</p>
<h2>Local Development Environment</h2>
<p>For local development I run everything in <strong>Docker</strong>. My stack consists of two containers:</p>
<p><strong>Oracle Database 26ai</strong> as I still believe this is the best database in the world, now with a lot of AI capabilities built in. Oracle provides a free Docker image. This local database syncs with the main DEV database (in the cloud).</p>
<p><strong>Oracle APEX + ORDS</strong>. Having APEX local means I can develop (together with my AI agents) and test without depending on any shared environment. Fast feedback loop and no interference.</p>
<h2>Automation</h2>
<p><strong>Jenkins</strong> for automation. I use a Jenkins instance to run pipelines: schema deployments, test suites, etc. Jenkins connects to Git and triggers on push.</p>
<h2>Node.js and Playwright</h2>
<p><strong>Node.js</strong> is needed for a few things: installing the AI Assistant, running some tooling, and running <strong>Playwright</strong> for automated browser testing. Playwright lets you write tests that actually open a browser and interact with your APEX application. We will use this later in the series for end-to-end testing.</p>
<p>Install Node.js via: <a href="https://nodejs.org">https://nodejs.org</a> or with Homebrew on macOS (<code>brew install node</code>).</p>
<h2>Browser</h2>
<p>I use <strong>Google Chrome</strong> for testing APEX applications. A few extensions that help: a REST client for testing APIs, and the standard Chrome DevTools are already built in. Nothing exotic needed here.</p>
<h2>Voice</h2>
<p>I really believe English is the new programming language.</p>
<p>I use <strong>SuperWhisper</strong>, which is a macOS app that lets you use your voice to type anywhere on your computer. It runs speech-to-text locally using AI models, so your audio stays private. I use it to dictate prompts for the AI Assistant, write commit messages, or talk through ideas without having to type everything out. It sits in the menu bar and activates with a keyboard shortcut, making it fast to switch between typing and speaking.</p>
<h2>Putting It All Together</h2>
<p>I wanted to make it easy to setup your own environment, so on my <a href="https://github.com/dgielis/apex-developer-reinvented">personal GitHub repo</a> I'm sharing quick starts.</p>
<p>If you have everything above installed and running, you are ready to follow along with the rest of this series, incase you wanted to experience this too.</p>
<h2>Note</h2>
<p>I expect things will keep changing over the coming months, as the world of AI is changing fast. Either I will update this post or create follow-up posts and link to them once available.</p>
]]></content:encoded></item><item><title><![CDATA[The APEX Developer Reinvented]]></title><description><![CDATA[Recently I asked an AI tool to build me a World Cup prediction app.Within a couple of minutes it generated a full application; a React frontend, backend APIs, some database tables. It even came with i]]></description><link>https://dgielis.com/the-apex-developer-reinvented</link><guid isPermaLink="true">https://dgielis.com/the-apex-developer-reinvented</guid><category><![CDATA[orclapex]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Sun, 15 Mar 2026 20:07:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/62cf5116466c6ad9ff5d7d6e/ef45a8b5-5163-4ca5-be42-db70d4a560aa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently I asked an AI tool to build me a World Cup prediction app.<br />Within a couple of minutes it generated a full application; a React frontend, backend APIs, some database tables. It even came with it's own todos, so I could follow along where it was!</p>
<img src="https://cdn.hashnode.com/uploads/covers/62cf5116466c6ad9ff5d7d6e/c1b2f18a-d387-4b31-b414-86abf7ce6cb9.png" alt="" style="display:block;margin:0 auto" />

<p>Everything wired together, deployed on the internet in one time. Pretty impressive!</p>
<p>The prompt I gave was simple:</p>
<blockquote>
<p>Build a web application that lets my friends and me predict the scores of games at the 2026 World Cup.</p>
</blockquote>
<p>You see or hear about these demos everywhere now, some call it vibe-coding.</p>
<p>But then I started thinking; if this was a <strong>real enterprise application</strong>, would I actually deploy this? Probably not.</p>
<p>Not because the AI did a bad job. But because when we build enterprise software, we care about things like:</p>
<ul>
<li><p>security</p>
</li>
<li><p>performance</p>
</li>
<li><p>maintainability</p>
</li>
<li><p>data integrity</p>
</li>
<li><p>predictability</p>
</li>
<li><p>(and so much more)</p>
</li>
</ul>
<p>And that is where the <strong>Oracle Database and Oracle APEX approach</strong> becomes extremely powerful.</p>
<h2>APEX Has Always Been About Productivity</h2>
<p>If you want to build applications on top of the Oracle Database, APEX is the fastest way to do it. Compared to traditional development stacks like Java, .NET, or JavaScript, developers are often <strong>20x more productive</strong> by using the APEX low-code platform. This was the message we gave customers, but I believe today that is no longer the main driver. Instead, the message will change to say that we can produce applications consistent, reliable, secure, and performant.</p>
<h3>The Early Days</h3>
<p>When I first started working with APEX (back then called HTML DB), we often positioned it as a replacement for Excel "databases".</p>
<p>Many organizations had big enterprise systems, but departments still built their own tools in spreadsheets. APEX turned out to be the perfect sweet spot for those applications.</p>
<p>You could quickly build a secure application on top of the Oracle Database and share it with your team.</p>
<p>Back in 2006 I even built <a href="https://dgielis.blogspot.com/2006/05/world-cup-2006-score-in-apex.html">a small application to predict scores with friends for the World Cup</a>. Simple idea, simple app, built quickly. That was exactly the magic of APEX.</p>
<h3>The APEX Community</h3>
<p>Over the years the Oracle APEX community grew tremendously.</p>
<p>More and more developers discovered that APEX was not only good for small departmental apps. It could also power serious enterprise systems.</p>
<p>Instead of traditional development stacks, companies started building:</p>
<ul>
<li><p>ERP systems</p>
</li>
<li><p>CRM systems</p>
</li>
<li><p>internal portals</p>
</li>
<li><p>workflow engines</p>
</li>
<li><p>data management platforms</p>
</li>
</ul>
<p>If there was an Oracle Database, APEX became the logical platform to develop on.</p>
<p>The community played a huge role in that growth. Blogs, plug-ins, conferences, examples everywhere. People sharing ideas and helping each other.</p>
<p>In 2017 I wrote a blog post explaining <a href="https://dgielis.blogspot.com/2017/08/from-idea-to-app-or-how-i-do-oracle.html"><strong>how I personally go from idea to application using APEX</strong></a>. That article describes how I typically build an application from scratch. And honestly, that approach worked really well for many years.</p>
<h3>APEX Becomes Strategic for Oracle</h3>
<p>Another big shift happened around 2020. During COVID, Oracle helped governments build applications extremely fast. APEX played an important role in that effort. At that moment it became clear, even at the highest level within Oracle, how powerful this platform really was.</p>
<p>From then on Oracle started positioning APEX much more prominently as the primary development platform for applications on the Oracle Database.</p>
<p>Before that, Java was often considered the default option. After that, the message became much clearer. If you have an Oracle Database, <strong>APEX should be your first choice for building applications</strong>.</p>
<h2>AI Changes Everything</h2>
<p>But the biggest shift is happening right now.</p>
<p><strong>AI.</strong></p>
<p>In the last few years the use of AI exploded. But for me it is especially in the last months that things really changed. Agentic coding tools like Claude Code, Codex, Cursor and others have become really good. And that changes how we work.</p>
<p>The role of the Oracle APEX developer is no longer just building pages, writing SQL and PL/SQL, and configuring components. We are moving from low coders to something else.</p>
<p>More like:</p>
<ul>
<li><p>designers</p>
</li>
<li><p>orchestrators</p>
</li>
<li><p>validators</p>
</li>
</ul>
<p>AI can generate SQL, PL/SQL code, APIs, and even applications.</p>
<p>But it still needs someone who understands:</p>
<ul>
<li><p>the business problem</p>
</li>
<li><p>the data model</p>
</li>
<li><p>Oracle APEX and the Oracle Database</p>
</li>
<li><p>and when AI is wrong</p>
</li>
</ul>
<p>That person is still the APEX developer.</p>
<p>But the way we work is evolving quickly. I might be wrong, but I believe this:</p>
<p><strong>Developers will not be replaced by AI. But developers using AI will replace those who don't.</strong></p>
<p>We are really in exciting times! By leveraging AI, we as developers can do so much more now and help so many more people.</p>
<h3>A New Series</h3>
<p>So I thought it was a good time to revisit something I wrote years ago.<br />In 2017, I described how I turn an idea into an application with APEX. Now I want to do that again, but this time <strong>with AI in the loop</strong>.</p>
<p>To make it fun, I will rebuild the World Cup prediction app, just like I did back in 2006.</p>
<p>But this time using:</p>
<ul>
<li><p>Oracle Database 26ai</p>
</li>
<li><p>Oracle APEX 24.2 (including ORDS)</p>
</li>
<li><p>AI coding tools like Claude Code</p>
</li>
<li><p>modern development workflows</p>
</li>
</ul>
<p>In the next posts we will go step by step through the process. From idea to working application and we will see how AI changes the way we develop with Oracle APEX.</p>
<p>Generating some PL/SQL with AI is the easy part… in the next posts I want to see if AI agents can handle the entire development lifecycle and build full Oracle APEX applications.</p>
<p>There is a lot to explore 😁</p>
]]></content:encoded></item><item><title><![CDATA[Oracle Database 26ai Assertions in a World Cup Betting App]]></title><description><![CDATA[Recently I was playing again with my World Cup betting application, originally built in 2006 with Oracle APEX. Yes… almost 20 years ago already! 😅
Back then the database enforced some constraints, bu]]></description><link>https://dgielis.com/oracle-database-26ai-assertions-in-a-world-cup-betting-app</link><guid isPermaLink="true">https://dgielis.com/oracle-database-26ai-assertions-in-a-world-cup-betting-app</guid><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Sat, 14 Mar 2026 08:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/62cf5116466c6ad9ff5d7d6e/9b9358e7-e67e-4138-b0d3-30e69f3c736d.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently I was playing again with my World Cup betting application, originally built in 2006 with Oracle APEX. Yes… almost 20 years ago already! 😅</p>
<p>Back then the database enforced some constraints, but many rules lived in the application layer (read APEX validation, processes, and PL/SQL). That was normal at the time.</p>
<p>But with Oracle Database 26ai and Assertions (introduced in 23.26.1) we can finally do something really nice:</p>
<p><strong>Write complex business rules directly in the database using SQL.</strong></p>
<p>No triggers.<br />No application checks.<br />Just declarative SQL.</p>
<p>I absolutely love this direction.</p>
<p>If you are new to assertions, check the official docs here:</p>
<ul>
<li><p><a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/create-assertion.html">https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/create-assertion.html</a></p>
</li>
<li><p><a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/cncpt/data-integrity.html#GUID-F87D5640-EACA-43EA-9ACA-8BFAA5C6E8B0">https://docs.oracle.com/en/database/oracle/oracle-database/26/cncpt/data-integrity.html#GUID-F87D5640-EACA-43EA-9ACA-8BFAA5C6E8B0</a></p>
</li>
</ul>
<p>And a great blog post from the Oracle SQL team:<br /><a href="https://blogs.oracle.com/sql/how-to-define-cross-table-constraints-with-assertions-in-oracle-ai-database">https://blogs.oracle.com/sql/how-to-define-cross-table-constraints-with-assertions-in-oracle-ai-database</a></p>
<p>But instead of theory, I like <strong>real problems</strong>.</p>
<p>So let's look at a fun one.</p>
<h2>The Problem: Prevent “Impossible Bets”</h2>
<p>In the World Cup betting app, users predict match results.</p>
<p>The tables look like this:</p>
<p><code>W14_MATCH</code> contains the official match info.<br /><code>W14_BET</code> contains the user's prediction.</p>
<p>Example:</p>
<table>
<thead>
<tr>
<th>Match</th>
<th>Prediction</th>
</tr>
</thead>
<tbody><tr>
<td>Brazil vs Germany</td>
<td>2-1</td>
</tr>
<tr>
<td>Spain vs France</td>
<td>0-0</td>
</tr>
</tbody></table>
<p>Pretty simple.</p>
<p>But knockout matches introduce an interesting problem. A knockout match cannot end in a draw. If the regular score is equal, the winner is decided by extra penalties.</p>
<p>Our table supports this:</p>
<pre><code class="language-plaintext">HOME_SCORE
VISIT_SCORE
HOME_EXTRA_PENALTIES
VISIT_EXTRA_PENALTIES
</code></pre>
<p>So a valid knockout bet could be:</p>
<pre><code class="language-plaintext">2 - 2
Penalties: 5 - 4
</code></pre>
<p>But what should never happen is this:</p>
<pre><code class="language-plaintext">2 - 2
Penalties: NULL - NULL
</code></pre>
<p>That means no winner.</p>
<p>And even worse:</p>
<pre><code class="language-plaintext">2 - 2
Penalties: 3 - 3
</code></pre>
<p>Also impossible.</p>
<p>Until now this kind of rule normally lived in:</p>
<ul>
<li><p>application validations</p>
</li>
<li><p>triggers</p>
</li>
<li><p>complex PL/SQL</p>
</li>
</ul>
<p>But now we can express it <strong>as a single SQL rule</strong>.</p>
<h2>The Assertion Solution</h2>
<p>Let's define the rule:</p>
<blockquote>
<p>If a bet predicts a draw, then the penalties must exist and produce a winner.</p>
</blockquote>
<p>This involves <strong>multiple columns and conditional logic</strong>.</p>
<p>Perfect use case for an <strong>assertion</strong>.</p>
<h3>Step 1. Create the Assertion</h3>
<pre><code class="language-plaintext">CREATE ASSERTION bet_knockout_must_have_winner
CHECK (
  ALL (
    SELECT b.home_score, b.visit_score,
           b.home_extra_penalties, b.visit_extra_penalties
    FROM w14_bet b
    WHERE b.home_score = b.visit_score
  ) b
  SATISFY (
    b.home_extra_penalties IS NOT NULL
    AND b.visit_extra_penalties IS NOT NULL
    AND b.home_extra_penalties &lt;&gt; b.visit_extra_penalties
  )
);
</code></pre>
<p>What does this do?</p>
<p>The assertion ensures that no row exists where:</p>
<ol>
<li><p>The predicted score is a draw</p>
</li>
<li><p>AND penalties are missing or tied</p>
</li>
</ol>
<p>If such a row appears, the database rejects the transaction.</p>
<p>Simple. Clear. Declarative.</p>
<h3>Step 2. Let's Test It</h3>
<p>Valid Bet</p>
<pre><code class="language-plaintext">INSERT INTO w14_bet
(ID, USER_ID, MATCH_ID, HOME_SCORE, VISIT_SCORE,
 HOME_EXTRA_PENALTIES, VISIT_EXTRA_PENALTIES,
 CREATED_BY, CREATED_DATE)
VALUES
(1, 10, 5, 2, 2, 5, 4, 'DIMITRI', SYSDATE);
</code></pre>
<p>Result:</p>
<pre><code class="language-plaintext">1 row inserted.
</code></pre>
<p>Good.</p>
<p>Now an invalid bet.</p>
<pre><code class="language-plaintext">INSERT INTO w14_bet
(ID, USER_ID, MATCH_ID, HOME_SCORE, VISIT_SCORE,
 HOME_EXTRA_PENALTIES, VISIT_EXTRA_PENALTIES,
 CREATED_BY, CREATED_DATE)
VALUES
(2, 10, 5, 2, 2, NULL, NULL, 'DIMITRI', SYSDATE);
</code></pre>
<p>Result:</p>
<pre><code class="language-plaintext">SQL Error: ORA-08601: SQL assertion (BET_KNOCKOUT_MUST_HAVE_WINNER) violated.
Help: https://docs.oracle.com/error-help/db/ora-08601/

More Details :
https://docs.oracle.com/error-help/db/ora-08601/
</code></pre>
<p>Exactly what we want. The <strong>database protects the integrity of the data</strong>.</p>
<h2>Why This Matters</h2>
<p>This might look like a small rule, but in real systems things get complicated quickly.</p>
<p>Think about rules like:</p>
<ul>
<li><p>A building cannot consume more power than the grid supplies</p>
</li>
<li><p>A hospital cannot schedule more patients than rooms available</p>
</li>
<li><p>A betting pool must have exactly one winner per match</p>
</li>
<li><p>A smart city cannot exceed environmental limits</p>
</li>
</ul>
<p>These rules often span <strong>multiple tables or conditional logic</strong>.</p>
<p>Before assertions we had to rely on:</p>
<ul>
<li><p>triggers</p>
</li>
<li><p>application validations</p>
</li>
<li><p>batch data cleanup</p>
</li>
</ul>
<p>Now we can express them as <strong>true data integrity rules</strong>.</p>
<p>Readable SQL. Centralized. Guaranteed.</p>
<p>I really like that.</p>
<h2>Why I Love This Feature</h2>
<p>Assertions make the database smarter.</p>
<p>And honestly, the <strong>Oracle Database has always been the best place for business rules</strong>.</p>
<p>We are just getting better tools to express them.</p>
<p>When I look back at the APEX app I built in 2006, many rules were in PL/SQL and page validations. If I would rebuild it today, a lot of that logic would move to assertions.</p>
<p>Cleaner architecture. Safer data. Less code. And that is always a good thing.</p>
<p>If you haven't played with Assertions in Oracle Database 26ai, go and try them out.<br />If you don't have a local DB and you want to try it, <a href="https://freesql.com/">Oracle FreeSQL</a> is very cool:</p>
<p>(note: at the time of writing the environment of FreeSQL was still 23.26, while you need 23.26.1 to get assertions to work)</p>
]]></content:encoded></item><item><title><![CDATA[Oracle APEX 25.1 and beyond]]></title><description><![CDATA[Since Oracle has been quiet about the new release of Oracle APEX, the community has wondered what happened to the next release. I thought it would be helpful to write about what I know for Joel Kallman Day.
In recent years, Oracle has released two ve...]]></description><link>https://dgielis.com/oracle-apex-251-and-beyond</link><guid isPermaLink="true">https://dgielis.com/oracle-apex-251-and-beyond</guid><category><![CDATA[orclapex]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[database]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Wed, 15 Oct 2025 15:17:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1760537029896/d8e3b7ac-d010-414a-adae-e7317f0f10a2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since Oracle has been quiet about the new release of <a target="_blank" href="https://apex.oracle.com">Oracle APEX</a>, the community has wondered what happened to the next release. I thought it would be helpful to write about what I know for <a target="_blank" href="https://oracle-base.com/blog/2025/09/24/joel-kallman-day-2025-announcement/">Joel Kallman Day</a>.</p>
<p>In recent years, Oracle has released two versions of APEX annually, typically in April and October. However, starting with Oracle APEX 24.2, the release schedule slipped slightly, and 24.2 was released early in 2025. There has been no new 25 release yet.</p>
<p>Why no release? From what I understand, the next version of Oracle APEX will introduce an entirely new way of developing Oracle APEX apps using AI, but that will take time. I expect that there won’t be a new release this year, but that Oracle will do the next release early next year. I even think it will be called Oracle APEX 26.1, in line with the new <a target="_blank" href="https://www.oracle.com/database/26ai/">Oracle AI Database 26ai</a> version.</p>
<p>At the <a target="_blank" href="https://www.odtug.com/kscope25">KScope</a> conference in June, Oracle provided us with insight into what is coming.</p>
<p>The next version of Oracle APEX is built around five key themes:</p>
<ul>
<li><p>Generative Development and Al</p>
</li>
<li><p>User Experience</p>
</li>
<li><p>Developer Experience</p>
</li>
<li><p>Enterprise Readiness</p>
</li>
<li><p>Community Ideas</p>
</li>
</ul>
<h2 id="heading-gendev-amp-ai">GenDev &amp; AI</h2>
<p>The use of AI is evident in all facets of Oracle APEX, from development to the features we offer to the users of the applications we build.</p>
<h3 id="heading-apex-ai-application-generator">APEX AI Application Generator</h3>
<p>There will be an entirely new way of building your APEX apps, simply by describing how you want your APEX app to function. This is made possible by introducing a new open application specification, called APEXlang. Here’s a screenshot of the announcement by Juan Loaiza in his <a target="_blank" href="https://x.com/i/broadcasts/1dRKZaVknrwxB">keynote</a> at Oracle AI World.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760537820579/e6039792-8381-480d-b6cb-156f8d53ef8e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-apexlang">APEXlang</h3>
<p>APEXlang looks like a combination of YAML and JSON. Your entire Oracle APEX app can be built using a text (APEXlang) file. For example, you can add a region name, title, type, and SQL, and everything else will use the default. If you define something in the text file, it will overwrite the default. This APEXlang file will be used to generate your APEX app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760537914856/41f3ba29-8e04-4578-a9b3-100baef6fe55.png" alt class="image--center mx-auto" /></p>
<p>The benefits of the APEXlang file extend far beyond AI. Martin D’Souza presented APEXlang at KScope and demonstrated what it can do. Here’s a screenshot of one of his slides:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760538219036/37e7c7c2-602f-4755-8fef-5d0b94f7af83.png" alt class="image--center mx-auto" /></p>
<p>An APEX export file, in the APEXlang format, is human-readable and is easily version-controlled. It allows you to make bulk changes straight in the text file by easy search/replace. This will open a whole new way of doing development with APEX. I envision myself building the initial version of the app using AI and describing what I want. It will generate the text file, which will then be used to generate the APEX app (metadata). I can make changes in the browser (Low-Code) and continue this way. If I need to bulk update something at some point, I can export the app, modify the exported APEXlang file, and redeploy the new version. I might even develop primarily text-based solutions in VS Code and let APEX deploy the latest version repeatedly. Doing text-based development also allows merging multiple developers' changes, etc.</p>
<h3 id="heading-ai-tools">AI Tools</h3>
<p>We can also make our APEX apps smarter using AI tools (functions). Before, you would give all your data to the AI (LLM), and you could ask questions. This wasn’t particularly performant, as you had to send a large amount of data across. The better approach is to use AI Tools, letting AI know how to obtain the information it needs. Here’s an example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760538746171/0672fd3c-8f29-43bf-87d2-123c1b41fd58.png" alt class="image--center mx-auto" /></p>
<p>And a screenshot of how it is configured in the APEX builder:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760538853315/e789a4df-5f88-4ede-abed-01fe5570bfcc.png" alt class="image--center mx-auto" /></p>
<p>Note that if you want to utilize AI today, we at United Codes have created a <a target="_blank" href="https://www.united-codes.com/ai/">UC AI package</a> that can help you significantly.</p>
<h3 id="heading-ai-in-interactive-reports">AI in Interactive Reports</h3>
<p>Another notable feature in the next version of Oracle APEX is the integration of AI into Interactive Reports. You can ask questions in natural language to your Interactive Report, and it will add filters on the fly for you, perform breaks, etc.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539131215/48680f0e-a622-4e6b-859d-425489ff3bcf.png" alt class="image--center mx-auto" /></p>
<p>It can even create charts, or you can have a chat with your IR data, and a chat panel opens on the right where you can delve deeper into your data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760538962150/a39c1ba7-7daf-4a21-a6cb-8101112a5a30.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-user-experience">User Experience</h2>
<p>A new version of Universal Theme is currently in development. Not sure if it will make the next version of Oracle APEX, but I hope so :) A fresh new look &amp; feel would be fantastic.</p>
<p>This new theme will also enable new mobile features.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760540984748/4ae055bf-ad03-4642-b1a8-f4b36e154b36.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-developer-experience">Developer Experience</h2>
<p>There are new features to make our lives as developers easier. There will be built-in live checks, much like what we offer with our QA Assistant in <a target="_blank" href="https://www.united-codes.com/products/apexprojecteye/">APEX Project Eye</a> (APE).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539924704/e5e0b424-5b92-4dcb-ad6c-79402ef04ee3.png" alt class="image--center mx-auto" /></p>
<p>Here’s a screenshot of how the new Advisor looks when an error occurs:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539908638/265dae57-573d-4be7-b06f-6339e03ca92e.png" alt class="image--center mx-auto" /></p>
<p>Having errors and checks directly in the builder is beneficial; more importantly, you can mark exceptions for false positives.</p>
<p>At <a target="_blank" href="https://www.united-codes.com">United Codes</a>, we place a strong emphasis on developer experience. If you haven’t checked out <a target="_blank" href="https://www.united-codes.com/products/apexprojecteye/">APEX Project Eye</a> yet, I strongly advise you to check it out! It provides significant insights into your APEX apps, while also aiding in their development, maintenance, and monitoring.</p>
<h2 id="heading-enterprise-readiness">Enterprise Readiness</h2>
<p>Oracle is using APEX itself extensively to rebuild the Cerner healthcare applications. Huge teams are building now apps using Oracle APEX. To make the apps consistent and easy for developers to share and reuse, a new section has been added to APEX called Pattern Pages and a Global Repository.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539495539/22f3628d-ff35-4570-8a46-4c7cdfe95d79.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539676366/aaf0a705-b2a5-4132-8bec-956b5343c311.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539679861/2bb0a2e2-5e6c-4732-9474-947808408a93.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1760539684597/56fb9793-f419-4623-92c7-7994f009aa6b.png" alt class="image--center mx-auto" /></p>
<p>We will explore why more features are being developed for large teams, as Oracle also requires this functionality.</p>
<h3 id="heading-community-ideas">Community Ideas</h3>
<p>Finally, many new features were added that were submitted by the community through the <a target="_blank" href="https://apexapps.oracle.com/pls/apex/r/apex_pm/ideas/home">APEX Ideas</a> app.</p>
<p>If you want APEX to do something, submit it there, and the APEX team might pick it up in the future!<br />If you can’t wait till the next version of APEX, you can always let us know, too. With our Oracle APEX <a target="_blank" href="https://www.united-codes.com/products/plug-ins-pro/">Plug-ins Pro</a> offering, we are extending APEX while supporting and maintaining it.</p>
<p>Hopefully, this post provides you with some insight into what's to come. Oracle mentioned these things at APEX conferences, but hasn’t been very public about it. You can also refer to the <a target="_blank" href="https://apex.oracle.com/roadmap/">APEX Roadmap</a>, which is the official Oracle page that outlines upcoming features.</p>
]]></content:encoded></item><item><title><![CDATA[Making File Upload required in Oracle APEX]]></title><description><![CDATA[Making the File Upload a required field is difficult with APEX 24.1 or earlier. In this post, I will show you the solution I use until Oracle APEX's native behavior improves.
The definition of my table:
create table xfile 
(    id           number ge...]]></description><link>https://dgielis.com/making-file-upload-required-in-oracle-apex</link><guid isPermaLink="true">https://dgielis.com/making-file-upload-required-in-oracle-apex</guid><category><![CDATA[orclapex]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Wed, 24 Jul 2024 02:42:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721789034337/c2ecd309-e158-4ed3-bb16-0d1e734ffc4c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Making the File Upload a required field is difficult with APEX 24.1 or earlier. In this post, I will show you the solution I use until Oracle APEX's native behavior improves.</p>
<p>The definition of my table:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> xfile 
(    <span class="hljs-keyword">id</span>           <span class="hljs-built_in">number</span> <span class="hljs-keyword">generated</span> <span class="hljs-keyword">by</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">on</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">as</span> <span class="hljs-keyword">identity</span>
                 <span class="hljs-keyword">constraint</span> xfile_pk primary <span class="hljs-keyword">key</span>,
    app_id       <span class="hljs-built_in">number</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>, 
    <span class="hljs-keyword">name</span>         <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">400</span>) <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>, 
    filename     <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">400</span>) <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>,  
    mime_type    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>,  
    created_on   <span class="hljs-built_in">date</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">sysdate</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>,  
    blob_content <span class="hljs-built_in">blob</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>
);
</code></pre>
<p>Create an Interactive Report with Form on this table:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721769776600/404c0f94-01bc-42a6-a3b2-b6a5c1ec39e0.png" alt class="image--center mx-auto" /></p>
<p>When you run the page and create a new record but forget to add a file, you will receive this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721769840962/a8e7e45e-18e3-4d8c-8ee1-cac47c437c78.png" alt class="image--center mx-auto" /></p>
<p>This is perfect, just like we want. The blob content item has the required value flag set automatically, because APEX picked up the "not null" constraint from the table. Because of this flag, APEX raises the error when no file is selected.</p>
<p>Now, what happens if we edit the record?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721769951796/f3637ac3-e30d-41fc-a641-0de1ed311080.png" alt class="image--center mx-auto" /></p>
<p>Although there is a file, APEX still complains that there is no file. This is not the behavior we want! Whenever there is a file, it should not give an error. The issue is that APEX doesn't detect that a file has already been selected before.</p>
<p>To work around this issue, I set the "Value Required" on the item to no and wrote my own validation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721770125242/274bc136-9a27-451f-b434-5f5957f7a107.png" alt class="image--center mx-auto" /></p>
<p>My custom validation "Check for required blob":</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721770152906/b8223a73-4e83-410a-9a00-42e0f3c9fd7e.png" alt class="image--center mx-auto" /></p>
<p>The code looks like this, I added debug messages to explain what it does:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">declare</span>
  l_exists <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">1</span>) := <span class="hljs-string">'N'</span>;
<span class="hljs-keyword">begin</span>
  apex_debug.message(<span class="hljs-string">'## The id is: '</span> || :P3_ID);
  apex_debug.message('<span class="hljs-comment">## The value of blob content is: ' || :P3_BLOB_CONTENT);</span>

  if :P3_ID is null and :P3_BLOB_CONTENT is not null
  then
    apex_debug.message('<span class="hljs-comment">## New record and blob filled in.');</span>
    l_exists := 'Y';

  elsif :P3_ID is not null
  then
    apex_debug.message('<span class="hljs-comment">## We need to find a blob for id: ' || :P3_ID);</span>
    <span class="hljs-keyword">begin</span>
      <span class="hljs-keyword">select</span> <span class="hljs-string">'Y'</span>
        <span class="hljs-keyword">into</span> l_exists
        <span class="hljs-keyword">from</span> xfile
       <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span> = to_number(:P3_ID)
         <span class="hljs-keyword">and</span> blob_content <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>; 

      apex_debug.message('<span class="hljs-comment">## We are good.');</span>
    exception
    when no_data_found
    then
      apex_debug.message('<span class="hljs-comment">## We did not find a blob.');</span>
    <span class="hljs-keyword">end</span>;
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>;

  apex_debug.message('<span class="hljs-comment">## Exists: ' || l_exists);</span>

  if l_exists = 'Y'
  then 
    return true;
  else  
    return false;
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>;  
<span class="hljs-keyword">end</span>;
</code></pre>
<p>This code checks whether a blob is present when creating a new record or editing an existing record.</p>
<p>The page allows you to remove a file by clicking the X:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721770420276/624ba501-f4f1-4118-a389-0f4bbf671424.png" alt class="image--center mx-auto" /></p>
<p>But when you do, Oracle APEX doesn't remove the file until you select another file. This is why the above code for the validation works, but it would have been cool if we could detect if the file was effectively removed.</p>
<p>So, an <strong>alternative</strong> solution to the above is detecting if a blob exists. This solution is a bit more complex since it has more moving pieces.</p>
<p>Create a hidden item on the page called P3_BLOB_EXISTS and make sure the item is not "Value Protected".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721786354680/156c324c-1991-41ee-9c56-63629c86062d.png" alt class="image--center mx-auto" /></p>
<p>We will fill this item with the value Y when there's a download link or remove button, otherwise the value will be N. <em>Note: checking only for the download link is not enough, since there is a setting to not show the download link.</em></p>
<p>Add a Dynamic Action called "Blob exists":</p>
<ul>
<li><p>When - Event: Before Page Submit</p>
</li>
<li><p>Action - True: Execute JavaScript Code</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">if</span> ($(<span class="hljs-string">".a-FileDrop-download"</span>).length &gt; <span class="hljs-number">0</span> 
      || $(<span class="hljs-string">".a-FileDrop-remove"</span>).attr(<span class="hljs-string">'tabindex'</span>) == <span class="hljs-number">0</span>) {
    apex.item(<span class="hljs-string">"P3_BLOB_EXISTS"</span>).setValue(<span class="hljs-string">"Y"</span>);
  } <span class="hljs-keyword">else</span> {
    apex.item(<span class="hljs-string">"P3_BLOB_EXISTS"</span>).setValue(<span class="hljs-string">"N"</span>);  
  }
</code></pre>
</li>
</ul>
<p>Here's a screenshot of what that looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721786599259/406a12a4-8285-4da8-a45f-e1dc06ca2bc5.png" alt class="image--center mx-auto" /></p>
<p>We will change our Validation "Check for required blob" to the following:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">declare</span>
  l_blob_content <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">255</span>) := :P3_BLOB_CONTENT;
  l_blob_exists  varchar2(1)   := :P3_BLOB_EXISTS;
<span class="hljs-keyword">begin</span>
  apex_debug.message(<span class="hljs-string">'## The value of blob content is: '</span> || l_blob_content);
  apex_debug.message('<span class="hljs-comment">## Did a blob exist before: ' || l_blob_exists);</span>

  if l_blob_content is not null
  then
    apex_debug.message('<span class="hljs-comment">## A new blob is added.');</span>
    return true;
  else
    apex_debug.message('<span class="hljs-comment">## The blob item is empty.');</span>
    if l_blob_exists = 'Y'
    then
      apex_debug.message('<span class="hljs-comment">## A blob existed before.');</span>
      return true;
    else 
      apex_debug.message('<span class="hljs-comment">## A blob is missing.');</span>
      return false;
    <span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>; 
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>;
<span class="hljs-keyword">end</span>;
</code></pre>
<p>Here's a screenshot of the validation:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721786829554/ea69321c-5d6b-4fc8-9f4d-a7754212a998.png" alt class="image--center mx-auto" /></p>
<p>So now, when you create a record and don't upload a file or when you edit the record and remove the file, APEX will say the field is required. And more importantly, APEX won't complain anymore when you edit the record and don't touch the file (blob).</p>
]]></content:encoded></item><item><title><![CDATA[ORDS - SQL Developer Web: Fix Invalid credentials]]></title><description><![CDATA[I had a weird issue with some Oracle database users I wanted to connect to in SQL Developer Web.
When I tried to log in at https://hostname/ords/sql-developer, I received the error: Invalid credentials: If your ORDS schema alias is different from you...]]></description><link>https://dgielis.com/ords-sql-developer-web-fix-invalid-credentials</link><guid isPermaLink="true">https://dgielis.com/ords-sql-developer-web-fix-invalid-credentials</guid><category><![CDATA[ords]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Wed, 22 Nov 2023 18:42:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1700678434099/af6b3874-53e2-4bcc-a67a-c79269887b93.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I had a weird issue with some Oracle database users I wanted to connect to in SQL Developer Web.</p>
<p>When I tried to log in at <strong>https://hostname/ords/sql-developer</strong>, I received the error: Invalid credentials: If your ORDS schema alias is different from your username, you can set it using the "Path" input in the "Advanced" options.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1700668249944/37fea48d-7ae6-44b6-97c9-e5541f2d65e7.png" alt class="image--center mx-auto" /></p>
<p>I also tried to log in at <strong>https://hostname/ords/aop_tst/sign-in/,</strong> but then I got the error: Invalid credentials.</p>
<p>Finally, when I tried to log in at <strong>https://hostname/ords/aop_tst/_sdw/?nav=worksheet</strong> it worked for me.</p>
<p>In case it's still not working for you, it might help to close and re-open your browser, at least that worked for me.</p>
<p>Once I was successfully logged in, the next time I could log in directly at <strong>https://hostname/ords/sql-developer</strong> without any issues.</p>
<p>Note that this behavior was only for a couple of users. When I created a user like in the next script, it worked straight away.</p>
<pre><code class="lang-plaintext">create tablespace uc_dev datafile '/u01/oradata/CDB1/dev/uc_dev01.dbf' size 50M autoextend on next 50M maxsize unlimited default table compress for oltp index compress advanced high;

create user uc_dev identified by secret default tablespace uc_dev quota unlimited on uc_dev temporary tablespace temp;

grant connect to uc_dev;
grant create job to uc_dev;
grant create dimension to uc_dev;
grant create indextype to uc_dev;
grant create operator to uc_dev;
grant create type to uc_dev;
grant create materialized view to uc_dev;
grant create trigger to uc_dev;
grant create procedure to uc_dev;
grant create sequence to uc_dev;
grant create view to uc_dev;
grant create synonym to uc_dev;
grant create cluster to uc_dev;
grant create table to uc_dev;
grant create session to uc_dev;
grant execute on ctxsys.ctx_ddl to uc_dev;

begin
  ords_admin.enable_schema(p_schema =&gt; 'uc_dev');
end;
/
</code></pre>
<p>I couldn't identify a reason why for some database users it's not working straight away, but hope that this workaround helps you too, when you encounter the same error.</p>
]]></content:encoded></item><item><title><![CDATA[A story about Joel and APEX Office Print (AOP) #JoelKallmanDay]]></title><description><![CDATA[Since this is the special Joel Kallman day, I thought to share a story about how document generation with AOP started at Oracle's internal APEX environment.
Today it might be normal for people to use APEX Office Print (AOP) to do their document gener...]]></description><link>https://dgielis.com/a-story-about-joel-and-apex-office-print-aop-joelkallmanday</link><guid isPermaLink="true">https://dgielis.com/a-story-about-joel-and-apex-office-print-aop-joelkallmanday</guid><category><![CDATA[JoelKallmanDay]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[aop]]></category><category><![CDATA[apexofficeprint]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Wed, 11 Oct 2023 14:39:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697035332970/94e0138d-b53c-4a6d-8704-7f2199a0f29d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since this is the special Joel Kallman day, I thought to share a story about how document generation with AOP started at Oracle's internal APEX environment.</p>
<p>Today it might be normal for people to use <a target="_blank" href="https://www.apexofficeprint.com">APEX Office Print (AOP)</a> to do their document generation in <a target="_blank" href="https://apex.oracle.com">Oracle APEX</a>, but back in 2017, it wasn't.</p>
<p>We were only around for two years and weren't as proven as we are today, but Joel really believed in us. On July 11th, 2017 I got the following email from Joel:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697025333593/d922ef1b-dacc-4ec7-9e40-941428e3b8c5.png" alt class="image--center mx-auto" /></p>
<p>Two weeks later AOP was running inside Oracle, so every department using the internal APEX instance could start generating PDFs, Excels, and other documents.</p>
<p>Joel himself installed AOP and created an internal site to explain what AOP was and how to get started. Today the internal Oracle APEX instance is maintained by other people as it has become a very big instance. The single AOP Server installed by Joel in 2017, has become six AOP servers maintained by the OPS team, but I will never forget how it all started.</p>
<p>Just as Joel served the entire APEX community, we want to do the same and constantly push ourselves to improve. We want to keep Joel’s energy going by turning developers into rock stars. For us, it means making you successful in generating, editing, and managing documents and having the best integration with APEX that we can.</p>
<p>I'm very thankful for Joel. APEX Office Print is definitely more successful because of his support. We miss you, my friend.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697033620867/a80d78c5-9a5a-4878-8deb-5111b3b65954.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Compare 2 Oracle APEX pages]]></title><description><![CDATA[I wanted to know if a page was the same within the same application.
Two (+1 in Oracle APEX 22.1+) features in Oracle APEX help to compare pages, which you find under the tools menu: Checksum and Export:

The checksum will show the checksum of the pa...]]></description><link>https://dgielis.com/compare-2-oracle-apex-pages</link><guid isPermaLink="true">https://dgielis.com/compare-2-oracle-apex-pages</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Compare]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Tue, 15 Aug 2023 11:37:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692097985437/587ef65b-03c0-478d-a4f1-a1641b2994c6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I wanted to know if a page was the same within the same application.</p>
<p>Two (+1 in Oracle APEX 22.1+) features in Oracle APEX help to compare pages, which you find under the tools menu: Checksum and Export:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692098515909/0dd40db4-ad7f-4a22-8b65-9eff2ad069ab.png" alt class="image--center mx-auto" /></p>
<p>The checksum will show the <strong>checksum</strong> of the page. This feature works great when you want to compare the same pages in different applications. In case the page number is different, the checksum will be different, so this feature won't help to compare different pages within the same application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692098544872/eee4ae7e-8803-4f3b-999f-3a269feb5668.png" alt class="image--center mx-auto" /></p>
<p>The <strong>page export</strong> feature works better if you want to compare pages inside the same application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692098554980/06192756-8b17-426c-a84e-02b666147e9f.png" alt class="image--center mx-auto" /></p>
<p>Exporting a page generates a SQL file. I then compare both SQL files in Visual Studio Code. Some ids will be different, but you can ignore those. For me, this technique works well to quickly identify differences between the two pages.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692098563640/e90d3f61-4ac6-4889-aab8-e73a517b326e.png" alt class="image--center mx-auto" /></p>
<p>It would have been even easier if the Oracle APEX team provided the option to export the page in a <strong>readable format</strong>, but this feature is only available when you export the entire application (Oracle APEX 22.1 and above).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692100818729/f1e02752-0d1f-4727-bbaa-7b79a7e2ac89.png" alt class="image--center mx-auto" /></p>
<p>When exporting in a readable format, you will get a zip file that contains a readable folder. In there, you find the pages in a JSON format.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692101128980/22aba95c-be15-4d41-a153-abd71df06cff.png" alt class="image--center mx-auto" /></p>
<p>Now you can <strong>compare the JSON files</strong> (just like we compared the SQL files before), but this time it's a bit more readable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692101136919/fa5abc87-f107-4950-a20a-ae9c4bd90e90.png" alt class="image--center mx-auto" /></p>
<p>In case you want to <strong>compare entire applications</strong>, you can use the application checksum feature which you find in the Utilities section of your Oracle APEX app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692099357559/9aa5e9df-47c2-4be4-b91b-5f5cdcce60e9.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[The application alias "X" can not be converted to a unique application ID.]]></title><description><![CDATA[You get this error when two or more Oracle APEX applications have the same alias.
When you import the sample application in the same workspace and give it a different ID, the alias is changed automatically so it's unique. However when you import an a...]]></description><link>https://dgielis.com/the-application-alias-x-can-not-be-converted-to-a-unique-application-id</link><guid isPermaLink="true">https://dgielis.com/the-application-alias-x-can-not-be-converted-to-a-unique-application-id</guid><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Fri, 04 Aug 2023 16:55:57 GMT</pubDate><content:encoded><![CDATA[<p>You get this error when two or more Oracle APEX applications have the same alias.</p>
<p>When you import the sample application in the same workspace and give it a different ID, the alias is changed automatically so it's unique. However when you import an application in a different workspace, the alias is not being replaced by a unique value, which might result in the error: "The application alias "X" can not be converted to a unique application ID."</p>
<p>There's an easy way to find where those applications are with the same alias by running the following query (as a DBA or a user with the APEX_ADMINISTRATOR_ROLE):</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> workspace, application_id, application_name
  <span class="hljs-keyword">from</span> apex_applications
 <span class="hljs-keyword">where</span> <span class="hljs-keyword">alias</span> = <span class="hljs-string">'X'</span>
</code></pre>
<p>This will give you the workspace, application id, and application name with the specific alias.</p>
]]></content:encoded></item><item><title><![CDATA[Oracle APEX: the Power of the Activity Logs]]></title><description><![CDATA[The issue
Have you ever had those moments when an end-user calls you out of the blue with a disturbing message about your app?
It happened to me last week; an end-user called in a panic with the message, "all my inspections are gone!"
FYI: This Oracl...]]></description><link>https://dgielis.com/oracle-apex-the-power-of-the-activity-logs</link><guid isPermaLink="true">https://dgielis.com/oracle-apex-the-power-of-the-activity-logs</guid><category><![CDATA[orclapex]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Logs]]></category><category><![CDATA[apexprojecteye]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Wed, 22 Feb 2023 15:00:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677078032980/e15ef6bf-f7fa-41af-be35-cdb54d29b8a8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-the-issue">The issue</h3>
<p>Have you ever had those moments when an end-user calls you out of the blue with a disturbing message about your app?</p>
<p>It happened to me last week; an end-user called in a panic with the message, "all my inspections are gone!"</p>
<p>FYI: This <a target="_blank" href="https://apex.oracle.com">Oracle APEX</a> application manages all inspections a company is doing. Those inspections are grouped into different categories.</p>
<h3 id="heading-my-thoughts">My thoughts</h3>
<p>Records don't disappear automatically, so my mind immediately started to think about the potential reasons why this might have happened:</p>
<ol>
<li><p>Did we update the app with an invalid WHERE clause or a bad JOIN?</p>
</li>
<li><p>Did we have a DELETE process that didn't have a condition?</p>
</li>
<li><p>Did a user do a bulk delete action or delete a parent record that caused the child records to go?</p>
</li>
</ol>
<h3 id="heading-the-investigation">The investigation</h3>
<p>On the call, I asked the user to tell me what he saw. It was weird indeed; the categories showed there were zero inspections.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676275192194/bebac643-f6de-49e0-bd96-a885ff10d8a5.png" alt class="image--center mx-auto" /></p>
<p><strong>But</strong> this one category (Thermography) still had two inspections... bizarre.</p>
<p>I asked a few more questions and got the answers that parents or children were not deleted, bulk actions were not executed, and the records were there in the morning, but were gone in the afternoon.</p>
<p>As we didn't deploy a new version of the app, and it worked before, it was a bit of a mystery to me.</p>
<h3 id="heading-activity-logs-to-the-rescue">Activity Logs to the rescue</h3>
<p>This is when I'm glad Oracle APEX has a built-in feature that logs a user's activity, which is turned on by default. You find the setting in your Application Attributes:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676276845830/5240c9fe-82e1-4c57-844d-53563586c7f9.png" alt class="image--center mx-auto" /></p>
<p>You can change the default settings of an app in the instance settings (INTERNAL workspace) under Manage Instance &gt; Feature Configuration &gt; Monitoring.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676298640364/4db2e905-b71a-4ecd-aa48-a87fdcf83ff2.png" alt class="image--center mx-auto" /></p>
<p>By default, at least 14 days of log data will be stored, but it can be changed in the instance settings under Manage Instance &gt; Manage Log Interval.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676298651198/899c328b-4159-401e-af5f-c422e46f0536.png" alt class="image--center mx-auto" /></p>
<p>The logs are captured in two different tables: wwv_flow_activity_log1 and wwv_flow_activity_log2. APEX is switching the table used behind the scenes every x days (the setting above). In case you leave the log switch to 14 days, it means that you have 14 to 27 days of activity logs. You don't have to worry about which table to query to see the data. You instead use the view APEX_WORKSPACE_ACTIVITY_LOG.</p>
<p>I wanted to give this background as you may want to increase your logs. The maximum amount before a log switch happens is 180 days. If you need more, you need to copy the records to your tables (also read further on that <a target="_blank" href="https://www.apexprojecteye.com">APEX Project Eye</a> can help with this).</p>
<p>To see the logs, you either query the APEX_WORKSPACE_ACTIVITY_LOG view or you can go to the Monitor Activity section within APEX:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676299634919/c8fad74f-c6ef-431f-bd2c-46d1012d9295.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-the-proof">The proof</h3>
<p>To make the activity more alive, I love to use <a target="_blank" href="https://www.apexprojecteye.com">APEX Project Eye (APE)</a>. APE is a powerhouse of tools that help any Oracle APEX developer and project manager. For me, APEX Project Eye is for Oracle APEX what Enterprise Manager is for the Oracle Database. APE is the most advanced tool to give you insight into your Oracle APEX applications, from how it was developed to how it is being used.</p>
<p>Back to our investigation on the disappearance of the records... I focused on the window from the morning when the records were there till the records disappeared. In APE, I used <strong>Session Flow</strong> to see who accessed the application during this period and accessed a page where a delete could have been done. I saw an unusually high number of going back and forth between a report and a form... In Session Flow, it shows lines between pages. The bigger the line between the pages, the more that path was taken. Session Flow also allows you to <strong>replay a session</strong>. The path gets highlighted, and you get the details of the request.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677062736841/ef85a019-5b59-4a7f-8c5e-b110f07df9fc.png" alt class="image--center mx-auto" /></p>
<p>This way, I knew exactly what happened... somebody went into the records individually and deleted them. APE gave me the power to present the end-users precisely when somebody made an action visually.</p>
<h3 id="heading-apex-project-eye-helps-in-dev-test-and-prod">APEX Project Eye helps in DEV, TEST, and PROD</h3>
<p>We use APEX Project Eye a lot; during <strong>development</strong> (e.g., quality assurance), during <strong>testing</strong>, e.g., to review performance and error investigation, and during <strong>production</strong> to monitor our applications. Session Flow, in particular, is beneficial when APE shows an end-user got an error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677069838883/5c34cf87-1775-492d-9070-c8f00a282704.png" alt class="image--center mx-auto" /></p>
<p>For the error, we see the Session ID, and based on this Session ID, <strong>we can replay their session until the error pops</strong> up. We know exactly what they did and don't have to ask for a reproducible case.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677073572639/5da23267-656e-4b27-b624-44b99c54ebcd.png" alt class="image--center mx-auto" /></p>
<p>There was another occasion when Session Flow was a rescuer for me. At one point, we had a <strong>security breach</strong> in one of the apps. At least one person saw data in an Interactive Report that he wasn't supposed to see. He reached a page he wasn't supposed to have access to. Using Session Flow, I knew exactly how he came there, how long he had stayed on the page, and what he had done. I could, for example, see that he didn't download the data from the Interactive Report. <strong>Without Session Flow, I could have probably found out by analyzing the logs, but it would have taken me much more time.</strong> This was one of the reasons we now have Quality Assurance in APE so that APE can warn us of security risks. Do you know eSert, the popular security scanner for Oracle APEX, from a few years ago? With <strong>APE, you can use all of the eSert rules!</strong></p>
<h3 id="heading-recap-apes-session-flow">Recap APE's Session Flow</h3>
<p>APE's Session Flow is fantastic for the following use cases:</p>
<ul>
<li><p>See how people use the application you built.</p>
</li>
<li><p>View exactly when and how an error occurred.</p>
</li>
<li><p>Have a visual representation when you talk to project managers and end users.</p>
</li>
<li><p>Prove if an action was done or not.</p>
</li>
</ul>
<h3 id="heading-to-remember">To remember</h3>
<p>Oracle APEX's built-in logging is very useful. There are settings to define the number of days the logging is kept. <a target="_blank" href="https://www.apexprojecteye.com">APEX Project Eye (APE)</a> can help you get a better insight into these logs.</p>
]]></content:encoded></item><item><title><![CDATA[Fix for ORDS connection pool named |default|lo| is not able to proxy to the schema]]></title><description><![CDATA[Today on our server running ORDS 22.4 and Oracle APEX 22.2 we had a weird error:
The database user for the connection pool named |default|lo|, is not able to proxy to the schema named ET_DEV. This could be a configured restriction on the maximum numb...]]></description><link>https://dgielis.com/fix-for-ords-connection-pool-named-defaultlo-is-not-able-to-proxy-to-the-schema</link><guid isPermaLink="true">https://dgielis.com/fix-for-ords-connection-pool-named-defaultlo-is-not-able-to-proxy-to-the-schema</guid><category><![CDATA[ords]]></category><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Fri, 13 Jan 2023 18:37:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673635102994/e167d7b1-cbe0-49a3-ae39-ac4810024b54.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today on our server running <a target="_blank" href="https://www.oracle.com/be/database/technologies/appdev/rest.html">ORDS</a> 22.4 and <a target="_blank" href="https://apex.oracle.com">Oracle APEX</a> 22.2 we had a weird error:</p>
<p><mark>The database user for the connection pool named |default|lo|, is not able to proxy to the schema named ET_DEV. This could be a configured restriction on the maximum number of database sessions or an authorization failure.</mark></p>
<p>I have seen 503 errors before, but not one with default|lo. It might be because we imported the REST web services from another system and only noticed it now or it might have been other things, we are not sure what caused it. Other Oracle APEX workspaces and schemas didn't have this issue.</p>
<p>The fix for us was a 4-step process:</p>
<ol>
<li><p>Export All Web Services</p>
</li>
<li><p>De-Register the schema from ORDS</p>
</li>
<li><p>Enable the schema again</p>
</li>
<li><p>Import All Web Services again</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673634762688/2e50bab9-9170-4b4c-8729-caf717896bf8.png" alt class="image--center mx-auto" /></p>
<p>Hope it helps you when you have it.</p>
]]></content:encoded></item><item><title><![CDATA[Restarting to blog]]></title><description><![CDATA[At the beginning of the year, I tend to reflect on the last year(s). When looking back this year I realized that in the last 15 years things changed in the amount I blogged.
I love Oracle Application Express (APEX) and started my blog to share what I...]]></description><link>https://dgielis.com/restarting-to-blog</link><guid isPermaLink="true">https://dgielis.com/restarting-to-blog</guid><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Dimitri Gielis]]></dc:creator><pubDate>Sun, 01 Jan 2023 20:23:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1672606721168/a81fbba4-461f-4bd5-8887-2d49a1ec8579.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>At the beginning of the year, I tend to reflect on the last year(s). When looking back this year I realized that in the last 15 years things changed in the amount I blogged.</p>
<p>I love <a target="_blank" href="https://apex.oracle.com">Oracle Application Express (APEX)</a> and started my blog to share what I learned while developing in Oracle APEX. I also blogged because I believed Oracle APEX could help many businesses, so I wanted to promote it and make other people successful in building apps with Oracle APEX. My blog was also a way for me to connect to other people that were using Oracle APEX. So many great people helped each other being successful ... this is what we know today, Oracle APEX has a strong community with passionate people about the product.</p>
<p>In the first few years, I did over two blog posts per week. In the years after I did one blog post every week or every other week, but in the last two years, I blogged much less.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672601642827/91e748df-2edc-401a-948a-c11af1502920.png" alt class="image--center mx-auto" /></p>
<p>There are many different reasons why I blogged less:</p>
<ul>
<li><p>Oracle is promoting Oracle APEX much more than before, so there is already more content available today than there was 15 years ago.</p>
</li>
<li><p>I like to help people be successful using Oracle APEX, but I'm doing this now more through <a target="_blank" href="https://www.united-codes.com">United Codes</a> by building products that help Oracle APEX developers.</p>
</li>
<li><p>I was all-in on building out the company and supporting the products that we created, which was often 1-1.</p>
</li>
<li><p>I put ideas down that I wanted to share, but never took the time to effectively write them out.</p>
</li>
<li><p>The older I get, the faster time seems to go, so before I knew my time was consumed by other things.</p>
</li>
</ul>
<p>But for the next few years, I want to change this again and make some time to do some more blogging. As <a target="_blank" href="https://hashnode.com/">Hashnode</a> seems to be the blogging platform for developers I thought to start writing on this platform over continuing at my <a target="_blank" href="https://dgielis.blogspot.com">old Blog</a> done in Blogger.</p>
<p>Here's what I plan to write about:</p>
<ul>
<li><p>Oracle APEX comes out with two releases a year, but instead of blogging about the different features and how to use them, I want to give my view on why you may want to use (or not use) this new feature.</p>
</li>
<li><p>In United Codes, we build great products that I believe help every Oracle APEX developer out there to be more productive and give them the ability to achieve more. But if you don't know they exist, you won't use them, so I want to change that and show you why we build the products we put out there.</p>
</li>
<li><p>Every day I learn something. It may not always be about Oracle APEX, but those insights help me to understand the world I'm living in, so I hope they will be useful to others.</p>
</li>
<li><p>We have a great Oracle APEX community, but things changed over time. Many people from the community are now working for Oracle, we had Corona which meant not meeting people live, Joel, who was the leader of our community, passed away, people seem to have moved and new people came... I want to make a conscious effort again to learn about the people in our community and want to help to build out our lovely Oracle APEX community again.</p>
</li>
</ul>
<p>That's it for now... I speak you soon again!</p>
]]></content:encoded></item></channel></rss>