Oracle Forms File Upload Utility

Overview

This utility provides a demonstration of how a combination of a Java Bean embedded in the Oracle 9iAS Forms Java Client and Java called from the Oracle 9iAS Forms Services on the middle tier can be used to transfer files from the browser client machine, onto the middle tier machine. The utility consists of three parts:

  1. A Client side Java Bean which selects, encodes and transfers a file from the browser client.  This is the UploadClient Java Bean
  2. Some server side Java classes which handle the receiving of the transferred file, decoding and writing it back to disk on the server.
  3. A PL/SQL library which provides the glue between the two sets of Java.

The Java Bean portion must reside in a signed JAR file at deployment time since it performs an operation that is outside of the Java sandbox for non trusted code. This distribution ships with a signed version of the JAR file as well as some utilities that will aid you in signing your own JAR files.

This distribution contains both the source code for the upload utility as well as a demo and compiled versions. When unzipped you will see the following directories:

Directory Contains
.\src The Java source files for the Java Bean, and the Server side Classes
.\classes The compiled classes for the UploadClient Java Bean that can be used as a PJC in an Oracle Forms application. The compiled classed for the Server side portion of the code. The Utility also includes three JAR files in this directory:
  1. The JAR file for the PJC - UploadClient.jar
  2. A Signed version of the UploadClient.jar file with a .sig suffix
  3. A JAR file containing the server side classes UploadServer.jar (There is no need to have a signed version of this)
.\doc The JavaDoc generated documentation from the Java Bean and Server side Java source files. This documents the methods and attributes used within the code.
.\misc Contains files for creating a certificate to sign the UploadClient JAR file used to deploy the client side of the application. The JAR file signing utilities have been developed for use on a Windows operating system but should be easily ported to other operating systems. The digital certificate used to sign the JAR file (PJC.x509) is also stored in this directory.
.\forms Contains a PL/SQL library which contains the code required to incorporate the file upload utility into your modules.  You will also find an example form demonstrating the use of the utility.

This document covers the following tasks:

Installing and running the File Upload Demo

Reusing the File Upload Utility in your own Applications

The FileUpload PL/SQL API

Making changes to the File Upload Utility

Known Restrictions

Trouble Shooting

Installing and running the File Upload Demo

Prerequisites

This utility is designed to work only with Web deployed Oracle iAS Forms services 6i Release 2 and above. The utility can be used either with the Forms Listener, or the Forms Listener Servlet (Patch 4 and above). If using the Forms listener, then the various environment settings for CLASSPATH etc. will have to be set in the environment used by the listener as it starts. When using the listener servlet, then environment settings can be placed in the jserv.properties file or in a separate environment variables file if using Patch 5 or above.

In order to run the middle tier portion of the code you will need a version 1.2.2 JDK (or above) runtime available.

Installing the Code

  1. Unizip the FileUpload.zip file into a directory called FileUpload
  2. Copy the UploadClient.jar.sig file from the FileUpload\classes directory to the codebase directory being used to deploy the Forms Services - Usually forms60/java.
  3. Copy the UploadServer.jar file from the FileUpload\classes directory to the same codebase directory. This file can actually be located anywhere on the server but it is best to keep the server and client code together.
  4. Set the CLASSPATH of the Forms Services to include the UploadServer.jar - using the location you selected in Step 3. As mentioned before you may need to set this CLASSPATH in the environment if using the Forms Listener, in the jserv.properties (using a wrapper.classpath= directive) if using the Listener Servlet with Patch 4, or in an environment file if using the Listener Servlet with Patch 5 (see example environment file below)
  5. Set the PATH for the Forms Services to include the Forms \bin directory and the \bin\classic directory of a 1.2.2 JDK runtime.
  6. Set the FORMS60_PATH for the Forms Services to include the FileUpload\forms directory to be able to run the Demo Form.

A sample environment file if using the Forms Listener Servlet with Patch 5 might look like:

#Environment file used to setup the FileUpload Demo

ORACLE_HOME=d:\oracle\dev6i
PATH=d:\oracle\dev6i\bin;d:\oracle\ias\Apache\jdk\jre\bin\classic
FORMS60_PATH=d:\FileUpload\forms
CLASSPATH=d:\oracle\dev6i\forms60\java\UploadServer.jar

Running the code

  1. On the client machine that will be running the demo it it's browser, install the PJC.x509 certificate. To do this:
  1. Copy the PJC.x509 certificate to the client machine temp directory e.g. c:\temp
  2. Open an operating system shell
  3. Change directory to your JInitiator \bin directory e.g. C:\Program Files\Oracle\JInitiator 1.1.8.10\bin
  4. Issue the following commands in the O/S shell (assuming that you saved the certificate into C:\temp):

javakey -c PJC true

javakey -ic PJC c:\temp\pjc.x509

  1. Assuming that you are invoking your Forms applications through the Forms Servlet or Forms CGI create the following entry in your formsweb.cfg file:

[UploadDemo]
IE50=JInitiator
form=FileUpload
connectMode=http
archive_jini=f60all_jinit.jar,uploadclient.jar.sig
width=650
height=550
separateFrame=false
splashScreen=no
lookAndFeel=Oracle
colorScheme=Khaki

  1. Then run the demo:

Using the Servlet:

http://<servername>/servlet/oracle.forms.servlet.FormsServlet?config=UploadDemo

Using the CGI:

http://<servername>/dev60cgi/ifcgi60?config=UploadDemo

If you use Static HTML files create a new file to run the Form FileUpload, with the ARCHIVE parameter including the uploadclient.jar.sig.

Reusing the File Upload Utility in your own Applications

Reusing the FileUpload utility within your own applications requires the following steps.

  1. Attach the FileUpload.pll library (shipped in the FileUpload\forms directory) to the form that needs upload capability
  2. Create a new BeanArea on one of your canvases. The bean is invisible and so you can set the size to 1x1. The BeanArea should be placed into a block with the Single Record property set to Yes. This will ensure that the bean is instanciated as soon as the Form is started. You can create a brand new block to hold the bean if you wish.
  3. Set the Implementation Class property of the new BeanArea to oracle.forms.demos.uploadclient.FileUploader
  4. Create a WHEN-CUSTOM-ITEM-EVENT trigger on the BeanArea with the code:

begin
FileUploader.eventHandler(:system.custom_item_event,get_parameter_list(:system.custom_item_event_parameters));
end;

  1. Create a user named trigger e.g. FILEUPLOADER_CALLBACK which the upload utility will execute when the upload is complete or if the upload fails for some reason. We need this trigger because the upload is an asynchronous process, and the trigger that calls the FileUploader.UploadFile() function is not blocked until the upload is finished. A sample callback trigger might look like.

/*----------------------------------------------------*
* Sample Callback trigger for FileUploader
* You should always implement a check on the status
* to make sure that the upload has worked.
*
* This trigger will only be executed once the upload
* has finished or aborted
*---------------------------------------------------*/
Begin
 if FileUploader.getStatus = FileUploader.FINISHED then
  message(FileUploader.getSourceFile || 'was uploaded');
elsif FileUploader.getStatus = FileUploader.FAILED then
  message('Upload Failed because: '||FileUploader.getError);
 end if;
end;

  1. Register the Bean and the Callback trigger by calling FileUploader.init(<BeanArea>,<TriggerName>). This can be done in the startup code for the form, or just before invoking an upload. However, you must call Init() before uploading. A sample call to Init might look like:

FileUploader.init('UPLOAD.FILE_UPLOAD_BEAN','FILEUPLOADER_CALLBACK');

  1. Finally write the code to call the upload. You can either call FileUploader.UploadFile() to display a selection dialog on the client, or FileUploader.UploadNamedFile() to upload a specific file.

FileUploader.UploadFile('d:\temp\uploaded');

Warning: If you intend to use the FileUpload utility in your own applications, We recommend that you re-sign the UploadClient PJC with your own x509 certificate. The certificate supplied with the packaged utility is provided for demonstration purposes and both the public and private keys are available as part of the distribution. This could allow malicious third parties to sign their own code with the same certificate and potentially execute it on any machine with the supplied demo PJC.x509 registered. Furthermore we would recommend that you removed the PJC identity from your identity database (using the command javakey -r PJC), once you have created and installed your own certificate. You can obtain a new certificate from a Certificate Authority or you can generate your own using the cert-maker.bat file supplied in the fileupload\misc directory

The FileUpload PL/SQL API

All of the code required for the FileUpload facility is exposed through the FileUploader package in the FileUpload.pll library. The FileUpload PLL also contains several other packages which provide interfaces to the Java classes used by the utility. These are called via FileUpload and should not be called directly.

Main Functions in the FileUploader package

Function Purpose
Init (BeanName in VARCHAR2, CallbackTrigger in VARCHAR2)

Defines the settings for the upload utility This must be called before upload can be used.

  • BeanName should contain the block and field name of the BeanArea that you've defined for the bean
  • CallbackTrigger will contain the name of a user defined trigger that will be called once an upload is finished or aborted
UploadFile (DestinationDirectory in VARCHAR2, DestinationFilename in VARCHAR2, SourceDirectory in VARCHAR2);

Displays a file dialog on the client, allows the user to select a file and uploads that file to the middle tier.

  • DestinationDirectory is the directory on the middle tier that the uploaded file will be written to. You must have write access to this directory
  • DestinationFilename [optional] is the name for the file once it has been uploaded. If omitted the file name on the client is used.
  • SourceDirectory [optional] is the initial directory for the file dialog to be set to. If this is not set, the utility remembers the last directory that you browsed in this session
UploadNamedFile (FileName in VARCHAR2, DestinationDirectory in VARCHAR2, DestinationFilename in VARCHAR2)

Directly uploads a named file from the client without displaying a file selection dialog.

  • Filename path to and name of file to upload
  • DestinationDirectory is the directory on the middle tier that the uploaded file will be written to. You must have write access to this directory
  • DestinationFilename [optional] is the name for the file once it has been uploaded. If omitted the file name on the client is used.
GetStatus return PLS_INTEGER

Returns the current status of the upload as one of the following constants:

  • FileUploader.UPLOADING: The bean is currently sending Data
  • FileUploader.FINISHED: The bean is not currently Uploading
  • FileUploader.FAILED: The bean is not currently Uploading and the last upload attempt failed (usually because the requested file did not exist)

GetStatus is mainly called from the Callback trigger which will be executed after a successful and a failed upload

GetError return VARCHAR2 Returns the text of the last error returned by the FileUpload. The result of this function is useful after GetStatus returns FileUploader.Failed or after the exception FileUploaderEx is raised.
EventHandler (EventName in VARCHAR2, EventData in PARAMLIST);

Handles all of the messages (events) from the bean. Should be called from the WHEN-CUSTOM-ITEM-EVENT trigger attached to the Bean Area.

  • EventName should be passed :SYSTEM.CUSTOM_ITEM_EVENT
  • EventData should be passed :SYSTEM.CUSTOM_ITEM_EVENT_PARAMETERS

Exceptions in the FileUploader package

Exception Purpose
FileUploaderEx

Exception raised when an unexpected error occurs in the FileUpload process.

When this exception is raised you should check the value of FileUploader.getError;

Utility Functions in the FileUploader package

The following functions are used to control various aspects of FileUpload functionality.

Function Purpose
GetSourceFile return VARCHAR2

Returns the name of the last file to be uploaded.

Note: this is the name of the file on the client. The upload process may have renamed the file when saving on the server if that was requested.

GetSourceDir return VARCHAR2

Returns the name of the directory that the last file was uploaded from.

GetSourceLen return PLS_INTEGER

Returns the size in bytes of the last file that was uploaded.

SetCompressed (CompressionOn in BOOLEAN)

Takes a boolean value to switch compression on or off. When compression is switched on, the FileUpload utility will automatically compress the file before uploading it. The file will be decompressed as it is written to the server.

Compressing the file in this way can vastly reduce the amount of time required for upload and is switched on by default. However, with certain file types such as files which are already compressed (.ZIP, .CAB files etc.) compression will actually slow down the overall upload process. To evaluate the effectiveness of the compression, switch Debug mode on (see below) and you will see the effect of compression on the number of bytes being uploaded.

SetDebug (DebugOn in BOOLEAN)

Takes a boolean value to switch Debug mode on. When Debug mode is on, various informational messages will be written to the Java console as the upload process progresses.

SetDialogPos (X_Pos in PLS_INTEGER,Y_Pos in PLS_INTEGER) Allows you to control the position of the file selection dialog in Pixels. (See Known Restrictions)

Making changes to the File Upload Utility

The FileUpload utility is provided with full source code and JavaDoc. The source code for the client and server parts of the code can be found in FileUpload\src\uploadclient and FileUpload\src\uploadserver respectively. In each of these directories you will find a batch file makepjc.bat which can be used to recompile and deploy the code. In the case of the UploadClient, it also creates a signed version of the JAR file automatically.

Makepjc generates the JavaDoc into the FileUpload\doc directory and the JAR and Class files into the FileUpload\classes directory. In each source directory(src) you will find a file called pjc.properties which drives the make process. This file should not be changed except in the case of signing the UploadClient.jar file, in which case you can change the SIGN_DIRECTIVE property to point to your signing directive file.

Makepjc can also deploy the JAR files to whatever directory is specified on the makepjc command line.

Before running the utility you will need to set two environment variables. The ORACLE_HOME directory contains your Forms installation and the JDK_HOME pointing to the home directory of the correct version of a Java development kit. UploadClient requires a 1.1.8 JDK for compilation. UploadServer requires a 1.2.2 JDK. Ensure that you set the JDK_HOME accordingly before running makepjc for either.

So as an example the commands to rebuild the UploadClient PJC and deploy to the d:\oracle\dev6i\forms60\Java directory would look like:

set ORACLE_HOME=d:\oracle\dev6i
set JDK_HOME=d:\tools\jdk1.1.8
makepjc d:\oracle\dev6i\forms60\Java

Known Restrictions

At the time of publication the FileUpload utility has the following restrictions:

  1. No signed CAB file is shipped with the utility. For the UploadClient bean, we only ship a JAR file and a Signed JAR file. If you want to use the utility with native Internet Explorer (without JInitiator), you will have to create a signed CAB file of your own containing the classes in oracle.forms.demos.uploadclient using the makecab utility from Microsoft. Alternatively you can alter your baseie.htm file to replace the CABBASE parameter with ARCHIVE and refer to the supplied JAR files. If you do this, however, you will have to change your security settings in IE to allow allow unsigned content to run.
  2. SetDialogPos only works when running in native Internet Explorer. When running with JInitiator, the positioning settings are ignored.
  3. File Sizes. Testing of the upload utility has only been carried out with files up to 4MBytes in size. Files that are uploaded are held completely in memory and the maximum size that can be transferred is dependent on the memory available to the JVM.
  4. The look and feel of the progress bar and file selection dialogs are not configurable and may not match the current look and feel being used by your application.
  5. Only one upload bean item is supported per Form
  6. The FileUpload.pll library is not designed for shared use e.g. the use of OPEN_FORM() with SHARE_LIBRARY_DATA. If you have multiple forms with the fileupload code which are sharing libraries, copy the FileUpload package into each of the Forms. (The remaining packages may be shared)
  7. The Bean has no visible aspect and attempting to open a canvas containing the bean will fail. To work around this, open another canvas first than then use the poplist to switch to the canvas with the upload bean on it.

Troubleshooting

Checking your server side CLASSPATH is correct:

When running the demo form (FileUpload) that is supplied with the utility, press Key-Listval (Control+L by default). This will pop up a dialog containing the current CLASSPATH. If this fails then this is because Forms cannot instanciate any Java code at all. Ensure that:

You get a FRM-40735 error whilst running the Demo

If you have ensured that your CLASSPATH is correct and you still get an error when running the demo form, then you should do a Recompile All on the supplied PLL and FMB file.