You are on page 1of 24

Enhancing Oracle Applications

Concurrent Processing
An Oracle White Paper
November 2001
Enhancing Oracle Applications
Concurrent Processing

CONTENTS

1. INTRODUCTION ...........................................................................................................3
2. THE STRUCTURE OF THE PAPER.........................................................................4
2.1 CONCURRENT PROCESSING – A QUICK RECAP ........................................5
3. MANAGING SINGLE CONCURRENT REQUESTS ..........................................6
EXAMPLE 1: REDIRECTING OUTPUT.................................................................7
EXAMPLE 2: RUNNING AN EXTERNAL PROGRAM.....................................8
EXAMPLE 3: INTEGRATING A FAX SERVER.................................................10
4. MANAGING MULTIPLE REQUESTS ...................................................................11
4.1 EXTRACTING VALUES (1): THE BASIC SQL SCRIPT .................................12
4.2 EXTRACTING VALUES (2): THE INTEGRATED APPROACH................13
EXAMPLE 1: WORKING WITH A SINGLE VALUE .......................................13
EXAMPLE 2: WORKING WITH A LIST OF VALUES .....................................14
EXAMPLE 3: WORKING WITH A MULTI-VALUE LIST...............................15
5. LIMITATIONS AND UTILITIES .............................................................................17
5.1 MANIPULATING OUTPUT RECORDS USING PERL..................................17
5.2 PROBLEMS WITH PERL ON WINDOWS NT..................................................18
5.3 SCHEDULING FILE TRANSFERS .......................................................................19
5.4 COMPRESSING & EMAILING DOCUMENTS................................................20
5.5 PDFs AND CONVERSION .....................................................................................21
AUTOMATING PDF PRINTING............................................................................22
AN EXAMPLE CONVERSION ROUTINE ..........................................................22
5.6 SECURITY CONCERNS ...........................................................................................23
6. CONCLUSION ...............................................................................................................23

Enhancing Oracle Applications Concurrent Processing -2-


1. INTRODUCTION

This paper introduces several techniques that can be used to enhance and automate
the Oracle Applications concurrent processing suite. It starts by presenting some
simple changes that control the concurrent program that they are associated with.
The paper continues by introducing more powerful techniques, which can be
adapted to work on a range of concurrent requests. These examples are more
complex but a lot of effort has gone into ensuring that they are simple enough to
ensure that anybody with a rudimentary knowledge of shell scripting and SQLPlus
should be able to understand them.

Several concurrent processing functions can be automated using standard Oracle


Applications functionality. For example, when used with Oracle Alert, you can easily
set up an alert that will page a system administrator if there is a problem with a
concurrent manager or one of the queues. This type of standard functionality can
greatly enhance your management capabilities and is already well documented. The
types of examples described in this paper differ in that they control the output
whereas Oracle Alert tends to be more event driven.

In addition to the many benefits of Oracle Alert, the types of automation that you
will be able to achieve by following the examples in this paper include:

• Moving sensitive report files to secure directories


• Redirecting concurrent output to specific directories (other than
$APPLCSF/$APPLOUT)
• Compressing reports and distributing them during off-peak periods over
Wide Area Network links (which may also be low quality links)
• Automatically faxing reports, orders or other documents
• Converting documents to Adobe’s Portable Document Format (PDF)
format ready for distribution
• Automatically emailing reports or documents
• Publishing information or complete reports to the web
• Automatically archiving selected request output before purging the
concurrent requests

As you can see, most of the functions in this list would normally require some form
of manual intervention; however, they can all be automated. In most of cases, the
necessary changes usually only take a few minutes. For example, you can modify the
printer command line to move sensitive files the instant that they complete.

The paper describes conversion routines that you can use to convert a report into a
variety of output formats without having to rerun a concurrent request multiple
times. This type of approach can be easily be extended to automatically zip specific
types of documents or convert them to PDF format, which could then be kept on-
line for differing lengths of time depending on their type. While zipping is simply a
matter of running a utility, conversion to PDF is more involved. There is a
proliferation of document conversion utilities in the public domain; when making
your selection, select those that have a command line interface as these will be easier
to automate.

The final point in the list can give you complete control over archiving and purging.
Although the paper does not propose a full solution, it does provide you will all the
necessary tools to create your own.

Enhancing Oracle Applications Concurrent Processing -3-


2. THE STRUCTURE OF THE PAPER

This paper is split into three parts. These first two sections describe the techniques
that you can use and include several examples that gradually build in flexibility.

Managing Single Requests: The first part of this paper shows how to control
concurrent output by modifying the printer command. The approach is very easy to
understand and can be implemented very quickly. The examples show a number of
methods that can be used to automatically move the concurrent output to a secure
or alternate directory. This approach is limited in that it only works on the
concurrent program being run whereas the programs in the later half of the paper
are more powerful and will process a range of concurrent requests. The examples
build to show you how you could setup an automatic fax facility.

Managing Multiple Requests: The second section starts on a completely different


tangent by introducing a technique that enables the output of a simple SQL script to
be assigned to a system variable. While this is a very powerful technique in its own
right, this paper shows you how it can be used to manipulate concurrent request
output within a shell script, even if the concurrent manager is not running. The first
example shows a number of ways to process a single request. The subsequent
examples show how a single script can be used to manage several requests.

The final section continues with a discussion of some of the limitations of using
these approaches. For example, dealing with multiple values from each concurrent
request can be problematic and the approach you need to take will differ depending
on whether you are working on UNIX or Windows NT/2000. Should you find that
you have more complex requirements that cannot be handled in a shell script, an
example Perl script provides yet another approach, which also overcomes some of
the system-specific problems.

Finally the paper concludes with a brief discussion of some other utilities such as
Wget and NcFtp that can be useful when transferring programs between machines. It
also describes you how to convert the concurrent output files between different
formats and how you can automatically email them

Please note that although all the examples have been extensively tested (as will
become apparent), you should always perform your own tests.

Enhancing Oracle Applications Concurrent Processing -4-


2.1 CONCURRENT PROCESSING – A QUICK RECAP

You do not need a comprehensive knowledge of concurrent processing to follow


the examples in this paper. To recap on the way that the concurrent manager works:
when a user submits a job request, details of the request are entered into the
FND_CONCURRENT_REQUESTS table, which acts as a master request queue.

When designing your own programs, you will be able to intuitively map most of the
columns referred to in this document. However, it may be useful to remember that
the table stores each of the first 25 program arguments separately, and as comma-
separated values in the ARGUMENT_TEXT column.

During normal operation, concurrent managers continuously read requests from this
master queue and run the appropriate operating system jobs, based on the request’s
schedule, priority, and any incompatibility rules. The output files are written to the
$APPLCSF/$APPLOUT directory.

Concurrent programs have a user (visible) name and an internal name. The user
name is stored in the USER_CONCURRENT_PROGRAM_NAME column in
FND_CONCURRENT_PROGRAMS_VL. When developing your scripts, you
could use the CONCURRENT_PROGRAM_NAME, which is not only shorter but
will also make your scripts independent of the NLS_LANG setting. For example,
the internal name of the “Active Users” report is FNDSCURS. One way to find this
is using the Concurrent Programs screen under the Application Developer or System
Administrator responsibilities.

Note: The table and column names may be subject to change between
versions.

Enhancing Oracle Applications Concurrent Processing -5-


3. MANAGING SINGLE CONCURRENT REQUESTS

This part of the paper shows how to the control concurrent output from the printer
program itself. In this section you will be making changes to a printer driver or
creating a new one, which is described in detail in the Printers chapter of the System
Administration manual. You will need to review that chapter if you do not
understand the association between printer types, print styles, and printer drivers.
Your first design decision is to decide whether you are going to modify an existing
redundant definition or create your own customized combination. The
recommended approach is to create your own with a name that identifies its
purpose.

You can navigate to the Printer Drivers screen as shown in Figure 1 by selecting the
System Administrator responsibility and then Install | Printer | Driver.

Figure 1: Printer Drivers screen

The main fields of concern are as follows:

• Command: The concurrent manager can issue an operating system print


command and its arguments as entered in the Arguments field. This is the
approach that you will be modifying.

• Program: The concurrent manager can call a custom print program and pass
arguments to the program. This provides yet another approach, which
overlaps the examples in this section of the paper. There is no real
difference as far as the examples in this paper are concerned.

• Subroutine: The concurrent manager can call a predefined Oracle


Applications subroutine, which will pass a print command and its associated
arguments to the printer via the operating system.

Enhancing Oracle Applications Concurrent Processing -6-


The arguments passed to the print (lp) command normally include the following:

• $PROFILES$.PRINTER the destination printer


• $PROFILES$.CONC_COPIES the number of copies requested
• $PROFILES$.TITLE the report title
• $PROFILES$.FILENAME. the operating system path and name of
the output file

Importantly, $PROFILES$.FILENAME includes the complete path to the file.


Although the specific SRW driver that you use is of little concern, you should be
aware that the SRW driver affects the generation of character mode Oracle Reports.
If an SRW driver cannot be found for either the requests' print style or printer
driver, then the character mode report may not run. (This is why you are required to
choose a print style for Oracle Reports concurrent requests, even if you are not
printing.)

EXAMPLE 1: REDIRECTING OUTPUT

This first example shows how a completed report can be immediately moved out of
the $APPLCSF directory. The destination could be a secure location for sensitive
reports or perhaps to directory that is automatically polled by an automatic ftp or fax
program.

Figure 1 shows a standard print (lp) command and its associated arguments as used
on UNIX. On closer inspection, you could run this from the command prompt if
you resolved the variables. This is actually what happens and so to move a file, you
simply need to replace the print (lp) instruction with a move (mv) instruction and
modify the list of the profile options. For example, the move command: mv
$PROFILES$.FILENAME /disk17/secure.is shown in Figure 2. As you can
appreciate, the move command will be run as soon as the job has been completed.
The same principles may be applied to Windows NT/2000 systems.

Figure 2: Automatically moving a file on completion

Enhancing Oracle Applications Concurrent Processing -7-


Note that you need to define a new printer driver with the Driver Method set to
Remember to stop and restart your Command. As mentioned before, the driver name does not matter, but you will need
concurrent managers after making to link it to a printer before being able to test it. When you run the program, you will
any changes to the printer driver. need to set the number of copies to 1 otherwise there will be no output.

To ensure that these printer driver examples work, you must have the following
settings:

• Standard Input must be unchecked


• Spool File must be checked
• The Initialization and Reset strings must be null

$PROFILES$.FILENAME includes the operating system path and name for the
output file. If any of the settings above are incorrect then
$PROFILES$.FILENAME will not contain the value that you are expecting.

EXAMPLE 2: RUNNING AN EXTERNAL PROGRAM

There are several ways within Applications to run a group of programs together.
Typically you would write your program and then create or add it to a report set. So
as not to confuse the two, this approach differs in that the program, which in this
case is a shell script, is run immediately after the concurrent job completes.

The “redirecting output” example used the operating system command mv to move
the output file. This is simply an executable which can be found in a location
described in the $PATH variable for account that “owns” the Applications
executables. This implies that you can run any program on the Arguments line
provided it exists within the UNIX PATH variable. For example, if you had a shell
script called copyfile.sh, you could run it as shown in Figure 3.

Figure 3: Running An External Program

Enhancing Oracle Applications Concurrent Processing -8-


Before looking at the program, let’s start by analyzing the command. When using the
Program or Command method, if the program or shell script resides in
$FND_TOP/bin then the whole path does not need to be entered as this is
included the $PATH variable. The program or shell script could exist anywhere in
the path and so specifying the absolute path to the file is considered by many to be
good practice as it avoids this type of situation.

There are two arguments, which are passed to the copyfile.sh shell script. The first is
the output filename including the path and the second is a destination directory.
Specifying the target directory here rather than in the script ensures that the shell
script remains independent and can be used to transfer files to multiple different
directories.

In the following example, although the copyfile.sh script is very simple, it has the
advantage over the first example as it can also keep a log of what has happened. This
shell script simply appends the program parameters to a log file before copying the
file to the “secure” directory.

#!/bin/ksh
FILENAME=`basename $1`
echo "The first parameter was $1" >> /disk17/secure/output.txt
echo "The second parameter was $2" >> /disk17/secure/output.txt
cp $1 $2/$FILENAME

If you wanted to keep individual logs for each concurrent output file, then you
would simply need to change the following two lines :

echo "The first parameter was $1" > /disk17/secure/$filename.log


echo "The second parameter was $2" >> /disk17/secure/$filename.log

Note that the first line creates the file, and the second appends information to it.
The example output is as follows:

The first parameter was /disk19/oraa/admin/out/o773275.out


The second parameter was /disk17/secure

Although this is a very simple example, it could form the basis for something as
complicated as an output archiving system. You should consider including some
error checking for completeness. Later you will see that the request arguments can
also be extracted and recorded in the log file.

For normal programs, consider If you decide to use this or any other approach in this paper that runs custom
defining a single printer called "printing" steps, an external program, or shell script, then you should realise that the
"Special", with print styles that concurrent request will not be marked as complete until the program completes.
mimic the purpose of the shell You should ensure that the end users understand that they will need to review the
script or program such as "Fax", request log before complaining about performance or calling Oracle Support about a
"Copy", “Move” and so on. hanging concurrent request.

This approach can be particularly useful for comprehensively describing Financial


Statement Generator (FSG) reports. A few programs, like FSGs, actually choose
their own print style at runtime. In order to get around this problem, you need to
identify the set of print styles that FSG actually uses, and define a dedicated
"printer" for your driver (e.g. "FaxFSG"). Then your custom driver can be associated
with each style in the set for that printer.

Enhancing Oracle Applications Concurrent Processing -9-


EXAMPLE 3: INTEGRATING A FAX SERVER

Although there are several fax services available for both UNIX such as Hylafax
(http://www.hylafax.org) and Mgetty+Sendfax (http://alpha.greenie.net/mgetty) they can
be difficult to setup and integrate with Applications. One of the first problems that
you will find is how to extract the fax number from the document. You could pass
the fax number as a program argument, but this can quickly become very tedious.

As most of the Oracle Applications documents have a static layout, you could use a
combination of sed and awk to extract an embedded fax number or destination.
Products such as Mgetty+Sendfax, will resolve the name of the vendor using a
lookup file. However, if you want to add more information such as using a form
overlay, personal signatures or company logos then you probably need to consider a
completely integrated solution such as RightFax (http://www.rightfax.com).

To make this example more interesting, consider a scenario where you have a
Windows PC running as a fax server. This means that in order to fax the file, you
will first need to transfer it to the PC, in which case you will need an ftp server
running on the PC. At this point you will find another problem. You cannot specify
the username, password, or command (i.e. get/put) on the command line for a
normal ftp session and so you need to consider using an alternative such as the
Ncftp client (http://www.ncftp.com). The ncftp program parameters are as follows:
ncftp <options> -u <username> -p <password><host> <path><filename>.

So with a username and password of andy/andy and a the fax server called faxserv
you would use the following command as shown in Figure 4:

ncftp put –u andy –p andy faxserve $PROFILES$.FILENAME

Figure 4: Transferring Documents to a Fax Service on a PC

Note: If you use this technique, it is important to take the appropriate


security measures since you are using plaintext passwords! This is obviously
not acceptable on some applications.

Enhancing Oracle Applications Concurrent Processing - 10 -


4. MANAGING MULTIPLE REQUESTS

The second part of this paper introduces programmatic techniques that can be used
independently of concurrent processing or even Oracle Applications. It starts by
explaining a technique that enables the result of a simple SQL script to be assigned
to a system variable. Later examples deal with reporting the concurrent program
arguments, which are shown in context as a way of cataloguing multiple reports in a
complex archiving system.

In the printer driver examples in the previous section, each of the concurrent
requests must have completed prior to the shell script or program being run. In this
section the scripts can be run manually, as a timed program, or as a separate
concurrent job. This means that you need to understand the phases and status of
each request to avoid system locking issues or working with inappropriate files.

Each concurrent request has a life cycle, proceeding through three or possibly four
phases, which include inactive, pending, running, and completed. Each concurrent
request can have any one a number of possible statuses; the subset that apply to
completed requests are shown in Table 1.

Status Description
Normal Request completes normally.
Error Request failed to complete successfully. Review the log file
for more information.
Warning Request completes with warnings. For example, a report is
generated but fails to print.
Cancelled Pending or Inactive request has been cancelled by a user
setting the status of the request to Cancelled.
Terminated Running request has been terminated by a user setting the
status of the request to Terminated.
Table 1: Completed Request Statuses

The phase_code and status_code are stored in FND_LOOKUPS using the


quickcode types of CP_PHASE_CODE and CP_STATUS_CODE respectively. It
follows that if you only want to process jobs that have completed normally, then you
will need to add the expression phase_code = ‘C’ and status_code = ‘C’ to your SQL
query.

Enhancing Oracle Applications Concurrent Processing - 11 -


4.1 EXTRACTING VALUES (1): THE BASIC SQL SCRIPT

Historically, when you have needed to get a value from the database into a system
variable you would need to perform the task manually. For example, you would have
to query the value from the database and then manually assign it to a variable, or
possibly pass it as an argument to a shell script.

This first example shows how to run a SQL script and then automatically assign the
value to a variable. So, lets say that you want to find the most recent concurrent
REQUEST_ID for the ‘Active Users’ report. The SQL script (called getval.sql) that
you would need is as follows:

REM getval.sql
set feedback off
set pagesize 0
SELECT MAX(R.REQUEST_ID)
FROM FND_CONCURRENT_PROGRAMS_VL P,
FND_CONCURRENT_REQUESTS R
WHERE P.CONCURRENT_PROGRAM_ID = R.CONCURRENT_PROGRAM_ID
AND P.USER_CONCURRENT_PROGRAM_NAME = ‘Active Users'
AND R.PHASE_CODE = ‘C’
AND R.STATUS_CODE = ‘C’;
exit

The SQL script switches off all feedback and suppresses the SQL column and row
information (This is important so that only the actual value, the REQUEST_ID is
returned). The SQL query references the user (visible) name. It could have
referenced the internal name – the CONCURRENT_PROGRAM_NAME, as
described in the quick concurrent processing recap section at the start of this
document. This is not only shorter but will also make the script independent of the
NLS_LANG setting.

An example UNIX session to run the script and assign it to a system variable is as
follows. The apps password used throughout this document is “test”.

$ unixvar=`sqlplus -s apps/test @getval`


$ echo $unixvar
614190

There are three noteworthy points:

• SQLPlus is run with the –s option, which suppresses the SQL session login
information.
• The backward quotes are used which tell UNIX to evaluate the expression
before assigning the result to the variable.
• Although the username and password are used in this example, if the script
was going to be run as host concurrent program then you should replace
them with the variable '$FCP_LOGIN'. This avoids the security risk of
having a password hard coded in the script. This is discussed further in the
Security Concerns section of this paper.

Enhancing Oracle Applications Concurrent Processing - 12 -


4.2 EXTRACTING VALUES (2): THE INTEGRATED APPROACH

This section introduces the concept of integrating a SQL script and assigning the
output to a system variable within a single shell script. There are several examples
that each demonstrate a different feature. The first routine is based on the previous
generic example whereas the subsequent scripts expand on this basic idea to show
you more powerful techniques.

Tip: Although UNIX is used for throughout, if you are using Windows
NT/2000 you can use the shell that comes with the MKS toolkit if you have
Oracle Applications 11i installed. Using this approach for shell scripts should
be considered carefully as the requirement for MKS may not exist in future
Applications releases.

It is perhaps also worth noting at this point that these scripts should work without a
problem in the Bourne (sh) and Korn (ksh) shell, however they will probably not
work without modification in the C shell (csh) or extended C shell (tcsh).

EXAMPLE 1: WORKING WITH A SINGLE VALUE


A SQL/UNIX SCRIPT

This script produces exactly the same output as the previous example – it returns a
single REQUEST_ID for the most recent “Active Users” report and assigns it to a
UNIX variable. Let’s start by looking at the code and then work out what it is doing.

unixvar=`sqlplus -s apps/test @<<!


set termout off
set feedback off
set pagesize 0
select MAX(R.REQUEST_ID)
from FND_CONCURRENT_PROGRAMS_VL P,
FND_CONCURRENT_REQUESTS R
where P.CONCURRENT_PROGRAM_ID =
R.CONCURRENT_PROGRAM_ID
and P.USER_CONCURRENT_PROGRAM_NAME = 'Active Users'
AND R.PHASE_CODE = ‘C’
AND R.STATUS_CODE = ‘C’;
exit
!`

The easiest way to understand this script is to compare it with the previous basic
example that used a simple SQL script. First, UNIX evaluates the complete
expression between the `` (backward) quotes and then assigns the SQL query result
to the unixvar variable.

Taking a step back, when running a SQL script the @ symbol would normally be
used to denote the name of the file, but in this case it reads the SQL expression until
it encounters the exclamation mark (!). As in the previous example, the SQL script
suppresses the column and row information, runs a single query, and exits back to
UNIX. In order to show the output and demonstrate that the script worked, you
could use the following commands:

$ echo $unixvar
614190

Enhancing Oracle Applications Concurrent Processing - 13 -


This entire example can be run from a UNIX prompt or as a part of a shell script.
You could use this shell script as is or it could be the start of a much larger script. In
reality, if you just want to manipulate a single file you would be better off using one
of the examples from the first half of this document. Where this approach becomes
more useful is that it can be used to process multiple concurrent requests, as you will
see in the following example. As you probably realise, the concurrent request file
name is a little different to the value returned from SQL. However, it is very simple
to manipulate the system variable to reconstruct the precise filename and path
within a shell script.

EXAMPLE 2: WORKING WITH A LIST OF VALUES


A SQL/UNIX SCRIPT

This routine extends the previous approach by retrieving a list of values allowing you
to perform commands on each such as copy, move, zip, or perhaps running a
conversion utility. This approach is more useful when, for example, you want to
archive all the Active Users reports rather than just the latest.

As you can see, the example script below is very similar to the previous example. In
this case the SQL will return all the REQUEST_IDs for all the ‘Active User’ reports.
The UNIX for loop that follows the query simply echoes the request numbers for
each of the reports to demonstrate that each output file can be dealt with in turn.
This is the point where you would place your file commands, include some error
checking and perhaps even record the actions in a log file.

# getreqs
unixvar=`sqlplus -s apps/test @<<!
set termout off
set feedback off
set pagesize 0
select R.REQUEST_ID
from FND_CONCURRENT_PROGRAMS_VL P,
FND_CONCURRENT_REQUESTS R
where P.CONCURRENT_PROGRAM_ID =
R.CONCURRENT_PROGRAM_ID
and P.USER_CONCURRENT_PROGRAM_NAME = 'Active Users'
AND R.PHASE_CODE = ‘C’
AND R.STATUS_CODE = ‘C’;
exit
!`
for unixvar in $unixvar
do
echo "The request number is: $unixvar"
done

An example session might be:

$ ./getreqs
The request number is 540185
The request number is 540335
The request number is 540343
The request number is 540345

Enhancing Oracle Applications Concurrent Processing - 14 -


Two very important points that you should be aware of are as follows:

• All the values are concatenated into a single UNIX variable; the length of
the variables differs depending on the particular platform and so might be a
concern when working with very long lists.
• This example works without a problem as none of the values include
spaces. If there were embedded spaces in any of the fields then you will find
that each value is returned correctly by SQLPlus, but the UNIX for loop
splits each value across multiple lines. In this case, you will need to use a
different approach. The UNIX cut command works well.

The type and range of reports is controlled by the where clause in the SQL query and
instead of listing one particular report, you could simply change it to return say all
the security reports, or perhaps all the FSGs and other financial reports generated
during the month-end processing.

EXAMPLE 3: WORKING WITH A MULTI-VALUE LIST


A SQL/UNIX SCRIPT

In the preceding examples, each record returned only contains a single value – the
REQUEST_ID. While this may be adequate for very simple situations, in reality you
will normally want to return more information such as the name of the user who ran
the request and perhaps the arguments that were used to run the report. This final
example shows you how to retrieve and manipulate several values for each row
returned. As mentioned in the previous example, this information is essential when
cataloguing reports (such as FSGs) or publishing multiple reports to the web.

Consider a case where you want to move all the Active Users and Signon Audit Users
reports to another location before running the purge concurrent request program.
Let’s say that you also want to record the report parameters.

First you need to review the FND_CONCURRENT_REQUESTS table. While each


argument is stored separately, the first 25 arguments are stored as comma separated
values in the ARGUMENT_TEXT column, which is adequate for the intended
purpose here. This example again uses the user name rather than the internal name.
This forms the basis for the following script:

Enhancing Oracle Applications Concurrent Processing - 15 -


# getreqs
unixvar=`sqlplus -s apps/test @<<!
set termout off
set feedback off
set pagesize 0
select R.REQUEST_ID||’,’||U.USER_NAME||’,’||
R.ARGUMENT_TEXT||’:’
from FND_CONCURRENT_PROGRAMS_VL P,
FND_CONCURRENT_REQUESTS R,
FND_USER U
where P.CONCURRENT_PROGRAM_ID=
R.CONCURRENT_PROGRAM_ID
and R.REQUESTED_BY = U.USER_ID
and P.USER_CONCURRENT_PROGRAM_NAME IN
('Active Users', 'Signon Audit Users')
AND R.PHASE_CODE = ‘C’
AND R.STATUS_CODE = ‘C’;
exit
!`
count=1
num_of_fields=`echo $unixvar | awk -F: '{print NF}'`
while [ $count -lt $num_of_fields ]
do
test_var=`echo $unixvar | cut -d : -f $count`
count=`expr $count + 1`
echo "The value is : $test_var"
done

An example session that runs the program and displays the output is as follows:

$./getsql
The value is : 540550,OPERATIONS,LOGIN_NAME, , OPERATIONS, 01-JAN-99
The value is : 540548,OPERATIONS,
The value is : 540549,OPERATIONS,LOGIN_NAME, , OPERATIONS, 01-JAN-99
The value is : 540185,ASPARSHO,

Note that the SQL script appends a colon(:) to the end of each record. This is used
as a delimiter in the output to identify where each record ends. Also recall that the
UNIX for loop splits values containing spaces across multiple output lines. This
means that the while loop is necessarily more complex to get around this problem.

Without going into too much depth, the script sets the num_of_fields variable to the
You can find out who ran a request number of fields (print NF) in each record using a colon as a field delimiter (-F:).
by linking to the REQUESTED_BY The program could have been shortened by integrating step this into the while loop,
column to FND_USER. but this would have made the program unnecessarily complex. The while loop
contains the sequence of instructions for each record and separates each record
using the UNIX cut function.

Obviously, there are several other ways of delimiting the output and manipulating
each record or field in a record, but this provides some basic ideas and a good
starting point. If you decide to use another approach then you will need to test it
very carefully as several other UNIX commands did not work as well. For example,
as previously mentioned you will find that a very simple array processing for loop will
break the output across another line each time that it encounters a space in the
output stream.

Enhancing Oracle Applications Concurrent Processing - 16 -


5. LIMITATIONS AND UTILITIES

All of the methods up to this point have no problems when dealing with values that
do not include spaces. As all concurrent output filenames are contiguous then this is
not a problem within the context of manipulating concurrent request output files.
This means that you will be able to write very simple shell scripts with a high degree
of confidence.

Example 3 in the last section shows some of the problems when dealing with
embedded spaces. This final section describes an approach using Perl that avoids
some of the limitations of the UNIX examples. If you have a Windows NT/2000
system but do not have MKS installed then this provides another alternative. The
section concludes with a brief discussion of some transfer and conversion utilities
that you will find useful when developing your own programs.

5.1 MANIPULATING OUTPUT RECORDS USING PERL

There are several other ways of extracting values from the database and
manipulating the output files. This example uses Perl as it is a common language that
may also be used for Applications maintenance. If you do not have it installed then
you can get a win32 version, which is freely available from
http://aspn.activestate.com/ASPN/Downloads/ActivePerl.

This program functions in much the same way as the previous example.

#!/usr/local/bin/Perl
$statement="
sqlplus -s apps/test @<<!
set termout off
set feedback off
set pagesize 0
select R.REQUEST_ID||','||U.USER_NAME||','||
R.ARGUMENT_TEXT
from FND_CONCURRENT_PROGRAMS_VL P,
FND_CONCURRENT_REQUESTS R,
FND_USER U
where P.CONCURRENT_PROGRAM_ID =
R.CONCURRENT_PROGRAM_ID
and R.REQUESTED_BY = U.USER_ID
and P.USER_CONCURRENT_PROGRAM_NAME IN
('Active Users', 'Signon Audit Users')
AND R.PHASE_CODE = ‘C’
AND R.STATUS_CODE = ‘C’;
exit
! ";

@unixvar=`$statement`;
$length = $#unixvar;

Enhancing Oracle Applications Concurrent Processing - 17 -


for ($i = 0; $i < $length ; $i++)
{
print "unixvar=$unixvar[$i]....\n";
@split_unixvar = split(/,/,$unixvar[$i]);
print "row number= $i \n";
for ($j = 0; $j < 2 ; $j++)
{
#print "j= $j \n";
chomp($split_unixvar[$j]);
print "The value of unixvar value $j is: $split_unixvar[$j]\n" ;
}
}

You should easily recognise the SQL component. The @unixvar line runs the SQL
and again, the output is assigned to the unixvar variable. The remainder of the
program is a standard for loop, which will be familiar if you have programmed in
other languages such as C. The only thing that is slightly strange is the chomp
command; this filters the input record separator at the end of each record (simply
cleaning up the end of each record).

5.2 PROBLEMS WITH PERL ON WINDOWS NT

Perl on Windows NT is very different to UNIX as it does not understand or refuses


to work with "<<" which is at the heart of this example. This may be due to the
particular variant of Perl that was being used, but it is clear that it may need to be
handled differently.

Depending on which version you are using and which platform you are on, you may
need to use a separate SQL script. This means that you need to have multiple files,
which although very messy, may mean the difference between being able to achieve
your goal or not. So, the first thing you would need to do is create a file with the
SQL statement, say SQL_AT.SQL and run it using the following command:

$statement="plus80 -s apps/test \@sql_at.sql";

The remainder of the program would be exactly the same starting with the @unixvar
line.

Enhancing Oracle Applications Concurrent Processing - 18 -


5.3 SCHEDULING FILE TRANSFERS

There are a number of reasons where scheduling the transfer of large files (including
concurrent reports) after normal working hours or during quiet periods is beneficial.
Not only can this ensure the best network performance for remotely connected
application users in a high latency environment, but it can also even out the network
load, effectively reducing WAN costs.

There are several utilities that can schedule file transfers. For example, the free
versions of Go!Zilla (http://www.gozilla.com) and RealDownload
(http://www.real.com/download) for Windows NT/2000, and GNU Wget
(http://www.gnu.org/software/wget) for UNIX all work well and are relatively easy to
use. The user interfaces for the Windows utilities are self-explanatory. However, in
order to use Wget in a scheduling capacity, you have to use it in conjunction with the
UNIX at command.

A simple example of how you would use at and Wget to download multiple files at a
specific time is as follows:

$ at 18:30
at> wget ftp://apg.uk.oracle.com/pub/A89222-01.zip
at> >Hit CTRL-D at this point<

You should then be returned to your shell prompt, with a job number displayed next
to the timestamp when the job will start, even if you log out of the session. At the
specified time, Wget will wake up and attempt to download the files, in the
background to the directory where the at session was started. This means that
instead of “pushing” files, the control script will need to login to the remote machine
to get the files.

If you want to regularly transfer concurrent output files to a remote site then you
could, for example, use one of the routines in this paper to copy all the files to a
specific local directory. Next you would need to periodically schedule a wget script on
the remote machine to transfer all of the files in the local directory. The wget script
could run once say overnight, or during quite periods if there is no clear batch
processing window.

An alternative way to download files is to create a simple shell script. In the


Wget will try to resume a broken following example, the –P option is used to override the default directory and
download from the p For this specify a particular location that is to be used to save the files. The –o option
reason,oint of interruption. redirects errors from standard output to a log file. The ampersand (&) at the end of
the line makes sure that Wget works in the background.

#!/bin/ksh
wget –P /<target> -o <somepath>/file1.log ftp://oracle.com/pub/A89222-01.zip &
wget –P /<target> -o <somepath>/file2.log ftp://oracle.com/pub/A89223-01.zip &

You would then run this script from the command line. For example:

#at 18:30
at>/<somepath>/myfile.sh
at> >Hit CTRL-D at this point<

Enhancing Oracle Applications Concurrent Processing - 19 -


Wget works well on slow or unstable connections and will retry the connection until
a file is fully retrieved. Like the Windows utilities, it will try to resume the download
from the point of interruption, using `REST' with FTP and ‘Range' with HTTP
servers that support them.

5.4 COMPRESSING & EMAILING DOCUMENTS

When you submit a concurrent request, clicking the Options button in the Submit
Request screen will open the Upon Completion window. An example is shown in
Figure 5. You can use this screen to specify the people or roles to be notified when
the request completes. Setting the Concurrent:Attach URL profile option will
append the output URL to the notification enabling the recipient to view the request
results on-line. This effectively means that you can send the URL to any user or role
defined in Workflow, which is useful when mailing internal users.

Figure 5: The Upon Completion Window

There are several situations where you may want to email the output from a
concurrent request. Examples range from simply sending order-related documents
to a supplier to sending financial reports to a company accountant who does not
have direct access to the Applications system. It is clear that emailing documents can
provide a useful alternative to faxing documents (as described in the Integrating A Fax
Server example).

The programs mailx and sendmail (http://www.sendmail.org) are commonly found on


UNIX platforms; a quick search on the web will find several alternatives for other
platforms. There is a huge choice for Windows 2000/NT. However, there have
historically been many security concerns regarding email programs and so it is
important that you take all the necessary measures to ensure that the email program
you use correctly configured, fully patched and secure.

Enhancing Oracle Applications Concurrent Processing - 20 -


Before sending a document, compressing it beforehand will reduce the load on the
mail server, network, and recipient’s email quota. While finding a command-line zip
utility is fairly simple, attaching a file to an email is not. One solution is to uuencode
the file.

The following program shows you how to uuencode and send a file to a list of
people whose addresses are contained in a file called “mail_list”. The program keeps
a log of the emails sent in a file called “mail_log”.

#!/bin/ksh
# $1 is the filename to send

FILE=$1
subject="$FILE from Oracle Applications"

Use sed and awk to extract a


for recipient in `cat mail_list`
recipients name that is embedded
do
in a document.
echo "Mailing $FILE to $recipient at `date`" >>mail_log
uuencode $FILE ${FILE}_out | mailx -s $subject $recipient
done

Note that the recipient will need to understand the uudecode command.

5.5 PDFS AND CONVERSION

Oracle Applications 11i can automatically produce PDF and HTML output, in
addition to several other standard formats. When you want to create a file in a
variety of output formats, you would normally need to run the concurrent program
several times using different output options each time. Depending on the size of the
report, this may unnecessarily place a considerable load on the server. A better
approach is to run the concurrent program once and then convert the output files
using system utilities. As you have seen, running conversions programs automatically
can be very achieved using any of the techniques presented in this paper.

However, before considering file conversion, it is worth reviewing the PDF format,
which is one of the de facto standards for electronic distribution of documents.
They are created from postscript files (postscript is a programming language that
describes how the printed page should look) and can contain text, images, forms or
even movies. In Applications terms, this means that they can eliminate the need for
costly pre-printed forms. A PDF is considerably smaller than its corresponding
postscript file and can be viewed by anyone with a free Acrobat Reader or directly
from within Oracle Applications.

Enhancing Oracle Applications Concurrent Processing - 21 -


AUTOMATING PDF PRINTING

It is also worth mentioning that you cannot send a PDF direct to a printer; instead
you need to convert it back to postscript format first. This happens automatically in
Applications when a user reviews the file using Acrobat Reader and prints it locally.
If you want to print the file on UNIX you will need to install the Acrobat Reader.
To convert and print the PDF, you would use the command:

cat filename | acroread -toPostScript -shrink | lp

Note that if acrobat is not in the path, you will need to specify the complete path.

While you could use this command in a shell script, you can also print PDFs
automatically from the concurrent manager by changing the print command (as
shown in the Printer Drivers Screen in Figure 1) to the following:

cat $PROFILES$.FILENAME | acroread -toPostScript -shrink | lp -c -


d$PROFILES$.PRINTER -n$PROFILES$.CONC_COPIES
$PROFILES$.FILENAME

There is a huge amount of information on the web pertinent to Oracle Applications.


For example, http://www.fastio.com describes Unicode and Asian Font Support. It
discusses automating web page generation, which will simplify publishing reports to
the web, and how you go about generating customized reports.
http://www.planetpdf.com describes many of conversion tools available. The tips
section includes topics such as conversion from HTML, using forms and using
watermarks. http://www.pdfzone.com has a huge number of conversion, forms and
extraction tools.

AN EXAMPLE CONVERSION ROUTINE

Converting files is generally a very simple process. Consider the case where you want
to convert a postscript file into a PDF, but do not have Adobe Acrobat installed.
You could for example use a utility called Ghostscript which it available from
http://www.ghostscript.com. Not only does it have a command line interface that is well
documented and very easy to use, but it also runs on most platforms. In order to
convert a postscript file called infile.ps to mypdf.pdf on Windows you could use the
following command line:

gswin32 -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -


sOutputFile=mypdf.pdf infile.ps

The Ghostscript documentation describes several other conversion options such as


extracting text from a PDF. Ghostscript is just one of several utilities available. Many
have their own idiosyncrasies and limitations and so again, you should extensively
test the product you intend to use.

Enhancing Oracle Applications Concurrent Processing - 22 -


5.6 SECURITY CONCERNS

Most of these programs in this paper require usernames and passwords when used
outside of the context of the concurrent manager. A number of techniques exist for
passing usernames and passwords to scripts. Although a detailed discussion of
password security is outside the scope of this paper, one technique is to store
usernames and passwords in a text file which is protected using the operating system
security. A simple shell scripts could access this file to obtain the passwords as
required; effectively eliminating the need to hardcode passwords in scripts.

Consider a password file containing the username and password as follows:

#ora_passwd
#This is a protected password file
apps/test
system/mypassword

The following simple shell script will return the username and password in the
correct format (i.e. username/password):

grep -i $1/ <pathtofile>/ora_passwd

An alternative is to run the shell script as a host concurrent program. This approach
is described in the “Host Language Concurrent Programs” section of the System
Administration manual. To have the username/password passed as an environment
variable, you need to enter the term ’ENCRYPT’ in the Execution Options field of
the Register Concurrent Programs window when defining a concurrent program.
This signals the concurrent manager to pass the username/password in the
environment variable $FCP_LOGIN.

6. CONCLUSION

This paper has introduced you to several techniques that can be used to enhance and
automate the Oracle Applications concurrent processing suite. They have ranged
from simple changes to the printer driver through shell scripts to Perl programs and
as you can see, most of the examples are very quick and easy to implement.

As you have seen, you can retrieve any information from the database using the
embedded SQL approach described in this paper. You may have also realised that
you can just as easily insert, update, or delete records using the same type of shell
script. However, it is STRONGLY RECOMMENDED that you do not do this as
you risk corrupting your database and irreparably damaging all of your applications.

Apart from the simple benefits of being able to move sensitive reports or
automatically zipping and distributing documents across WANs during quiet
periods, you have the opportunity to build a very compressive archive routine that
can be used for example to catalogue, separate and organize month end reports.

Enhancing Oracle Applications Concurrent Processing - 23 -


November 2001
Author: Andy Tremayne (Applications Performance Group)
Acknowledgements:
Darren Smith
Robert Azzopardi
Mike Mast

Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065
U.S.A.

Worldwide Inquiries:
Phone: +1.650.506.7000
Fax: +1.650.506.7200
www.oracle.com

Oracle is a registered trademark of Oracle Corporation. Various


product and service names referenced herein may be trademarks
of Oracle Corporation. All other product and service names
mentioned may be trademarks of their respective owners.

Copyright © 2001 Oracle Corporation


All rights reserved.

You might also like