Tuesday, June 11, 2019

See APEX Debug info in PL/SQL and SQL Developer

When developping Oracle APEX apps I like to instrument my code with APEX_DEBUG and/or Logger.

With our APEX Office Print (AOP) PL/SQL API and APEX Plug-in we did the same, we use APEX_DEBUG and Logger behind the scenes to allow you to see what it going on. But when I tried to view the APEX debug messages in SQL Developer, I didn't see any. Christian Neumueller of the APEX Dev team, gave me the answer: APEX debug is buffering it's output, to reduce the I/O overhead. Buffering is disabled for LEVEL9, but the other levels only write:
 - after 1000 records
 - at the end of request processing
 - when you detach the session

This explained perfectly what was happening for me.

Here's a quick example when you want to debug the AOP PL/SQL API from PL/SQL and SQL Developer. The code downloads an Interactive Report of page 200 to Excel and stores it in a table.

  l_return          blob;
  l_output_filename varchar2(100) := 'output';
  apex_debug.enable(p_level => apex_debug.c_log_level_info); 
                    -- for more details, use: c_log_level_app_trace
  apex_debug.message(p_message => 'Debug enabled.');

  l_return := aop_api_pkg.plsql_call_to_aop (
                p_data_type       => aop_api_pkg.c_source_type_rpt,
                p_data_source     => 'report1',
                p_template_type   => aop_api_pkg.c_source_type_apex,
                p_template_source => 'aop_template_ir_customers.xlsx',
                p_output_type     => aop_api_pkg.c_excel_xlsx,
                p_output_filename => l_output_filename,
                p_aop_url         => apex_app_setting.get_value('AOP_URL'),
                p_api_key         => apex_app_setting.get_value('AOP_API_KEY'),
                p_app_id          => 498,    
                p_page_id         => 200);   
  insert into aop_output (output_blob,filename) 
  values (l_return, l_output_filename);              
  dbms_output.put_line('To view debug messages:');
  dbms_output.put_line('select * from apex_debug_messages where session_id = '
    ||apex_util.get_session_state('APP_SESSION') ||' order by message_timestamp');


Running the SQL statement to view the debug messages:
select * from apex_debug_messages where session_id = 16458652970080 order by message_timestamp

Et voila... the APEX debug info is available straight away :)

Saturday, March 30, 2019

Monitoring your Oracle APEX environment; when is a good time to do an upgrade?

Yesterday Oracle released Oracle APEX 19.1. We typically upgrade our environment within a week.

The question is always, when is a good time to upgrade?

As we are hosting multiple applications and sites in our environment, we want to find a spot with minimal impact to our customers. For some applications which are only accessed by some people in Belgium, it's very easy to schedule an upgrade at night as the chances are not high people accessing the app. But in the case of APEX Office Print, we have customers all over the world in different timezones. So they might want to look at their dashboard or download the latest version at any moment in time.

For our AOP service itself, we have an internal policy we don't allow downtime. We load balance, so even when performing upgrades of AOP, there will always be a server available to handle the requests. For our Oracle database and APEX environment, we are fine with a few minutes downtime while upgrading the server.

In Oracle APEX itself, when you go to Monitor Activity - Page Views by User by Hour you get a graphical overview when your applications are being used:

This screen works well for a given workspace. If you want to look cross workspaces, for your entire APEX instance, you could build something yourself similar to the above. An overview like that would give you an idea based on historical usage which hours have the least amount of impact.

Now that you found the window, you still want to check if somebody is using our APEX apps.

So before I start an upgrade, I always check the last activity in our APEX apps.
The script I use to monitor the activity in our entire APEX environment - as SYS user run in SQL>

    TO_CHAR(session_created, 'DD-MON-YYYY HH24:MI') AS session_created,
    TO_CHAR(session_idle_timeout_on, 'DD-MON-YYYY HH24:MI') AS session_idle_timeout_on,
    TO_CHAR(session_idle_timeout_on-(session_max_idle_sec/24/60/60), 'DD-MON-YYYY HH24:MI') AS last_activity,
    TO_CHAR(sysdate, 'DD-MON-YYYY HH24:MI') AS time_now,
    round((sysdate-(session_idle_timeout_on-(session_max_idle_sec/24/60/60)))*24*60) as minutes_ago
 FROM apex_workspace_sessions
WHERE user_name NOT IN ('APEX_PUBLIC_USER','nobody')
ORDER BY minutes_ago, workspace_name, session_idle_timeout_on DESC;

This gives me the following overview:

So I see how many minutes ago (last column) which APEX workspace was used by which user. I could even follow the APEX session to find out more about the APP etc. but that is not really relevant for me. In the script, I only check for logged in users.

In case I also want to see for direct connections to the database, or I want more real-time info from the APEX session, I run the following script to check the session in the Oracle Database:

    --sql_id, sql_exec_start, event,
    client_info         AS workspace_id_auth_user,
    module              AS db_schema_apex_app_id_page_id,
    action              AS action,
    client_identifier   AS auth_user_apex_session
 FROM gv$session
WHERE type = 'USER'
  AND service_name = 'apex_pdb';

This gives me the following overview:

In the above screen you see I'm connected to the database with SQL Developer. The other sessions are coming from our connection pool. What is interesting is that APEX is instrumented to populate session info in the database like module, client_info, and client_identifier. This is important as APEX/ORDS is working with a connection pool so it would be hard to see what APEX session corresponded to which database session in case they didn't.

The above helps me to find a good time to perform upgrades, without impacting too many people.
So I thought to share my scripts as it might help you too.

Friday, March 29, 2019

Where are my static application files of Oracle APEX?

Ever got the error that there's an issue with your environment because the Application Express files have not been loaded when you try to open Oracle APEX in your environment?

Since the Announcement of the availability of Oracle APEX Static Resources on a Content Delivery Network I typically configure APEX to use the CDN.

Steps to do so for the entire environment:
  • Navigate to the apex/utilities subdirectory from the directory you unzipped APEX to
  • Connect to your database as the SYS user
  • Run:  @reset_image_prefix.sql
  • when prompted for the image prefix, enter the correct path, e.g. https://static.oracle.com/cdn/apex/
Now, when I got the above error, I forgot which images folder APEX was using. Was there an issue with the connection to the CDN, was it a local issue?

Below is how I found out how the APEX images directory was configured and if it was using the CDN or local files.
Connect as SYS in a SQL window (SQLcl, SQL Developer, SQL Plus, ...):

SQL> set serveroutput on
SQL> begin
  2  dbms_output.put_line(apex_180100.wwv_flow_image_prefix.g_image_prefix);
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL> begin
  2  dbms_output.put_line(apex_180200.wwv_flow_image_prefix.g_image_prefix);
  3  end;
  4  /

PL/SQL procedure successfully completed.

Above you see that in APEX 18.1 the /i/ directory is used on the local web server.
On APEX 18.2 the CDN is being used.

Note: whenever you run the above command change to the correct APEX user (version), so for APEX 19.1 you use apex_190100.

Friday, March 01, 2019

Including an image from APEX Static Application Files in an email

Some people use APEX Office Print (AOP) to send out HTML emails based on a custom HTML template they created. Today we got a question in our AOP support inbox how to include images in those emails.

In an AOP Template, you can use a tag {%image} and AOP will replace that tag with a base64 encoded image. This works great when you open the resulting HTML file in a browser, but when using emails it's not so great as some email clients don't support base64 encoded images e.g. Outlook.

That the images don't always work is not really an AOP issue, it's more an issue with HTML emails.
Here's a good read on supporting images in HTML emails.

In short, it's better to include an URL to the image as that is supported by most, if not all, email clients. Typically the images are stored in a BLOB column in a table or people want to reference an image that they uploaded in APEX > Shared Components > Static Application Files.

This blog post shows a technique to reference an image stored in the database through a URL.

1. Create a new Public Page in an Oracle APEX Application e.g. Page 22

2. Create a region on the page

3. Create a hidden item on the page e.g. P22_FILE_NAME

4. Create a Before header Process "Retrieve image from DB" with following PL/SQL Code:

  l_file_name     apex_application_static_files.file_name%type;
  l_mime_type     apex_application_static_files.mime_type%type;
  l_file_charset  apex_application_static_files.file_charset%type;  
  l_file_content  apex_application_static_files.file_content%type;
  select nvl(file_name, 'output') as file_name, 
         nvl(mime_type, 'application/octet-stream') as mime_type, 
         nvl(file_charset, 'utf-8') as file_charset, 
    into l_file_name, 
    from apex_application_static_files 
   where application_id = :APP_ID 
     and file_name      = :P22_FILE_NAME;
  owa_util.mime_header(l_mime_type, false);
  sys.htp.p('Content-Disposition:attachment; filename="'||l_file_name||'"; '||'filename*='||l_file_charset||''''''||l_file_name);

  when no_data_found

5. That's it.

Now you can reference the image with the following URL: https://my_server/ords/f?p=MY_APP:22:0::::P22_FILE_NAME:my_image.png

If you want to test the functionality in an email, go to SQL Workshop >SQL Commands and use the following code:

    p_to        => 'my@email.com',
    p_from      => 'my@email.com',
    p_subj      => 'Mail from APEX with inline image',
    p_body      => 'Please review the email in html.',
    p_body_html => 'Here the inline image: <br/> <img alt="Image" height="150" width="150" src="https://my_server/ords/f?p=MY_APP:22:0::::P22_FILE_NAME:my_image.png">');


Now you can send HTML emails in APEX with references to images that are stored in the database.

Sunday, February 10, 2019

Region only shown in development mode in Oracle APEX

In the last months, I had to look up several times in different projects how to show a region only when I was logged in into the App Builder in Oracle Application Express (APEX). So I thought to write a quick post on it.

In one project we had to log in with different users to test the behavior of the authorization schemes, so people saw the things they should see and could do the things they are allowed to do. As the logins where not straight forward we created a region with those test credentials. Other people were testing too with their own credentials, so we really wanted to keep the original login page, and decided to just add a region on the page we would only see when we were logged in into APEX itself.

Today I added some new pages to an app and wanted to make sure the navigation to those pages were only visible to me. I know, you should do this in DEV, and then when all is fine, propagate the app to TEST and PROD. The truth is, I've some applications that only exist in one environment and so I update straight in "production". Those apps are still backed up automatically every night, so worst case I can always take the version of the previous day. But just to be clear, this is not good practice ;)

So how do you show a region only when you are in development mode in Oracle APEX?

You go to the Conditions section of your region, list entry or any component in APEX really, and add a PL/SQL Expression: apex_application.g_edit_cookie_session_id is not null

Alternative you can use "Item / Column not null" and specify APP_BUILDER_SESSION:
*) updated blog post 11-FEB-2019 after comment of Christian (thanks Christian!)

It would be cool if there was a condition type "Development Mode", but maybe I'm the only one needing this...

Typically you would use Build Options (see Shared Components) to include or exclude certain functionality in your APEX app, but in the above two use cases, it won't really work.

Another enhancement would be that the Status of the Build option would include "Dev Only" next to Include and Exclude.

Monday, January 28, 2019

The best free database... Google is wrong!

When you search on Google for "the best free database", the below is what you get (search done 11-NOV-2018 and again on 12-JAN-2019 and 28-JAN-2019). To my surprise, there's no Oracle on the list? The reason is Google took the answer from this review. As I don't want people to see this screenshot, I put in red what is wrong with the answer, so in case Google shows images, and people don't read this blog post, they don't get the wrong answer ;)

The above is so wrong for me, the best free database in the world is Oracle Express Edition (XE). Oracle released XE18c on October 19th, 2018. This database is unbelievable. You basically get an Enterprise Edition version and almost all options are turned on! It's amazing, the only restrictions you have is on the amount of RAM (2GB) and disk space (12GB). You even have the pluggable database architecture and can create 3 PDBs (pluggable databases).
In my opinion, there is no other free database in the world that will beat this. Below I will go in more detail why I like this Oracle XE18c so much, but first, let me show you Google actually knows the right answer too.

Google says "People also ask": "What are the top 5 databases available on the market?" and here Oracle is number one. The other question is "What is the best database software for small businesses?" Oracle number one again. If the question would be "What is the best database software for enterprise businesses?" Oracle is number one too, this is common knowledge.

Google's algorithm to answer the first question, just got it wrong. How can Oracle be number one and be the best, but not in the free section, whereas their best database is available for free? :)

Google allows you to comment on their search results, which I did:

Why do I like Oracle XE 18c so much?

When we talk about Oracle XE, we really talk about the full Oracle database in general. Yes, there are a couple of limitations, but nevertheless, you get the full feature set of the Oracle database! All the good stuff why Oracle shines is there: to have the best performance you can use partitioning and online index rebuilds (and in the future automatic index creation!), to increase high availability you have the full flashback technology to your disposal, for security Oracle has VPD, Real Application Security, Database Vault... Oracle plans to release a new version of XE every year too, so you have always the latest and greatest.

I should write another blog post why I like the Oracle database so much, but I encourage you to just try it and decide yourself.

Getting started with Oracle XE

If you just want to try Oracle XE, most likely the easiest way without hitting your system, is to go with the Oracle docker container. Here're the steps to get Oracle XE running in an Oracle docker container.

If you don't have Docker and Git yet, download and install first.

Open a Terminal or Command Prompt and run following commands:

git clone https://github.com/oracle/docker-images.git

cd docker-images/OracleDatabase/SingleInstance/dockerfiles

Download Oracle XE
Copy the oracle-database-xe-18c-1.0-1.x86_64.rpm in the docker-images/OracleDatabase/SingleInstance/dockerfiles/18.4.0 directory

Move on by running following command:

 ./buildDockerImage.sh -v 18.4.0 -x -i

docker images

docker run --name OracleXE -p 1521:1521 -p 8080:8080 -e ORACLE_SID=XE -e ORACLE_PWD=oracle -v /Users/dgielis/git/docker-images/OracleDatabase/SingleInstance/dockerfiles:/opt/oracle/oradata oracle/database:18.4.0-xe


And voila, you are done! (more info on the Oracle Docker images)

To get a view in your database you can use Oracle SQL Developer. Here's how you connect to it:

The next thing would be to install Oracle APEX, so you don't only have the best database in the world, but also the best low code platform in the world, which works absolutely awesome with the Oracle database.

Friday, January 25, 2019

Trying to decide which APEX events to attend? Here's where I'll be.

I love going to conferences, to catch up with friends, be part of the vibrant Oracle APEX community, gain and share knowledge and of course demo APEX Office Print (AOP).

Conferences are a great way to get some new ideas and insights. You learn not only from the content but even more from the different cultures and background of people and the way they approach things.

My schedule till June looks like this:

ITOUG Tech Day Milano, Italy: 30-JAN-2019

This day is part of the ITOUG Tech Days. I've never presented in Italy, so I really look forward to this first time. I'll present on "Bringing your Oracle Database alive with APEX".

APEX Meetup Düsseldorf, Germany: 5-FEB-2019

As we did some major releases with AOP 18.1 and 19.1 and we have many customers in Germany, Niels asked to present on Reporting in APEX. As it's a meetup, we have more room to make it really interactive, so if you are in the region of Düsseldorf and Ratingen, stop by and ask me any question. I'll show some cool tricks of AOP and will give some insight what's coming later in the year.

APEX World, the Netherlands: 25/26-MAR-2019

I don't think I've ever missed a version of APEX World. It became the biggest APEX only conference in the world, and it's basically in my backyard :) This year is special too, as it's the 10th year anniversary! My company, APEX R&D, has been a long time sponsor of the event. This is the only conference where we also have a booth, so you can stop by any time you want and ask us many questions :) At our booth, we show the latest and greatest dev build of APEX Office Print (AOP)!
I'll give my "Augmented Reality & Virtual Reality with APEX" presentation this year.

APEX Alpe Aldria, Croatia: 12-APR-2019

Last year this conference got its first edition and it was a great success. My friends Peter, Aljaz, and Dario really know how to make a great conference. Last year AOP sponsored and Sunil, our lead backend architect of AOP, was there to answer any questions. This year most of our team is going. I'll give a presentation "APEX Reporting Tips & Tricks", similar to the webinar I did for AUSOUG.

APEX Connect, Germany: 7/9-MAY-2019

The last couple of years I've presented at this conference. APEX is being used a lot in Germany, so it's great to see so many use cases of APEX. This year I was asked to do my "Augmented Reality & Virtual Reality with APEX" presentation. In our office we have 3 VR systems running (with HTC Vive) and are doing some research on cool use cases. I dream one day we can develop our APEX apps like Tom Cruise did in the movie Minority Report :)

ODTUG KScope, Seattle, US: 23/27-JUN-2019

Since my first attendance in 2006, this is my favorite conference. It's the go-to place to meet the APEX development team, and so many smart people you meet daily on the internet.
It's unsure yet what I'll present on this year, reviews are still ongoing, but for sure there are many good presentations there and the latest and greatest of the APEX Dev Team. If you can ever go to this conference, I would definitely recommend it!

If you are at one of the above events and you want to chat, don't hesitate to stop me. I would love to meet you. I'm thankful you read my blog and I would love to hear more about you.