In today’s post, we’ll be talking about the possible ways to manage the static images/CSS/JS that come shipped with APEX, when running on ORDS. They are separate resources (not contained in the DB like some other APEX images) necessary for your APEX applications look and behave the way they’re intended to. If you and your users browse your internet using lynx (see image below) feel free to skip this one. Otherwise - dig in!
The standard way
Normally, what you’d do is take the APEX images directory, pack them into a war and deploy the images in the /i/ context on the same app server that ORDS is deployed in (like it’s mentioned in the official installation guide. This is pretty straightforward and probably what will be sufficient for most. However, if you have multiple databases with APEX installed in them, possibly in different versions - this is where a problem arises.
So we have to provide different versions of the images for APEX to choose from. How should we do it and how do we tell APEX which one to choose?
The multi-database way - using aliases
Let’s say you have 3 databases - db1, db2 and db3. Db1 and db2 running APEX 18.2 and db3 running APEX 19.2.
In your application server include 2 folders with APEX images - apex_images1820 and apex_images1920. Then create 3 links - i_db1 and i_db2 pointing to apex_images1820 and i_db3 pointing to apex_images1920.
Then, for each of your APEX applications, you have to set the expected images’ context using the reset_images_prefix.sql script shipped with APEX.
SQL> @<apex directory>\utilities\reset_image_prefix.sql Enter the Application Express image prefix [/i/] /i_db1/
For db1 we set it to i_db1, db2 -> i_db2, db3 -> i_db3.
This way during APEX upgrade the DBAs take care of upgrading the APEX version in the database and all has to be done is to change the link in the application server. So let’s assume we’re upgrading db1. Simply change i_db1 to link to point to apex_images1920 and you’re done.
The multi-database way with the help of your friendly neighborhood DBA
Another approach to this is to leave all the work to the DBA - instead of setting up those aliases, just deploy the images folders - apex_images1820 and apex_images1920 in our case. Then with each upgrade remember to launch the reset_image_prefix scripts and point to the right context. This may sound simpler, but one thing has to be kept in mind, to cite Joel Kallman from Oracle:
“You should not do this on a live system, as this process will invalidate many objects in the APEX schema and they will need to be recompiled. Again - don't do this on a live system.”.
On the other hand, you’re upgrading your APEX schema anyway, so that shouldn’t be a that big of a problem.
Using a static file server
What if you have multiple application servers running ORDS (either to provide high availability or to serve different environments) and don’t want to store a multiplicity of the APEX static files? Thankfully you can point APEX to use an outside URL for requesting the files. Actually, even Oracle started providing these resources in CDN. You can either use the URLs provided by Oracle or, if you’d rather rely on your own infrastructure, create a static file server on your own - just be sure to include the
header to the responses, otherwise the browser will complain about CORS issues.
For example if you're running Apache HTTP Server, this small snippet may come in handy:
Header append Access-Control-Allow-Origin * Header merge Vary "Origin"
Use the same command as before to set the URL as image prefix. Like before, you have to take care of changing the prefix when upgrading.
Using the query parameter? Unfortunately not an option
One interesting thing that can be observed about the request made for the resource is a query parameter indicating a version, e.g.:
if a request is made on behalf of APEX 18.2. This looks very promising - we could envision a simple mod_rewrite or Tomcat’s adaptation to request the appropriate version of the resources automagically. Until it doesn’t - unfortunately some resources are requested without passing this parameter, for example:
If this one piece of the puzzle wasn’t missing, we would have a maintenance-free way of managing the APEX images - every APEX version would be directed to its corresponding resources.