Monday, February 18, 2013

Apex and APEX.SUCCESS_MSG.CHECKSUM_CONTENT_ERROR

After I successfully installed Application Express 4.2.1.00.08 (latest version in this moment), I decided to test Apex Listener. So I installed (latest version in this moment) Apex Listener 2.0.0 354.17.05, which seems to be stable enough.

First tried standalone version but very soon found out that this is not a good way to run this product even in demo environment.

So I decided to install Tomcat 7.0 as free solution and implement Apex Listener as classic application. Regardless this combination is officially not supported by Oracle, after some small configuration problems (mainly with SQL Developer as configuration platform), my Apex was running fast as hell ... and I was very glad to know that this combination really rocks. And the best of all free!

This looked very, very promising. I was courios what other problems I might run into ... but for some time there were none.

The problem

But while I was developing one app, I run in the problem which I firstly thought it is pure Apex problem. Notification message on protected page was making fatal Apex error. This is the error content from WEB developed session:
Error: Success message checksum content error
Contact your application administrator.
 
Technical Info (only visible for developers)
is_internal_error: true
apex_error_code: APEX.SUCCESS_MSG.CHECKSUM_CONTENT_ERROR
error_backtrace:
----- PL/SQL Call Stack -----
  object      line  object
  handle    number  name
000007FF7D92A9B0       548  package body APEX_040200.WWV_FLOW_ERROR
000007FF7D92A9B0       599  package body APEX_040200.WWV_FLOW_ERROR
000007FF7D92A9B0       903  package body APEX_040200.WWV_FLOW_ERROR
000007FF7C7F5C30       794  package body APEX_040200.WWV_FLOW_SECURITY
000007FF7DA033F0      5778  package body APEX_040200.WWV_FLOW
000007FF7DA138B0       249  procedure APEX_040200.F
000007FF7C49D528         2  anonymous block
Very soon I discovered that this error was triggering only when in it's content was Croatian (or any other) national characters (like €, Ł etc). Here are the step to reproduce the problem.
  1. Create a authentication page with "Page Access Protection" defined as "Arguments must have checksum"
  2. Create a page process (On Submit After Computation and Validation).
  3. In that process use Apex application variable (G_APP_MESSAGE, in mine case) as a holder for success message. Code is exactly like
    :G_APP_MESSAGE := 'Lozinka uspjesno promijenjena!';
    
  4. After submitting page, everything went fine ... and success message is shown as expected.
If You change step 3) so G_APP_MESSAGE is defined as :
:G_APP_MESSAGE := 'Lozinka uspješno promijenjena!'; 
Just to accent that I changed uspjesno->uspješno (s->š), and submit a page again, I get an error described previously.

I tried change G_APP_MESSAGE in a way:
:G_APP_MESSAGE := utl_url.escape('Lozinka uspješno promijenjena!'); 
I get success message as:
Lozinka%20uspje%BFno%20promijenjena!
but without error.
:-)
When I return back mine š sign to s (now message again has only USA characters), remove "utl_url.escape", page is submitted normally and success message is ok (but again without national signs).

The solution

I tried to reproduce the same problem in Apex cloud but this was not the case. So easy conclusion was that something is wrong in mine configuration and the only thing that differed was-Tomcat. So after some googleing I found the cause. Problem is with Tomcat URI Encoding. Default encoding is ISO-8859-1, but from APEX, comes URL with message encoded in UTF-8. Solution Solution was very easy to implement. Follow next steps:
  1. Stop Tomcat service
  2. Find file server.xml and make a backup.
  3. Open servr.xml file (with some proper editor which can handle UTF-8 encoded files), and find content:
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   maxHttpHeaderSize="32767"
                   redirectPort="8443" />;
    
    In mine case it wasline 70.
  4. Add URIEncoding="UTF-8" before closing tag. Changed value looks:
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   maxHttpHeaderSize="32767"
                   redirectPort="8443" URIEncoding="UTF-8" />;
    
  5. Steps 5 and 6 are for Older Apex Listener configuration, but on Apex 2.0 it was not needed at all.
  6. Create filters directory (error is not important if exists)
    mkdir $CATALINA_HOME/webapps/apex/WEB-INF/classes/filters
    
  7. Insert after the last </servlet-mapping> tag:
    vi $CATALINA_HOME/webapps/apex/WEB-INF/web.xml 
    
    
      Set Character Encoding
      filters.SetCharacterEncodingFilter
      
       encoding
       UTF8
      
     
    
      Set Character Encoding
      /*
    
    
  8. Restart Tomcat.

The End

Even this is not a rocket science, it may shorten finding the solution to someone else.

Hope this helps someone.

Cheers!