Monthly Archives: April 2010

Special and Pair validation types

I am working on an article about flexfields and flexfield validation.

Even though the article is not yet finished, I thought the part about ‘SPECIAL’ and ‘PAIR’ validation types might be interesting enough. Many people seem to think they can only use the seeded validation sets. However, you can also create your own validation sets. And their options are very powerful. So I wanted to publish this part of the article as a prelude to the full story.


Special Validation

Special validation is used to provide flexfield functionality for a single value. What that means is that you can have for example a concurrent program parameter that will be filled with a Key flexfield value, or a range of flexfield values.

Let’s go back to the Key Flexfield. We know that they are combinations of different segment values that are stored in a separate combination table.

When you want to submit a key-flexfield combination as a parameter to a concurrent program, you can code your own validation for the separate values. But you’ll be missing the nice functionality that gives you pop-ups, a validation over the resulting combination and if needed the ID-value for the flexfield combination.

That is possible with a ‘Special’ validation type.

The special validation uses a number of user exits to enter, validate and query keyflex segments. With special validation, you will be able to enter one or more segment values for a key flexfield. To enter these segment values, 3 user exits can be used. They are: ‘POPID’, ‘VALID’ and ‘LOADID’.

POPID is used to enable the user to enter the flexfield segment value. It is called when the users cursor enters the segment value field. With this user exit, you decide which segment values should be shown, and how they should be shown.

 VALID is called when the user exits the segment value, or confirms the chosen flexfield combination. It validates the entered value against the values existing in the key flexfield table.

LOADID is optional, and it can be used to choose which information will be returned as flexfield value. This can be the concatenated segments, or the id-value for the flexfield combination or segment values.

These 3 user exits can be assigned to 3 ‘events’. There are more events possible, but they are either not yet in use, or their use is not yet supported. So we will only use ‘Validate’, ‘Edit’ and ‘Load’.

Sounds complicated, so far? Don’t worry; this is not an easy validation. But we’ll build some examples to give you an idea. First we start with building a very easy special validation. This will be built on our Code Combination key flexfield. We’ll be using a concurrent program ‘Test Flex Validation’ program to see our different options.

This program is based on the following procedure:


( errbuf   out varchar2

, retcode  out varchar2

, p_flex   in  varchar2

, p_flex2  in  varchar2 := ‘XXX’

, p_flex3  in  varchar2 := ‘XXX’

, p_flex4  in  varchar2 := ‘XXX’

, p_flex5  in  varchar2 := ‘XXX’

) IS









This will only write the parameter value to the output of the request. To use flexfields as parameters for concurrent programs, we need to define a value set based on them.

We will start with the barest setup to enter a key-flexfield combination. For this article, we use the accounting flexfield, with code ‘GL#’  and id-num ‘101’.

In this case, we have the following definition:


So what does this mean?

The first box is for the edit event. This will be triggered when the user enters the cursor into the field with this value set.

FND POPID         This is the user exit to pop up a flexfield screen, and let the user enter the flexfield values.

CODE="GL#"     This is the flexfield code for the key flexfield that we will be using.

APPL_SHORT_NAME="SQLGL" The short name for the application the flexfield belongs too. Together with ‘Code’, this will identify the flexfield itself.

NUM="101"       The id-number for the flexfield structure. If you have only a single structure flexfield, it is optional. For flexfields enabled for multiple structures, you need to enter the id-number.

VALIDATE="PARTIAL"   Validate can be ‘None’, ‘Partial’ or ‘Full’. None means the combination is not validated. Partial means that the separate segments are validated, there is no validation if the combination exists. Full means that segments and combination will be checked, and if a new value is entered, this will be inserted into the key flexfield table.

SEG=":!VALUE"                This is the forms field that will be used to store the value of the segments.

The second box is for the ‘Validation’ event. This code will be called when the user navigates out of the field, or submits the entire combination.

Now when we set this value set as a parameter for our concurrent program, we can see how the validation works:


Now when we run the program, we get this pop-up:


We have all the functionality of the key flexfield. We can use the ‘Combinations’ button to search for existing combinations, and all separate segments will be validated, as will be the final combination.

When we submit a value to our program, it will show the concatenated segments as the value of our parameter:


Now let’s see some more features of this validation. For example, we’d like to have the value of the combination id. (CODE_COMBINATION_ID in our case, since we use the Accounting Flexfield).

To get that, we need to add the LOADID user exit:


The ‘Load’ event will get the combination-id from the flexfield table. This is only possible for the ‘VALIDATE=”FULL”, since it will validate the whole combination. Also we need to set the ID=”:!ID”. This will populate the :!ID column with the ID value of the combination.

Finally, I added the ‘DINSERT=”NO” ‘, because we don’t want to allow insertion of new code combinations from this value set. (And Validation=”FULL” by default inserts new combinations into the flexfield column).

Now when we run the concurrent request, we see that the parameter value is the code_combination_id instead of the concatenated segments:

With these user exits it is also possible to select just a number of segments, instead of the whole combination. For this we remove the ‘Load’ / ‘LOADID’ part again.

Then we add a ‘DISPLAY=”x” ‘ to the ‘Edit’ and ‘Validate’ user exits. The “display” parameter is defaulting to ‘ALL’. But you can also specify separate segments by their sequence number or names. In our case, we display the first 2 segments:


Now when we run the concurrent program, we get a pop-up for only the first 2 values:


A very nice feature (at least as far as I’m concerned) is the use of a where clause on the combination values. Consider the following ‘Enter’ code:






TITLE="Special Validation Key"




WHERE="segment2 not like '1%' "


The “WHERE” clause prevents us from choosing combinations that have a segment2 starting with ‘1’. When we run our concurrent program with this, and choose the combinations:



There is no Dpt starting with 1.


When we add the “WHERE”-clause to the validation event too, it will prevent us from entering the values manually:




The last feature that we’ll look into is the use of a pl/sql validation through the special validation routines. By using the user-exit PLSQL, we can call an anonymous PL/SQL block in our ‘Validation’ event. I created a value set with the following function for the ‘Validation’ event:


FND PLSQL " declare

  v_value varchar2( 10 ) := :!value ;

  v_sum number;

  v_valid boolean;



   for i in 1..length(v_value) loop

    v_sum :=v_sum+(length(v_value)+1-i)*substr(v_value,i,1);

  end loop;

  if mod(v_sum,11)=0 then

     v_valid := TRUE;



  end if;

  if not v_valid then

      fnd_message.set_name('FND','FND_GENERIC_MESSAGE' );

      fnd_message.set_token('MESSAGE','This is not a valid bank account');


  end if;

END; "



This PL/SQL procedure validates a (Dutch) bank account number. If it does need pass the test, a message will be displayed. This gives you almost unlimited possibilities for validating entered data.

As you can see, it is only a ‘Validate’ event. Because we don’t need any special functionality for entering the data. We can limit the entry to numbers only on the ‘Validation Set’ main page.


Now when we use this value set for our concurrent program, we can only enter valid dutch bank accounts:





The list of parameters for the user exits is longer than this. So we won’t be going through all the possibilities. You can check the Developers Guide and the Flexfield guide for a complete listing of options. (Did you notice the flexfield title that I sneaked into the pop-up? Try and find the option for that!)

Please try the different options for yourself, and realize the possibilities of the special validation.


Pair Validation

Meanwhile, we’ll continue to the ‘Pair’ validation. The pair validation is very much like the ‘special’ validation. It uses the same kind of user exits, but this time, a range of segment values or combinations is selected.

Let’s first create a range of the account segment. Instead of using POPID and VALID, we use POPIDR and VALIDR. The R-version of the user-exits automatically create a range.

Of course we need 2 parameters to set the range. However, we need only one validation set.

I created the validation set ‘XXX_PAIR_VAL’. I entered only the edit and validate events:


The next step is to set the parameters for both the low and high value. Both parameters have the validation set ‘XXX_PAIR_VAL’.


Now when we run the program, we can enter a range. This includes validation that the high value is indeed higher or equal to the low value.


Of course the concurrent program will receive the values for 2 parameters.


When we use the full validation we can enter a range of the whole account combination. Note that we cannot use the FULL validation for pair-validation. Because that would mean the use of the combination-id from the flexfield table and based on the combination-id’s you cannot build a range.


So we can only use PARTIAL and NONE for the validation. For that same reason, I have not yet had a reason to use a LOAD event for PAIR validation. It is however allowed to use one.


I created a PAIR validation for the whole accounting range as follows:



When used in the concurrent program, it will indeed allow us to enter a range of all segments:



That completes the chapter on PAIR validation too.


Oracle eBS 11i Infrastructure

Oracle eBS 11i Infrastructure


In this article we will describe the infrastructure of Oracle eBusiness Suite (eBS). In its simplest form, eBS is a 3-tier application with a client tier, Application-tier and DB-tier.


Let’s start with the DB-Tier. Surprisingly, the database tier has only very little eBS specific features.

Of course we need a database (instance) and therefore an ORACLE_HOME. But the database can either be a single-instance or a RAC-installation and all Oracle RDBMS features are transparently available for eBS.

The management of the RDBMS Installation is also independent of eBS.


DB-Tier filesystem

Let’s start with the filesystem on the DB-Tier. Of course there is an Oracle_home installation needed, for the RDBMS-Instance. This will be installed during installation of eBS. But also a fresh installed ORACLE_HOME can be used, with an eBS database.

In the ORACLE_HOME, an extra directory is added. The Appsutil directory. This directory contains the software and data needed for running Autoconfig and Rapidclone.

All other directories are at the discretion of the eBS DBA.

Oracle Instance

When we look at the instance to run eBS, we find a number of mandatory parameters for eBS. These are found in Metalink notes 216205.1 and 396009.1 (At the time of writing. Please verify these notes for yourself).

These parameters are recommended or mandatory based on testing by Oracle Corp. They will automatically be set by the eBS installer. But you should take note of them when you use a fresh installed ORACLE_HOME.

Then we finally come to the contents of the database.

The eBS Database

Let’s start with the schemas in the database. Oracle eBS creates a separate schema for every module. The schema is named as the short_name of the module, for example AP (Oracle Payables / Accounts Payable), AR (Oracle Receivables / Oracle Receivables).

There is a separate schema for the Application owner APPS.

The Application schemas contain the tables, indexes and sequences for the different applications. All objects in these schemas (except indexes, of course) have a synonym in the APPS Schema. In the APPS Schema we also find all PL/SQL objects, views and Materialized Views.

A major part of eBS is written in PL/SQL. All PL/SQL objects are also installed in the APPS Schema.

User sessions within eBS will usually run in the APPS Schema as well.

That brings us to an extra schema in the database: APPLSYSPUB. This schema has access to some of the eBS tables and packages, that allow it to validate eBS logins and start an APPS-session based on that login information. We will see the details of this later on.

Before release 11.5.2 every schema had its own tablespace. However, the number of modules for eBS (and with that the number of schemas) is ever increasing. So managing the database became more and more complex. In 11.5.2 Oracle introduced the Oracle Applications Tablespace Model (OATM). Within this model, the tablespaces in eBS are based on functionality, rather than schemas.

In this model, we see the following tablespaces:

APPS_TS_TX_DATA – Containing all transaction tables, Materialized Views and IOT’s

APPS_TS_TX_IDX – Containing all indexes for transaction tables

APPS_TS_SEED – Containing the tables and indexes with seeded data (as opposed to transaction data).

APPS_TS_INTERFACE – For Open Interface tables

APPS_TS_SUMMARY – Contains summary tables for several modules (AR, PA, BIM, etc)

APPS_TS_NOLOGGING – For tables and objects that are created with the NOLOGGING option

APPS_TS_ARCHIVE – Containing archive and history tables (and indexes)

APPS_TS_QUEUES – Containing the AQ (Advanced Queuing) objects

APPS_TS_MEDIA – Containing tables with LOB’s. For media objects or documents.

The Undo and Temp tablespaces are not part of the tablespace model.


Application Tier

Now it’s time to look at the Application Tier. In fact the Application Tier consists of 3 different services: Web service, Forms service and Concurrent Processing. In 11i installations, there is also an Administration service.

The Application Tier significantly changed from R11i to R12. We’ll discuss the 11i Apps Tier shortly, and then discuss the R12 tier in more detail.

The 11i infrastructure

Both the R11 and R12 infrastructure consist of a Web-service, a Forms Service and a Concurrent Processing part.

We will be discussing the different services here. The following picture shows all components and their communications. You might want to keep it for reference during this article.



R11i Web Service

For 11i, the web tier is built on Oracle iAS 9i. The iAS installation provides webservices (Apache HTTP/HTTPS), a Java Runtime Engine (JSERV) and a PL/SQL engine (modplsql).

The web service also acts a gateway for the Concurrent Request log and output files. And it is the first point of access when starting a forms session. (When using a socket forms connection, when using a forms servlet the web tier will host the forms process).

A detail from the picture above shows the iAS structure.


The core of iAS is the web server. This is the front-end for the client. Requests can also be forwarded to and from the forms server and the concurrent processing. We’ll see that in the next paragraphs.

Within the iAS Jserv and modplsql are plugins. They are the only components that communicate with the database. When they are called, they execute java (Jserv) or PL/SQL (modplsql) and return an html page. This page is then sent to the client through the HTTP service.

The Jserv delivers a Java Runtime Environment. In the Jserv, java servlets can be run. Also the JSP-files are executed in the Jserv. A JSP-file (Java Server Page) is a page with java code that returns an html-page (similar to the way scripting languages like PhP work). The java part is executed in Jserv, which returns the html to the webserver. The webserver redirects the html to the client.


Let’s take a closer look at the components and their executions:



The webserver is based on the regular Apache 2 webserver. The configuration file is also equal to the Apache config file. The configuration is set in httpd.conf (or httpds.conf for SSL).

Instead of starting the webserver through $APACHE_HOME/bin/httpdctl, we start through $APACHE_HOME/apachectl. The default port number used for eBS 11i is 8000. This is part of port-pool 0. For different port-pools, the port number is increased. So for port-pool 1 the webserver runs on port 8001.

The root directory for the webserver is set to $OA_HTML, which is by default $COMMON_TOP/html. This directory contains all *.html files for eBS.

A number of virtual directories are set up within eBS.



As mentioned before, java code is executed by Jserv. Jserv is a java servlet engine. That means that it can run both servlets and jsp-files.

These servlets are mostly located in the $JAVA_TOP. The *.jsp files are located in the $OA_HTML directory.

One of the options of Jserv is to create a database connection to the rdbms database. This is done by a JDBC Thin Client connection.

Before we look at the configuration for Jserv, examine the following picture.

Within Jserv, we can define different java environments, called zones. These zones are configured with different servlets or java archives (jar-files). Each zone is configured with its own configuration file. Within the zone the startup parameters (initargs) for the servlet are defined.

On the other side of the picture, you see a group. All java processes within Jserv are grouped together. You must define at least one group. The default group is ‘OACoreGroup’. Within each group, we create one or more processes that will be mapped to our zones.

This mapping is done by mounting the zones and the groups to different logical directories. In the picture, a mountpoint is created: /oa_servlets/. It refers to the group ‘OACoreGroup’, which holds 3 java processes. And it is mapped to zone ‘root’, which includes the servlet ‘dummy’ with a set of startup parameters.

When iAS receives a call to the virtual directory /oa_servlets/ it will be recognized as a Jserv mount point and the request will be forwarded to Jserv. In this example Jserv has 3 java processes in the group for this mount point. And they will be able to run all the servlets in the zone.

Sounds complicated? Take a look at the following configurations:


ApJServGroup OACoreGroup 3 1 /etc/oracle/iAS/Jserv/etc/

ApJServGroupMount /oa_servlets balance://OACoreGroup/root




root<host>.properties = /etc/oracle/iAS/Jserv/etc/

servlet.Dummy.initArgs=message=I'm a dummy servlet


Within jserv.conf we define a group called OACoreGroup. This group is running 3 Java processes. And the definition of the group is in the file. The 1 indicates the weight for load-balancing with multiple groups.

Then we mount the zone ‘root’ to the group ‘OACoreGroup’. This mount point is linked to the virtual directory /oa_servlets/.

The virtual directory is used for redirection to the JServ. When a request is made to the virtual directory Jserv will be called. The part of the URL after the virtual directory is the path to the servlet. This path will be searched for in the $CLASSPATH.

When the java servlets need to connect to the database, they can build a connection using JDBC. The access information is stored in a *.dbc file in $FND_TOP/secure. The dbc-file is referred to in the parameters for the zone.



Let’s take a look at the modplsql module. This module is designed to run pl/sql procedures within the database. The connection is based on the file. This file contains the DAD (Database Access Descriptor), including the access data to the eBS database.

The module is also called through a virtual directory. For example http://<host>:<port>/pls/TESTDB/ dummy. /pls/ is the virtual directory that refers to modplsql. TESTDB is the name of the DAD and dummy is the name of a pl/sql procedure accessible for the db-user from the DAD.


That concludes the 9i iAS module for now.



Let’s take a look at the forms server.

Oracle forms can be set up in two ways, socket connection and servlet. The default is socket connection. With a socket connection, a separate forms server and dedicated forms processes are used. For the servlet connection, a java servlet is called within the iAS.

The formsserver itself is installed in the 8.0.9 ORACLE_HOME. Forms has a forms server, and one or more client processes. The forms server is started with f60svr. It will spawn a f60webmx process for every client session connecting.

On the server side, forms are run in the forms client processes. On the client side, they are run in a java applet. When the client clicks a forms based function in the Personal Home Page, it calls an URL that refers to the forms client executable in the 8.0.6 ORACLE_HOME.

This URL is taken from the profile option ‘ICX: Forms Launcher’, and the default value is like ‘http://<server>:<port>/dev60cgi/f60cgi’. The parameters referring to the function being clicked are added to this URL as parameters. (i.e. the name of the form to be started)

When this URL is called, the webserver will execute the executable f60cgi. This executable returns a HTML page to the client. This page is called the ‘Base HTML’ for this forms server. (by default this is $OA_HTML/US/appsbase.htm)

This HTML page calls the J-initiator plugin (or the native JVM when configured). It also includes the parameters to connect to the forms server and the name of the form to start.

The J-initiator will start an applet on the client, which connects to the forms listener process. The forms listener process then assigns a dedicated forms client process.

At this point the whole chain looks like this:


The configuration for the forms server is in the appsweb.cfg file in ($OA_HTML/bin). This file contains the basic coloring scheme for the forms server, the forms settings and the referral information to the J-Initiator plugin. The plugin on the client side is called through its class-id, which is also set in the appsweb.cfg.


Concurrent Managers

The last part of the application tier is the concurrent processing part. The concurrent managers are used to execute background and batch processes.

Different executables including host-command files, pl/sql procedures, Oracle Reports, SQL*Loader control files and Binary executables can be defined to be run as concurrent programs. Parameters are also optionally defined with the concurrent programs.

The executable files are defined separate from the concurrent programs. So an executable can be run as different programs with different parameters.

The programs are executed through ‘Requests’. A request is started as a concurrent program and the values of its parameters. It can be scheduled to start at a specific time, or in a specific schedule. The output of the program can be sent to a printer. It is also available through the application.

This picture shows the relation between programs, requests and managers.


The managers

We’ll take a closer look at the concurrent programs later. Let’s first look at the concurrent managers. There are concurrent managers and transaction managers. Also a number of control managers are defined.

We’ll start with the ‘Internal Manager’. This is the first manager to be started. Its purpose is to control the stopping and (re-)starting of the other managers. When Generic Service Management is enabled (default as of 11.5.7), it delegates to the ‘Service Managers’. On every node where concurrent processing is enabled, a ‘Service Manager’ is started. However, only one Internal Manager is running at any time.

The other concurrent managers are defined with a work shift that controls how many processes a concurrent manager should have at certain times. The work shifts consist of a time-range and a number of processes. The Service Managers (or Internal Manager) will start and stop processes according to these work shifts.

Another part of the setup of concurrent managers is their specialization rules. The specialization rules indicate which programs are valid for a concurrent manager, or are excluded for that manager. They work on an include/exclude principle. When programs are included for that manager, the manager can only run those programs. When programs are excluded, the manager can run any program except the excluded ones.

When a request (to run a program) is submitted from eBS, it will be placed in FND_CONCURRENT_REQUESTS with a status_code ‘I’ (The eBS forms have fewer statuses than the codes in the table). The manager processes will query this table for requests that they are eligible to run.

Once a manager process finds a request with status_code ‘I’, which it is eligible to run then it will put the request on its own queue. It will then run the executable with the defined parameters. The logfile and outputfile are written to the filesystem in $APPLCSF/$APPLLOG resp. $APPLCSF/$APPLOUT.

There are some special cases that need to be discussed. The first is the incompatibility. Concurrent Programs can be made incompatible with each other. That means that they cannot run at the same time. Once a program is started that is defined as incompatible with another, it will be automatically put on the queue for the ‘Conflict Resolution Manager’. This special manager will check if any incompatible program is running or ‘Pending’ with code ‘I’. If so, it will hold the request on its own queue. If no incompatible program is running or ‘Pending’, then it will set the status of the request to ‘Pending’.

Another special case are the ‘Transaction Managers’. They are started and stopped the same way as the other concurrent managers. But they do not use the request queue. Transaction managers are called online from the eBS forms. And they execute a limited number of programs. These programs defined within their executables. They are called through the ‘FND_TRANSACTION.SYNCHRONOUS’ procedure, which uses the ‘DBMS_PIPE’ package.


The programs

It’s time to look at the concurrent programs. As mentioned before, a concurrent program is an instantiation of an executable. The executable is defined with a short name, an application (module), a filename and a method.

The short name will uniquely identify the executable. The other data is needed to determine what should be run for this executable. If the executable is an OS-based program, the application will be used to derive the directory on the file system where the executable is found.

When the executable is defined as PL/SQL, the filename will contain the procedure that needs to be run.

The concurrent program is defined as the executable with an (optional) set of parameters. It also has some properties for the printing of the output (print-style, pre-defined printer, size of the output).

Depending on the type of executable that needs to be run, the parameters will be sent to the executable ordered or named. For PL/SQL and host files, the parameters are ordered. And the order in which they are defined in the form defines how they will be sent to the executable. For reports the parameters are named, which means they are sent as <parameter>=<value>, ….

After the request has finished, the request table ‘FND_CONCURRENT_REQUESTS’ will be updated with the status information and a reference to the log- and output file. During the execution of the request, a status_code and phase_code are updated. The exact values of these fields are described in one of the next articles. That will go deeper into concurrent processing.

The output

The log- and output file from the requests are written to the directories $APPLCSF/$APPLLOG and $APPLCSF/$APPLOUT. But they of course also need to be made available to the user. This is done through the ‘Applications Report Review Agent’.

There is quite a lot of setup that can be done for the whole process. But within the scope of this article, we’ll only look at the basic architecture.

From the eBS form the log and output file are available from 2 buttons. These buttons call the web server for ‘FNDWRR.exe’ (.exe on both Windows and Unix).

FNDWRR.exe is a cgi-executable that will call the ‘FNDFS listener’.

This is an 8.0.6 TNS-listener in the eBS ORACLE_HOME on the eBS application tier. One of the less known features of the TNS-listeners is that they can do more than create database connections.

In the listener.ora, you can define a program to be called when a connection is made on a certain tns-entry. That feature is used for the FNDFS listener. When it is called, it will redirect traffic to the ‘FNDFS’ (FND File System) executable. This executable will read the requested file from the file-system and send it to FNDWRR.exe.

Again, we have a schema to show the whole flow:


This complex retrieval is of course needed because the concurrent processing tier can be separate from the forms and web-tiers.


eBS Troubleshooting

Oracle eBS troubleshooting


On this webpage, I’ll make a FAQ on common eBS problems and troubleshooting. Probably the format will change over time. But I’ll just start. I use basic flow diagrams, to give an overview of the process. Under the diagrams is an explanation of all the steps.

Ø My concurrent manager does not start


1)      Check if the Internal Manager is running. On Unix, you can run: ps –ef | grep ‘FNDLIBR FND CPMGR’. If this returns a process, check the start time for the process to make sure it is the correct process.

2)      If a process is returned, and it started at the time you started the managers, the ICM is running.

3)      The ICM is not running. First check the adcmctl.txt file. It is found in the process_log directory. (Check your autoconfig xml file or the script). It will show the logs for the start-up scripts of the ICM.

4)      The ICM is running, but can’t start the other managers. Most common cause is  the APPS Listener is down. Check for it running with: ps –ef  | grep ‘tnslsnr APPS_<SID>’

5)      If no process is returned, start the apps listener with Wait a minute afterwards, for the ICM to retry starting the managers.

6)      The ICM is running, or was started successfully before it died. Check the logfile from the ICM in $APPLCSF/$APPLLOG. By default the file is named <SID>_<proc>.mgr, where proc is the process_id from adcmctl.txt.


Ø Notifications are not being sent by the notification mailer


1)      Look for the notification in ‘wf_notifications’. Check the status, mail_status, recipient_role and notification_id.

2)      If Mail_status = ‘SENT’, the message has been mailed already. If status<>’OPEN’ (Note the difference between status and mail_status), the notification is not eligible to be mailed anymore.

3)      The Notification Mailer has already sent this message. Maybe it was sent to the TEST_ADDRESS  from the Notification Mailer.

4)      Check the mail_preference for the recipient_role from wf_roles.

5)      If the preference is ‘QUERY’, ‘SUMHTML’, ‘SUMMARY’ or ‘DISABLED’ then the recipient will not receive notifications by mail.

6)      Change the preference in the Users preferences. Or test with a different user.

7)  The Notification Mailer reads notifications to send from the queue WF_NOTIFICATION_OUT. Select from the queue-view:

select notification_id,msg_state,msg_id,role,corrid,enq_time,deq_time

from  (select msg_id, o.enq_time, o.deq_time, msg_state

              ,(select str_value

                from   table (

                where  name = 'NOTIFICATION_ID') notification_id

              , (select str_value

                 from   table (

                 where  name = 'ROLE') role

              , (select str_value

                 from   table (

                 where  name = 'Q_CORRELATION_ID') corrid

       from$wf_notification_out o)         

where notification_id=<notification_id>

and rownum=1;

8)      If you received a result on the query, the notification is in the queue.

9)      The status of the notification in the queue should be ‘READY’. If it is ‘PROCESSED’, or ‘ERROR’, the notification is already dequeued or errored. Otherwise check the status of the queue with:

select name,enqueue_enabled,dequeue_enabled

from dba_queues


10)   The status of the message should be ‘READY’. The ‘ENQUEUE_ENABLED’ and ‘DEQUEUE_ENABLED’ columns should be ‘YES’.

11)   Reprocess the message with the conc. Request. Or stop/start the queue with dbms_aqadm.

12)   Check the Notification Mailer logfile. The notification is ready for the mailer, but it is unable to pick it up. Check if the mailer shut down due to too many errors.

13)   The message is not in ‘WF_NOTIFICATION_OUT’. It can still be queued on the ‘WF_DEFERRED’ queue. Check this queue with:

select v.msg_id,v.msg_state,v.enq_time,v.deq_time,v.corr_id

from$wf_deferred v

,      table(v.user_data.parameter_list) t

where v.corr_id like ''


and value = <Notification_id>;

14)   If the query returned results and the msg_state is ‘READY’, the notification is still being processed. Skip to 16

15)   Unfortunately, your notification seems to have gone missing. Consult Oracle Support. Please inform us of the solution in this case, so we can extend the FAQ.

16)   The notification is still in the deferred queue, waiting to be picked up by the ‘Workflow Deferred Notification Agent Listener’. Check the status of this listener. And if needed, check its logfile.

17)   If the Deferred Notification Agent Listener is not running, or erroring

18)   (re)start it.

19)   Check if the Business Event ‘’ is enabled and has a subscription to procedure ‘Wf_Notification_Util.Denormalize_RF’.

20)   If either the Business event is disabled, or the subscription non-existent or disabled, go to 21.

21)   Make sure that the Business event is enabled and the subscription is valid and enabled. You will still have to reprocess the notification with the concurrent program to resubmit notifications.

22)   Unfortunately, we can’t locate the issue yet. If you manage to solve the issue please inform us, so we can update this FAQ.