<?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[Oracle APEX, ORDS, PL/SQL and OCI]]></title><description><![CDATA[Father of three, husband and passionate nerd on everything related to Oracle APEX, PL/SQL and the Oracle Cloud]]></description><link>https://blog.rhjmartens.nl</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 20:58:54 GMT</lastBuildDate><atom:link href="https://blog.rhjmartens.nl/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[setting up Bitwarden SSH Agent for VS Code on MAC OS]]></title><description><![CDATA[Recently I switched over from Roboform to Bitwarden as my passwordvault. The main advantages why I did this:

I use a vaultwarden docker image on my DS420j NAS

Vaultwarden is completely free

I can u]]></description><link>https://blog.rhjmartens.nl/setting-up-bitwarden-ssh-agent-for-vs-code-on-mac-os</link><guid isPermaLink="true">https://blog.rhjmartens.nl/setting-up-bitwarden-ssh-agent-for-vs-code-on-mac-os</guid><category><![CDATA[ssh-keys]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Bitwarden]]></category><category><![CDATA[vaultwarden]]></category><category><![CDATA[VS Code]]></category><category><![CDATA[Git]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Thu, 12 Mar 2026 11:36:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/a87bae2a-e2ea-4aff-888e-42e23f15f843.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently I switched over from Roboform to Bitwarden as my passwordvault. The main advantages why I did this:</p>
<ul>
<li><p>I use a vaultwarden docker image on my DS420j NAS</p>
</li>
<li><p>Vaultwarden is completely free</p>
</li>
<li><p>I can use the standard Bitwarden clients (Desktop and Browser extensions)</p>
</li>
<li><p>I can share my passwords between all my laptops (Mac OS, Linux and Windows)</p>
</li>
<li><p>It has an integrated SSH agent, so I can use my SSH keys throughout my development stack on all my devices</p>
</li>
</ul>
<p>Very important, make sure (on Mac OS) to use brew to install Bitwarden:</p>
<pre><code class="language-shell"> brew install --cask bitwarden
</code></pre>
<p>then make sure that your environment is set correctly (I did it in my "~/.zshrc" file:</p>
<pre><code class="language-shell">export SSH_AUTH_SOCK=~/.bitwarden-ssh-agent.sock
</code></pre>
<p>Finally, make sure that the MacOS environment is properly configured for VS Code to pick up the setting:</p>
<pre><code class="language-shell"> launchctl setenv SSH_AUTH_SOCK "$SSH_AUTH_SOCK"
</code></pre>
<p>Now, when I open a git repo from gitlab, github or whatever git server, VS Code tries to open the SSH Agent and my Bitwarden desktop client asks me to authorize the request; Brilliant.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/0b01e8fd-0797-40d5-91ee-6c8e643c4ddd.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[Opentelemetry in Oracle APEX (part-1)]]></title><description><![CDATA[When preparing for my sessions this year on OpenTelemtrey within Oracle APEX I came across a couple of contributions:

Dominik H on the Oracle forum: https://forums.oracle.com/ords/apexds/post/opentel]]></description><link>https://blog.rhjmartens.nl/opentelemetry-in-oracle-apex-part-1</link><guid isPermaLink="true">https://blog.rhjmartens.nl/opentelemetry-in-oracle-apex-part-1</guid><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Sat, 07 Mar 2026 17:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/252354d0-0e4e-41c1-b88e-4eccd94aa6e3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When preparing for my sessions this year on OpenTelemtrey within Oracle APEX I came across a couple of contributions:</p>
<ul>
<li><p>Dominik H on the Oracle forum: <a href="https://forums.oracle.com/ords/apexds/post/opentelemetry-in-apex-24-2-2174">https://forums.oracle.com/ords/apexds/post/opentelemetry-in-apex-24-2-2174</a></p>
<ul>
<li>Steve Muench (Oracle) replied on this by pointing out a japanese website:<br /><a href="https://apexugj.blogspot.com/2025/01/apex242-new-feature-opentelemetry.html">https://apexugj.blogspot.com/2025/01/apex242-new-feature-opentelemetry.html</a></li>
</ul>
</li>
</ul>
<p>The blog is available in a gazillion languages through Google Translate, that helps a lot. Nevertheless I thought, let me rephrase Yuji in English and add English screenshots as well.</p>
<h2>Support for OpenTelemetry in Oracle APEX 24.2</h2>
<p>Yuji checked the settings for OpenTelemetry, a new feature added in Oracle APEX 24.2. As far as he can tell from 2.31 Java Script Library Upgrades in the <a href="https://docs.oracle.com/en/database/oracle/apex/24.2/htmrn/new-features.html#GUID-175489FB-CC24-40F6-89EF-A4A7AAFD7770">Oracle APEX 24.2 Release Notes</a> , the following libraries are built into the front end of Oracle APEX as the OpenTelemetry SDK:</p>
<p>2.31 JavaScript Library Upgrades</p>
<ul>
<li><p>@opentelemetry/api 1.9.0</p>
</li>
<li><p>@opentelemetry/core 1.26.0</p>
</li>
<li><p>@opentelemetry/instrumentation 0.53.0</p>
</li>
<li><p>@opentelemetry/instrumentation-document-load 0.39.0</p>
</li>
<li><p>@opentelemetry/instrumentation-fetch 0.53.0</p>
</li>
<li><p>@opentelemetry/instrumentation-xml-http-request 0.53.0</p>
</li>
<li><p>@opentelemetry/sdk-trace-base 1.26.0</p>
</li>
<li><p>@opentelemetry/sdk-trace-web 1.26.0</p>
</li>
</ul>
<p>In Oracle APEX 24.2, there is little configuration required to enable sending client-side telemetry data through OpenTelemetry.</p>
<p>Oracle APEX 24.2 introduces <strong>OpenTelemetry</strong> to <strong>Workspace Utilities .</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/e37848b2-b089-4fc5-9541-1d1bfa299619.png" alt="" style="display:block;margin:0 auto" />

<p>Configure OpenTelemetry by setting the client logging service URL and token relay URL .</p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/53a12215-0830-4a2f-b1e8-5a622fd6b17c.png" alt="" style="display:block;margin:0 auto" />

<p>The APEX application's application <strong>definition user interface</strong> now includes a section for <strong>OpenTelemetry</strong>, where you set <strong>the product family .</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/ddb3e668-acbe-4f00-9be3-0245345b964f.png" alt="" style="display:block;margin:0 auto" />

<p><strong>It was unclear to Yuji what OpenTelemetry settings settings such as Client Logging Service URL</strong> , <strong>Token Relay URL</strong> , and <strong>Product Family</strong> corresponded to, but it appears that Oracle APEX 24.2's OpenTelemetry support is intended to send data to the observability framework provided by Oracle's SaaS products .</p>
<p>Since connecting to Oracle SaaS is difficult, we will implement <strong>the client logging service URL</strong> and <strong>token relay URL</strong> processing in Oracle REST Data Services to verify the operation of OpenTelemetry in Oracle APEX 24.2.</p>
<h2>Creating your own collector</h2>
<p>An OpenTelemetry-enabled APEX application sends trace data from the browser in HTTP/JSON format, compressed with gzip. The Client Logging Service URL is the destination for this data. This data format is likely to be received directly by an OpenTelemetry Collector receiver.</p>
<p>Create a table to store the received traces. Name the table OTEL_TRACES <strong>.</strong></p>
<pre><code class="language-sql">create table otel_traces (
    id         number generated by default on null as identity
               constraint otel_traces_id_pk primary key,
    trace      clob,
    created    date default on null sysdate
);
</code></pre>
<p>You can do this in the SQL-workshop or any other (more appropriate tool)</p>
<p>Now we have the table, we can create a rest-service on it:</p>
<p>I'll provide the scripts that create all services below as well.</p>
<p><strong>The module name</strong> is <strong>OpenTelemetry</strong> and <strong>the module base path</strong> is <strong>/otel/</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/2f3cf034-5c95-4768-bfa7-7c65dbed19d1.png" alt="" style="display:block;margin:0 auto" />

<p>Create <strong>traces</strong> as <strong>a URI template</strong> in the created module <strong>OpenTelemetry.</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/f006db40-927f-4a4e-ac68-f84b48ef943c.png" alt="" style="display:block;margin:0 auto" />

<p>Register <strong>the POST</strong> handler in template <strong>traces.</strong><br />Write the following as <strong>a source</strong> . The received data is decompressed with gzip and the extracted JSON document is saved in the <strong>TRACE</strong> column of the <strong>EBAJ_OTEL_TRACES table.</strong></p>
<pre><code class="language-sql">declare
   l_uncompressed_blob blob;
   l_json              clob;
begin
   l_uncompressed_blob := utl_compress.lz_uncompress(:body);
   l_json := apex_util.blob_to_clob(l_uncompressed_blob);
   insert into otel_traces(trace) values(l_json);
   dbms_lob.freeTemporary(l_uncompressed_blob);
end;
</code></pre>
<p><strong>The client logging service</strong> is now complete. Copy and record <strong>the full URL</strong> of the resource handler as you will set it as <strong>the client logging service URL.</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/33cf8a76-4d00-4339-9f1c-2a49ba39adce.png" alt="" style="display:block;margin:0 auto" />

<h2>Creating the Token Relay Service</h2>
<p>The whole process however is a bit different than we are used to as APEX / ORDS service developers. Instead of providing a client-id / secret to the application, remember we only gave APEX a "Token Relay URL". This will be a public service that APEX will call to retrieve a token.</p>
<p>It will then use that token to call the Client Logging Service</p>
<p>The process below falls apart in these steps:</p>
<ol>
<li><p>create rest client (Client-ID and Secret)</p>
</li>
<li><p>store these client-credentials within APEX builder</p>
</li>
<li><p>create the Token Relay service that will turn the client-credentials into a token</p>
</li>
</ol>
<p>The OpenTelemetry implementation in Oracle APEX expects <strong>the client logging service URL to be protected with OAuth2 authentication, and the token relay URL</strong> is called to obtain the access token to be placed in the Authorization header.</p>
<p>Configure the module that implements the client logging service to require OAuth2 authentication when accessing <strong>OpenTelemetry .</strong></p>
<p>Run the following script. It will secure the module OpenTelemetry with OAuth2 and print <strong>the client_id</strong> and <strong>client_secret needed to access it.</strong></p>
<pre><code class="language-sql">declare
  C_MODULE_NAME constant varchar2(40) := 'OpenTelemetry';
  C_ROLE_NAME   constant varchar2(40) := 'opentelemetry_client';
  C_PRIV_NAME   constant varchar2(40) := 'opentelemetry.priv';
  C_OAUTH_NAME  constant varchar2(40) := 'opentelemetry_client';
  l_priv_roles    owa.vc_arr;
  l_priv_patterns owa.vc_arr;
  l_priv_modules  owa.vc_arr;
  l_exist number;
  l_client_id     user_ords_clients.client_id%type;
  l_client_secret user_ords_clients.client_secret%type;
begin
  -- check if role C_ROLE_NAME is exist
  select count(*) 
  into l_exist 
  from user_ords_roles 
  where name = C_ROLE_NAME;
  if l_exist = 0 then
    -- create role
    ords.create_role( p_role_name =&gt; C_ROLE_NAME );
    dbms_output.put_line('Role ' || C_ROLE_NAME || ' is created.');
  else
    dbms_output.put_line('Role ' || C_ROLE_NAME || ' not created.');
  end if;
  -- check if privilege C_PRIV_NAME is exist
  select count(*) 
  into l_exist 
  from user_ords_privileges
  where name = C_PRIV_NAME;
  if l_exist = 0 then
    -- create priv
    l_priv_roles(1)   := C_ROLE_NAME;
    l_priv_modules(1) := C_MODULE_NAME;
    ords.define_privilege(
      p_privilege_name =&gt; C_PRIV_NAME
     ,p_roles    =&gt; l_priv_roles
     ,p_patterns =&gt; l_priv_patterns
     ,p_modules  =&gt; l_priv_modules
     ,p_label    =&gt; 'opentelemetry'
     ,p_description =&gt; 'priv for opentelemetry traces url'
     ,p_comments =&gt; ''
     );
    dbms_output.put_line('Privilege ' || C_PRIV_NAME || ' created.');
  else
    dbms_output.put_line('Privilege ' || C_PRIV_NAME || ' not created.');
  end if;
  -- check if oauth client is exist
  select count(*) 
  into l_exist
  from user_ords_clients
  where name = C_OAUTH_NAME;
  if l_exist = 0 then
    -- create oauth client
    oauth.create_client(
      p_name =&gt; C_OAUTH_NAME
     ,p_grant_type =&gt; 'client_credentials'
     ,p_description =&gt; 'access OpenTelemetry receivers'
     ,p_support_email   =&gt; 'your.email@example-domain.com'
     ,p_privilege_names =&gt; C_PRIV_NAME
     );
    dbms_output.put_line('OAuth client ' || C_OAUTH_NAME || ' created.');
  else
    dbms_output.put_line('OAuth client ' || C_OAUTH_NAME || ' not created.');
  end if;
  -- grant role to oauth client
  oauth.grant_client_role(
      p_client_name =&gt; C_OAUTH_NAME
      ,p_role_name  =&gt; C_ROLE_NAME
  );
  dbms_output.put_line('Role ' || C_ROLE_NAME || ' has is granted to OAuth user ' || C_OAUTH_NAME || '.');
  -- print client_id and client_secret
  select client_id
        ,client_secret
  into l_client_id
      ,l_client_secret
  from user_ords_clients
  where name = C_OAUTH_NAME;
  dbms_output.put_line('grant_type: client_credentials');
  dbms_output.put_line('client_id: ' || l_client_id);
  dbms_output.put_line('client_secret: ' || l_client_secret);
end;
/
</code></pre>
<p>Copy and record <strong>the client_id</strong> and <strong>client_secret</strong> that are printed as you will need them when creating <strong>web credentials</strong> for APEX .</p>
<pre><code class="language-sql">declare
  C_ROLE_NAME  constant varchar2(40) := 'opentelemetry_client';
  C_PRIV_NAME  constant varchar2(40) := 'opentelemetry.priv';
  C_OAUTH_NAME constant varchar2(40) := 'opentelemetry_client';
  l_exist number;
begin
  -- delete OAuth client.
  select count(*) 
  into l_exist
  from user_ords_clients 
  where name = C_OAUTH_NAME;
  if l_exist = 1 then
    oauth.delete_client( p_name =&gt; C_OAUTH_NAME );
    dbms_output.put_line('OAuth client deleted.');
  end if;
  -- delete privilege.
  select count(*) 
  into l_exist
  from user_ords_privileges 
  where name = C_PRIV_NAME;
  if l_exist = 1 then
    ords.delete_privilege( p_name =&gt; C_PRIV_NAME );
    dbms_output.put_line('Privilege deleted.');
  end if;
  -- delete role.
  select count(*)
  into l_exist
  from user_ords_roles
  where name = C_ROLE_NAME;
  if l_exist = 1 then
    ords.delete_role( p_role_name =&gt; C_ROLE_NAME );
    dbms_output.put_line('Role is deleted.');
  end if;
end;
/
</code></pre>
<p>Open <strong>the Workspace Utilities</strong> Web <strong>Credentials</strong> and create a new <strong>web credential.</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/c3532135-e89f-4fbb-8668-56d4a4f7e979.png" alt="" style="display:block;margin:0 auto" />

<p>Create <strong>a web credential</strong> named OpenTelemetry with <strong>a static ID</strong> of <strong>OPENTELEMETRY</strong> . Select <strong>OAuth2 Client Credentials</strong> as <strong>the authentication type.</strong></p>
<p>Enter <strong>the client_id</strong> value printed as a result of running the script above as <strong>the client ID or username , and the client_secret</strong> value as <strong>the client secret or password.</strong></p>
<p>That's it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/45e41478-c2a0-48f0-80e4-878d6be68b70.png" alt="" style="display:block;margin:0 auto" />

<p><strong>A web credential</strong> , OpenTelemetry (Static ID: <strong>OPENTELEMETRY</strong> ), has been created.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6392045c0771b6e5cf4a8714/26c58f5a-f89a-4090-8915-597d1440c621.png" alt="" style="display:block;margin:0 auto" />

<p>Create a service in Oracle REST Data Services that uses these web credentials to obtain an access token - this service will be <strong>your token relay .</strong></p>
<p><strong>Open the RESTful service</strong> and create a module, <strong>name</strong> it <strong>OpenTelemetry-Auth</strong> and use <strong>the base path</strong> / <strong>otel-auth/.</strong></p>
]]></content:encoded></item><item><title><![CDATA[To open "Datamodeler.app", you need to install Rosetta. Do you want to install it now?]]></title><description><![CDATA[No I do not.

There are two solutions:

Start the datamodeler by running the “./Datamodeler.app/Content/MacOS/datamodeler.sh”

This is what I did for a couple of moths. Cumbersome, but it works! I created a “.command” file in the /Applications folder...]]></description><link>https://blog.rhjmartens.nl/to-open-datamodelerapp-you-need-to-install-rosetta-do-you-want-to-install-it-now</link><guid isPermaLink="true">https://blog.rhjmartens.nl/to-open-datamodelerapp-you-need-to-install-rosetta-do-you-want-to-install-it-now</guid><category><![CDATA[Oracle Data Modeler]]></category><category><![CDATA[PL/SQL]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Mon, 01 Dec 2025 14:24:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/qK39tusA9uE/upload/4e5653be2292f6285ad629ec8dd07b1c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>No I do not.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764598731775/09717aa5-8e79-4b74-bff5-5a993b90544e.png" alt class="image--center mx-auto" /></p>
<p>There are two solutions:</p>
<ul>
<li>Start the datamodeler by running the “./Datamodeler.app/Content/MacOS/datamodeler.sh”</li>
</ul>
<p>This is what I did for a couple of moths. Cumbersome, but it works! I created a “.command” file in the /Applications folder, so I could double-click that to start the datamodler.</p>
<p>The downside of course is that it will also start a terminal window. This must be closed manually after use of the modeler.</p>
<ul>
<li>Start the modeler with a double-click as we’re used to</li>
</ul>
<p>For this you need to right click the Datamodeler.app file:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764598985860/5b0c75a9-9058-445d-858b-25c2a5a7ea28.png" alt class="image--center mx-auto" /></p>
<p>uncheck the “Open using Rosetta” tick-box.</p>
<p>You’re done.</p>
]]></content:encoded></item><item><title><![CDATA[Oracle Font APEX - hidden (and undocumented) icons]]></title><description><![CDATA[I love the Font APEX icons. Hundreds of icons free to use in any APEX application. Since it is also present on GitHub (https://oracle.github.io/font-apex/index.html) you can even use them in a non-apex application.
I use Google authentication a lot, ...]]></description><link>https://blog.rhjmartens.nl/oracle-font-apex-hidden-icons</link><guid isPermaLink="true">https://blog.rhjmartens.nl/oracle-font-apex-hidden-icons</guid><category><![CDATA[Apex]]></category><category><![CDATA[font apex]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Mon, 02 Jun 2025 11:15:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/BVyNlchWqzs/upload/55b87d7114190cafd4e126236e1ae874.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I love the Font APEX icons. Hundreds of icons free to use in any APEX application. Since it is also present on GitHub (<a target="_blank" href="https://oracle.github.io/font-apex/index.html">https://oracle.github.io/font-apex/index.html</a>) you can even use them in a non-apex application.</p>
<p>I use Google authentication a lot, and always used the “fa-google” icon on the button that allows such authentication. Without even thinking about it. This morning suddenly I thought: What other icons do I have?<br />I therefore went to the link on <a target="_blank" href="https://oracle.github.io/font-apex/index.html">github</a> and had a look. To my surprise I couldn’t find any of them. They were however properly displayed in my app. So where are they defined and what other icons are available?</p>
<p>Looking at the HTML and CSS of my displayed google icon I found that these “extras” do heavily rely on the <code>font-apex.min.css</code> however they are not defined there. Their definition is in <code>Core.min.css</code>, part of the universal theme.</p>
<p>Here is a list of icons that we can find there:</p>
<p>All css classes are prefixed with “fa-”. Just like you’re used to with other font-apex icons.</p>
<p>I hope the APEX team reads this… :-) I do have some ideas for other brands to be included:</p>
<ul>
<li><p>apple (fa-apple)</p>
</li>
<li><p>android (fa-android)</p>
</li>
<li><p>bluesky (fa-bluesky)</p>
</li>
<li><p>hashnode (fa-hashnode)</p>
</li>
<li><p>windows (fa-mswindows)</p>
</li>
<li><p>mac-os (fa-macos)</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748861703927/ce32b585-0428-43e4-959a-e2e24e61bdf3.png" alt class="image--center mx-auto" /></p>
<p>Next to all these “branded” icons we now also have “flag-icons”:</p>
<p>A full list of flag-icons can be retrieved with following SQL:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * 
  <span class="hljs-keyword">from</span> APEX_DG_BUILTIN_FONTAPEX 
 <span class="hljs-keyword">where</span> ICON_CATEGORY = <span class="hljs-string">'FLAG'</span> 
 <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> icon_name
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748862862287/b686e4b0-447b-4086-bb73-5b2d62f79046.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Oracle Font APEX icon builder]]></title><description><![CDATA[Yes, I advised everyone to use the Universal Theme sample application to build their icons.
It’s convenient, we can copy all our classes, change the behaviour of the icons and what not. We should all love that, and we do.
However, I did found an alte...]]></description><link>https://blog.rhjmartens.nl/oracle-font-apex-icon-builder</link><guid isPermaLink="true">https://blog.rhjmartens.nl/oracle-font-apex-icon-builder</guid><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Mon, 27 Jan 2025 08:55:28 GMT</pubDate><content:encoded><![CDATA[<p>Yes, I advised everyone to use the Universal Theme sample application to build their icons.</p>
<p>It’s convenient, we can copy all our classes, change the behaviour of the icons and what not. We should all love that, and we do.</p>
<p>However, I did found an alternative that has a better response time (the UT app can be a bit “sluggish”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737967950065/acf0704d-d71d-4588-833b-3115217bb4a3.png" alt class="image--center mx-auto" /></p>
<p>Hosted on GitHub: <a target="_blank" href="https://oracle.github.io/font-apex/index.html">https://oracle.github.io/font-apex/index.html</a></p>
<p>It also allows creating our icons in a similar way:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737968051048/341bd32c-c249-4010-b841-008d2d0ba963.png" alt class="image--center mx-auto" /></p>
<p>regards,<br />Richard</p>
]]></content:encoded></item><item><title><![CDATA[Presentations]]></title><description><![CDATA[DateConferenceCityTitle



18 Dec 2023SPOUGonlinePLSQL-OO an object oriented approach to table API’s

2 Jun 2023SIOUGPortorozUnderstanding auto-rest (ORDS on steroids)

1 Jun 2023SIOUGPortorozAPEX Application lifecycle with feature based deployment

...]]></description><link>https://blog.rhjmartens.nl/presentationsthroughouttime</link><guid isPermaLink="true">https://blog.rhjmartens.nl/presentationsthroughouttime</guid><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Sun, 24 Dec 2023 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Hb6uWq0i4MI/upload/d2d477fb1226fe41bb5a53a3bc4ff499.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="hn-table">
<table>
<thead>
<tr>
<td>Date</td><td>Conference</td><td>City</td><td>Title</td></tr>
</thead>
<tbody>
<tr>
<td>18 Dec 2023</td><td>SPOUG</td><td>online</td><td>PLSQL-OO an object oriented approach to table API’s</td></tr>
<tr>
<td>2 Jun 2023</td><td>SIOUG</td><td>Portoroz</td><td>Understanding auto-rest (ORDS on steroids)</td></tr>
<tr>
<td>1 Jun 2023</td><td>SIOUG</td><td>Portoroz</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>3 May 2023</td><td>APEX Connect</td><td>Berlin</td><td>APEX, PLSQL and RESTful services II: Consuming Secure Services</td></tr>
<tr>
<td>3 May 2023</td><td>APEX Connect</td><td>Berlin</td><td>APEX, PLSQL and RESTful services I: Publishing Secure Services</td></tr>
<tr>
<td>21 Apr 2023</td><td>Apex Alpe Adria</td><td>Zagreb</td><td>APEX, PLSQL and RESTful services I: Publishing Secure Services</td></tr>
<tr>
<td>4 Apr 2023</td><td>SOUG</td><td>Winterthur</td><td>APEX, PLSQL and RESTful services I: Publishing Secure Services</td></tr>
<tr>
<td>31 Mar 2023</td><td>APEX World</td><td>Zeist</td><td>Are you a report-conductor?</td></tr>
<tr>
<td>30 Mar 2023</td><td>APEX World</td><td>Zeist</td><td>About the menu (a la carte or from the menu?)</td></tr>
<tr>
<td>2 Dec 2022</td><td>UKOUG</td><td>Liverpool</td><td>Utilizing the data attribute: Client-side behavior in APEX</td></tr>
<tr>
<td>2 Dec 2022</td><td>UKOUG</td><td>Liverpool</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>1 Dec 2022</td><td>UKOUG</td><td>Liverpool</td><td>Utilizing the data attribute: Client-side behavior in APEX</td></tr>
<tr>
<td>13 Oct 2022</td><td>HROUG</td><td>Rovinj</td><td>APEX, PLSQL and RESTful services Part I: Consuming Secure Services</td></tr>
<tr>
<td>13 Oct 2022</td><td>HROUG</td><td>Rovinj</td><td>APEX, PLSQL and RESTful services Part II: Publishing Secure Services</td></tr>
<tr>
<td>12 Oct 2022</td><td>HROUG</td><td>Rovinj</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>6 Oct 2022</td><td>RoOUG</td><td>Bucharest</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>20 Sep 2022</td><td>DOAG</td><td>Nürnberg</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>5 Sep 2022</td><td>SWEOUG</td><td>Stockholm</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>22 Jun 2022</td><td>KSCOPE</td><td>Grapevine,TX</td><td>APEX Application Lifecycle with Feature-based Deployment</td></tr>
<tr>
<td>21 Jun 2022</td><td>KSCOPE</td><td>Grapevine,TX</td><td>APEX’s Classic Report: The Power of No Template</td></tr>
<tr>
<td>20 Jun 2022</td><td>KSCOPE</td><td>Grapevine,TX</td><td>Developing Native-looking Apps with APEX for the Apple App Store and Google Play Store (cospeaker)</td></tr>
<tr>
<td>3 Jun 2022</td><td>SPOUG</td><td>Online</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>25 May 2022</td><td>APEX World</td><td>Zeist</td><td>APEX, PLSQL and RESTful services I: Consuming Secure Services</td></tr>
<tr>
<td>17 May 2022</td><td>SOUG</td><td>Winterthur</td><td>PLSQL-OO an object oriented approach to table API’s</td></tr>
<tr>
<td>3 May 2022</td><td>APEX Connect</td><td>Brühl</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>22 Apr 2022</td><td>AAAPEKS</td><td>Maribor</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>14 Oct 2021</td><td>HROUG</td><td>Rovinj</td><td>PLSQL-OO an object oriented approach to table API’s</td></tr>
<tr>
<td>29 Sep 2021</td><td>APEX World</td><td>Zeist</td><td>APEX Application lifecycle with feature based deployment</td></tr>
<tr>
<td>5 Jun 2020</td><td>APEX Connect</td><td>online</td><td>Using RESTful Services and Remote SQL</td></tr>
<tr>
<td>4 Dec 2019</td><td>UKOUG</td><td>Brighton</td><td>APEX’s classic report: the power of no template</td></tr>
<tr>
<td>1 Dec 2019</td><td>UKOUG</td><td>Brighton</td><td>PLSQL-OO an object oriented approach to table API’s</td></tr>
<tr>
<td>21 Nov 2019</td><td>DOAG</td><td>Nürnberg</td><td>APEX’s classic report: the power of no template</td></tr>
<tr>
<td>20 Nov 2019</td><td>DOAG</td><td>Nürnberg</td><td>APEX: My user is socially authenticated, now what?</td></tr>
<tr>
<td>19 Nov 2019</td><td>DOAG</td><td>Nürnberg</td><td>PLSQL-OO: An Object Oriented approach to Table API’s</td></tr>
<tr>
<td>18 Oct 2019</td><td>HROUG</td><td>Rovinj</td><td>APEX’s classic report: the power of no template</td></tr>
<tr>
<td>17 Oct 2019</td><td>HROUG</td><td>Rovinj</td><td>APEX: My user is socially authenticated, now what?</td></tr>
<tr>
<td>16 Oct 2019</td><td>HROUG</td><td>Rovinj</td><td>KANBAN Game for developers (and business analysts)</td></tr>
<tr>
<td>14 Oct 2019</td><td>SIOUG</td><td>Portoroz</td><td>APEX’s classic report: the power of no template</td></tr>
<tr>
<td>6 Sep 2019</td><td>POUG</td><td>Wraclaw</td><td>APEX’s classic report: the power of no template</td></tr>
<tr>
<td>8 Jun 2019</td><td>BGOUG spring</td><td>Borovets</td><td>APEX: My user is socially authenticated, now what?</td></tr>
<tr>
<td>7 Jun 2019</td><td>BGOUG spring</td><td>Borovets</td><td>KANBAN Game for developers (and business analysts)</td></tr>
<tr>
<td>12 Apr 2019</td><td>AAAPEKS</td><td>Zagreb</td><td>After the social login feature of APEX do additional REST calls to Google / Facebook API’s</td></tr>
<tr>
<td>21 Nov 2017</td><td>DOAG</td><td>Nürnberg</td><td>Utilizing the data attribute: Client-side behavior in APEX.</td></tr>
<tr>
<td>19 Oct 2017</td><td>HROUG</td><td>Rovinj</td><td>Utilizing the data attribute: Client-side behavior in APEX.</td></tr>
<tr>
<td>3 Jun 2017</td><td>BGOUG spring</td><td>Pravets</td><td>Utilizing the data attribute: Client-side behavior in APEX.</td></tr>
<tr>
<td>3 Jun 2017</td><td>BGOUG spring</td><td>Pravets</td><td>Validate User input in APEX</td></tr>
<tr>
<td>4 Dec 2016</td><td>UKOUG</td><td>Birmingham</td><td>Bootstrap authentication and authorization</td></tr>
<tr>
<td>15 Nov 2016</td><td>DOAG</td><td>Nürnberg</td><td>Validate User Input in APEX</td></tr>
<tr>
<td>15 Nov 2016</td><td>DOAG</td><td>Nürnberg</td><td>Bootstrap APEX Authentication and Authorization</td></tr>
<tr>
<td>12 Nov 2016</td><td>BGOUG autumn</td><td>Pravets</td><td>Bootstrap authentication and authorization in Oracle APEX</td></tr>
<tr>
<td>12 Nov 2016</td><td>BGOUG autumn</td><td>Pravets</td><td>Google Apps integration in Oracle APEX</td></tr>
<tr>
<td>19 Oct 2016</td><td>HROUG</td><td>Rovinj</td><td>Bootstrap authentication and authorization</td></tr>
<tr>
<td>19 Oct 2016</td><td>HROUG</td><td>Rovinj</td><td>Validate user input in apex</td></tr>
<tr>
<td>18 Oct 2016</td><td>SIOUG</td><td>Portoroz</td><td>Bootstrap authentication and authorization</td></tr>
<tr>
<td>17 Oct 2016</td><td>SIOUG</td><td>Portoroz</td><td>Validate user input in APEX</td></tr>
<tr>
<td>22 Jun 2016</td><td>OUG Scotland</td><td>Glasgow</td><td>User validation in Oracle APEX</td></tr>
<tr>
<td>25 May 2016</td><td>SROUG</td><td>Zlatibor</td><td>Validations in Oracle APEX</td></tr>
<tr>
<td>25 May 2016</td><td>SROUG</td><td>Zlatibor</td><td>Google Apps Integration in APEX</td></tr>
<tr>
<td>2 Mar 2016</td><td>LVOUG</td><td>Riga</td><td>Google Apps Integration in Oracle Apex</td></tr>
<tr>
<td>2 Mar 2016</td><td>LVOUG</td><td>Riga</td><td>Validate User input in APEX</td></tr>
<tr>
<td>6 Dec 2015</td><td>UKOUG</td><td>Birmingham</td><td>Google Apps integration in Oracle Apex</td></tr>
<tr>
<td>17 Nov 2015</td><td>DOAG</td><td>Nürnberg</td><td>Integrating APEX and Social media</td></tr>
<tr>
<td>15 Oct 2015</td><td>HROUG</td><td>Rovinj</td><td>Google Apps integration in Apex</td></tr>
<tr>
<td>15 Oct 2015</td><td>HROUG</td><td>Rovinj</td><td>Twitter Bootstrap APEX Theme</td></tr>
<tr>
<td>12 Oct 2015</td><td>SIOUG</td><td>Portoroz</td><td>Google Apps Integration in APEX.</td></tr>
<tr>
<td>24 Jun 2015</td><td>KSCOPE</td><td>Hollywood,FL</td><td>Google Apps Integration in APEX</td></tr>
</tbody>
</table>
</div>]]></content:encoded></item><item><title><![CDATA[a trip down memory lane]]></title><description><![CDATA[I cannot however publish a blog post where our friend Joel is mentioned without reflecting on the relationship I had with him.
The first time I met Joel was at the OGH (now NLOUG) conference APEX-World in Zeist. I think it was the last time the confe...]]></description><link>https://blog.rhjmartens.nl/joelkallmanday2023</link><guid isPermaLink="true">https://blog.rhjmartens.nl/joelkallmanday2023</guid><category><![CDATA[JoelKallmanDay]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Wed, 11 Oct 2023 14:26:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697034185270/84afacfb-5c38-42e5-9573-888a799cf874.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I cannot however publish a blog post where our friend Joel is mentioned without reflecting on the relationship I had with him.</p>
<p>The first time I met Joel was at the OGH (now NLOUG) conference APEX-World in Zeist. I think it was the last time the conference was held at the Figi Hotel there. I felt so honored to have met him.</p>
<p>But I remember him on so many more occasions and am happy I was able to introduce him to my wife Indyra and son Eric one Saturday. It was this Saturday that we spent having a beer (or some..) at the monastery close to my home-town of Tilburg (<a target="_blank" href="https://uk.latrappetrappist.com/gb/en.html?uri=/content/latrappe/gb/en.html">https://uk.latrappetrappist.com/gb/en.html?uri=/content/latrappe/gb/en.html</a>) We were practicing his presentation that he would do next Monday.. The result you can see below.</p>
<p>Joel, you are still in our prayers... I am convinced you are in the presence of the Lord we both love. If anybody ever showed to be worthy of such a privilege it is you. I thank you for having been in my life.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/_zz9tREWJbs">https://youtu.be/_zz9tREWJbs</a></div>
]]></content:encoded></item><item><title><![CDATA[Pronounceable password generator in PL/SQL]]></title><description><![CDATA[How often do I need to generate a password for one of my database users and colleagues?
Here is how I do that.
function auth_pwgen return varchar2 is
  l_pos integer;
  l_pw  varchar2(100);
  l_c   varchar2(100) := 'bcdfghjklmnprstvwz'; --consonants
...]]></description><link>https://blog.rhjmartens.nl/pronounceable-password-generator-in-plsql</link><guid isPermaLink="true">https://blog.rhjmartens.nl/pronounceable-password-generator-in-plsql</guid><category><![CDATA[PL/SQL]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Wed, 02 Nov 2022 15:44:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/f0QiOMWdP-o/upload/de95935be50df91c00291225a23919fa.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How often do I need to generate a password for one of my database users and colleagues?</p>
<p>Here is how I do that.</p>
<pre><code class="lang-sql">function auth_pwgen return varchar2 is
  l_pos integer;
  l_pw  varchar2(100);
  l_c   varchar2(100) := 'bcdfghjklmnprstvwz'; <span class="hljs-comment">--consonants</span>
  l_v   varchar2(100) := 'aeiou'; <span class="hljs-comment">--vowels</span>
  l_a   varchar2(100) := l_c || l_v; <span class="hljs-comment">--both</span>
  l_s   varchar2(100) := '!@<span class="hljs-comment">#$%^&amp;*()';</span>
<span class="hljs-keyword">begin</span>
  <span class="hljs-comment">--use three syllables...</span>
  <span class="hljs-keyword">for</span> ii <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> .. <span class="hljs-number">3</span>
  <span class="hljs-keyword">loop</span>
    l_pw := l_pw || <span class="hljs-keyword">substr</span>(l_c, trunc(dbms_random.value(<span class="hljs-number">0</span>, <span class="hljs-keyword">length</span>(l_c))), <span class="hljs-number">1</span>);
    l_pw := l_pw || substr(l_v, trunc(dbms_random.value(0, length(l_v))), 1);
    l_pw := l_pw || substr(l_a, trunc(dbms_random.value(0, length(l_a))), 1);
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">loop</span>;
  <span class="hljs-comment">--... Make one Uppercase</span>
  l_pos := round(dbms_random.value(1, length(l_pw)));
  l_pw  := substr(l_pw, 1, l_pos - 1) 
        || upper(substr(l_pw, l_pos, 1)) 
        || substr(l_pw, l_pos + 1);
  <span class="hljs-comment">--... and add a nice number</span>
  l_pw := l_pw || round(dbms_random.value(10, 99));
  <span class="hljs-comment">--... and add a special character</span>
  l_pw := l_pw || substr(l_s, dbms_random.value(1, length(l_s)), 1);

  return l_pw;

<span class="hljs-keyword">end</span> auth_pwgen;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OCI connections to multiple Autonomous Transaction Databases in the Oracle Always Free cloud]]></title><description><![CDATA[I still use PL/SQL developer to work in our Oracle Databases. It is a tool I’ve been using for years and old habits seldom die.. In fact Pl/SQL developer is the only sound reason I have parallels desktop (nowadays: UTM) installed on my Mac.

PL/SQL d...]]></description><link>https://blog.rhjmartens.nl/oci-connections-to-multiple-autonomous-transaction-databases-in-the-oracle-always-free-cloud</link><guid isPermaLink="true">https://blog.rhjmartens.nl/oci-connections-to-multiple-autonomous-transaction-databases-in-the-oracle-always-free-cloud</guid><category><![CDATA[tnsnames]]></category><category><![CDATA[database]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Tue, 08 Oct 2019 21:37:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/eb0DNqbzrNU/upload/daab3a941c4caec111d0712dc7d3a670.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I still use PL/SQL developer to work in our Oracle Databases. It is a tool I’ve been using for years and old habits seldom die.. In fact Pl/SQL developer is the only sound reason I have parallels desktop (nowadays: UTM) installed on my Mac.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036768549/88d94172-25a6-4c86-9c85-9ddea0070850.png" alt="🙂" /></p>
<p>PL/SQL developer connects to the database using an Oracle Client. This can be a full blown client or it can be the InstantClient. I use the latter.</p>
<p>You must have heard about Oracles “Always Free Autonomous cloud”. I love it.</p>
<p>When you create a database and must connect to it, be it SQL Developer or an OCI using program (like PLSQL Developer). You first must dowload a wallet. We should make a small change to our sqlnet.ora file and copy the entries into our tnsnames.ora. This works like a charm, until you must connect to multiple databases, in multiple domains.</p>
<p>I solved it as follows:</p>
<ol>
<li><p>My client resides in C:\Oracle\</p>
</li>
<li><p>My windows environment says: TNS_ADMIN = C:\Oracle\</p>
</li>
<li><p>I created an extra folder structure:</p>
<ol>
<li><p>C:\Oracle\wallets\devdomain</p>
</li>
<li><p>C:\Oracle\wallets\tstdomain</p>
</li>
</ol>
</li>
<li><p>The wallet.zip for the devdomain I placed in the “devdomain” directory and of course the tstdomain.zip I placed in “tstdomain” and unzipped both in their folders</p>
</li>
<li><p>I didn’t touch the sqlnet.ora for me it looks like<br /> SSL_SERVER_DN_MATCH=yes</p>
</li>
<li><p>I refer to the wallet location in the tnsnames.ora file:</p>
<pre><code class="lang-plaintext"> oraconfxdev_high.richardmartens.oci = 
    (description= (retry_count=20)(retry_delay=3)
       (address=(protocol=tcps)(port=1522)
          (host=adb.eu-amsterdam-1.oraclecloud.com))
    (connect_data=
       (service_name=something_goes_here_high.adb.oraclecloud.com))
    (security=
       (MY_WALLET_DIRECTORY = "C:\the\dir\containing\unzipped\wallet")
       (ssl_server_dn_match=yes)))
</code></pre>
</li>
</ol>
<p>So I added the line that says where this entry should take the wallet from. (MY_WALLET_LOCATION)</p>
<p>Now PLSQL Developer is able to connect to all my instances, however before switching from one DB to another I first nicely must log-off. Logging on into a database while still connected to another gives me a ORA-12529: TNS:connect request rejected based on current filtering rules.</p>
<p>Logging of before establishing a new connection is something I can live with.</p>
<p>Regards,<br />Richard</p>
]]></content:encoded></item><item><title><![CDATA[The kanban game for developers and business-analysts]]></title><description><![CDATA[It was March 2018 when Jasper Alblas and Frans Jacobs introduced me to a nice way of explaining the advantages of Kanban within a Scrum environment.
In the Agile world, Kanban and Scrum have been seen as separate frameworks/practices, but as we all k...]]></description><link>https://blog.rhjmartens.nl/the-kanban-game-for-developers-and-business-analysts</link><guid isPermaLink="true">https://blog.rhjmartens.nl/the-kanban-game-for-developers-and-business-analysts</guid><category><![CDATA[events]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Sat, 18 May 2019 11:00:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036841683/75184b3e-640f-4e03-861b-4ecd8403441b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It was March 2018 when Jasper Alblas and Frans Jacobs introduced me to a nice way of explaining the advantages of Kanban within a Scrum environment.</p>
<p>In the Agile world, Kanban and Scrum have been seen as separate frameworks/practices, but as we all know Scrum teams practice Kanban as well.</p>
<p>With this guide, The practice of Kanban within Scrum is formalized without adding or deducting anything from Scrum or Kanban but recognizing the strength of using both.</p>
<p>We probably can learn a lot and improve our Kanban practices, so that’s why I proposed doing a Kanban workshop, so we can look at this guide and see how we can improve flow, focus and collaboration using Kanban.</p>
<p>Please download the file below</p>
<p><a target="_blank" href="https://smart4solutions.nl/blog/wp-content/uploads/2019/05/2018-Kanban-Guide-for-Scrum-Teams_0.pdf">2018 Kanban Guide for Scrum Teams_0</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036778472/0cb6819d-5975-4563-87c6-fabde4f00a7b.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036781500/818ad526-44e6-42a7-ac73-fceadd3940d6.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036784972/097cb80c-01d1-4109-a9d4-acfbac5f9913.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036787595/642ff3a4-dd68-441d-b07f-a1a5c7a3aba6.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036790766/ecca35fa-c5c5-4407-8751-a6ade3a78d86.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036793683/2aa58044-b77a-46fb-897b-9b07664658a7.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036796797/45245f63-c3f8-4bfa-8308-6701f6be4883.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036799958/6f7128c3-96c0-41f5-9794-1a6f35897de6.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036803128/c0d3ed69-b49f-4083-bfe5-9008d046524f.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036806476/144630a4-697c-4202-ad73-2e5a486845ce.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036809171/34b122ed-92a7-46e4-80a7-553237b00f6c.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036812259/eed2d3cb-7e76-4826-8596-13c62ca41650.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036815327/05a3363f-e4c8-42ae-b0b3-0e5e45d06ce2.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036818806/c3ed54dc-befd-4845-b30f-81057c893f88.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036822493/9d7e1f0d-6a17-4893-8474-ff421d76538e.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036825516/b9f37273-f691-403e-8a5f-92d41dc1e0cb.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036828293/59e34c01-282e-441c-8c4b-73ddebf0614d.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036831446/e93a7382-f08e-4e80-8e89-c674ef80d348.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036834842/f3a0bacf-98bc-4c65-bd55-299f879fa82f.jpeg" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697036838346/81876340-021a-429a-9af7-f324df2072ca.jpeg" alt /></p>
]]></content:encoded></item><item><title><![CDATA[making https (webservice) requests from PL/SQL without a wallet]]></title><description><![CDATA[While developing the application for my kscope15 presentation I discovered that my Oracle XE database is unable to handle the certificate for Linked-in. This has to do with the algorithm used to sign the Linked-in certificate. Oracle XE 11 has a bug ...]]></description><link>https://blog.rhjmartens.nl/making-https-webservice-requests-from-plsql-without-a-wallet</link><guid isPermaLink="true">https://blog.rhjmartens.nl/making-https-webservice-requests-from-plsql-without-a-wallet</guid><category><![CDATA[orclapex]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[oracle pl/sql]]></category><category><![CDATA[PL/SQL]]></category><dc:creator><![CDATA[Richard Martens]]></dc:creator><pubDate>Thu, 09 Jul 2015 10:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721809710905/8d086c84-4f9f-467d-abad-c8c143dfff27.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While developing the application for my kscope15 presentation I discovered that my Oracle XE database is unable to handle the certificate for Linked-in. This has to do with the algorithm used to sign the Linked-in certificate. Oracle XE 11 has a bug that prevents it from handling the certificate correctly.</p>
<p>The solution lies in creating a proxy in between your database and the final API endpoint.<br />Like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721809710905/8d086c84-4f9f-467d-abad-c8c143dfff27.png?w=1600&amp;h=840&amp;fit=crop&amp;crop=entropy&amp;auto=compress,format&amp;format=webp" alt="making https (webservice) requests from PL/SQL without a wallet" /></p>
<ol>
<li><p>your pl/sql program uses UTL_HTTP or APEX_WEB_SERVICE.MAKE_REST_REQUEST to do the API-request to your Apache proxy.</p>
</li>
<li><p>The proxy uses its configuration to forward the request to the final endpoint</p>
</li>
<li><p>The endpoint replies to your proxy</p>
</li>
<li><p>Your proxy reverse proxies it to the requesting code inside your database</p>
</li>
</ol>
<p>In this drawing the green numbers are regular HTTP requests and the orange numbers represent HTTPS requests and responses.</p>
<p>This all sounds very promising. Getting rid of the Oracle wallet seems like a good idea. However you can set the greens to be HTTPS as well, in which case you only need to have one certificate in your wallet.</p>
<h3 id="heading-considerations">Considerations</h3>
<ul>
<li><p>My Oracle database server uses a private IP range.</p>
</li>
<li><p>My Apache server is accessible from the internet, but has a second network interface connected to the private IP range.</p>
</li>
</ul>
<h3 id="heading-setting-up-your-proxy"><strong>Setting up your proxy</strong></h3>
<p>Setting up the proxy consists of creating a new (virtual) site on your server. I chose to use the domain "revprox.local" because this domain will never get resolved into a real IP-number:</p>
<p>I now need to edit the httpd.conf for my apache server:</p>
<pre><code class="lang-bash">RewriteEngine On
ProxyVia On

<span class="hljs-comment">## proxy for linkedin</span>
ProxyRequests Off
SSLProxyEngine On


  Order deny,allow
  Allow from all


ProxyPass        /www.linkedin.com/     https://www.linkedin.com/
ProxyPassReverse /www.linkedin.com/     https://www.linkedin.com/
ProxyPass        /api.linkedin.com/     https://api.linkedin.com/
ProxyPassReverse /api.linkedin.com/     https://api.linkedin.com/
</code></pre>
<p>As you see in the linked-in API documentation, all API endpoint either are on https://www.linkedin.com/ or on http://api.linkedin.com. It is therefore sufficient to define these two in my httpd.conf.</p>
<h3 id="heading-setting-up-your-database">Setting up your database</h3>
<p>As I mentioned before, the url http://revprox.local will never resolve into anything useful. We must tell the database what to do when a request for revprox.local comes around.</p>
<p>We now only need to alter the /etc/hosts file as thus:</p>
<pre><code class="lang-plaintext">192.168.1.1     revprox.local
</code></pre>
<p>The trick lies in the last line:</p>
<ul>
<li><p>192.168.1.1 is the private IP number of my apache-proxy</p>
</li>
<li><p>In the example I removed extra lines that are not relevant for my story</p>
</li>
</ul>
<h3 id="heading-making-a-web-request">Making a web-request</h3>
<p>Now we set up the proxy and made changes to the /etc/hosts file we can actually start using them.</p>
<p>For example, when getting an oauth2 token from linked-in, the <a target="_blank" href="https://www.blogger.com/blog/post/edit/5795693851973117/2281539692030390001#">documentation</a> tells us to make a request to:</p>
<pre><code class="lang-plaintext">https://www.linkedin.com/uas/oauth2/accessToken
</code></pre>
<p>Instead we will be stubborn and use:</p>
<pre><code class="lang-plaintext">http://revprox.local/www.linkedin.com/uas/oauth2/accessToken
</code></pre>
<p>as the API endpoint.</p>
<p>That's all folks.</p>
]]></content:encoded></item></channel></rss>