Oracle SQLJ Frequently Asked Questions

This document contains answers to frequently asked questions about Oracle's SQLJ drivers. Note that these address specific technical questions only and are used to document solutions to frequent customer questions as well as any known problems. Please consult the Oracle8i SQLJ Developer's Guide and Reference for full background information.

If you have any questions or feedback on this document, please e-mail sqljsup@us.oracle.com or helpsqlj@us.oracle.com.

Last updated: 11 July 2000

Quick Jump

Need Troubleshooting?

Go to the Troubleshooting Checklist to solve a problem or issue you have encountered.

Or, jump directly to one of the following

- Errors When Starting the Translator
- Error Messages Encountered During Translation
- Additional Translation Issues
- Error Messages Encountered During Deployment or Runtime
- Additional Deployment and Runtime Issues

Have General Questions?

Start the General Questions part, or go to one of the following

- SQLJ (and JDBC Basics)
- SQLJ Language and Programming
- Oracle-Specific Features
- Translation Process
- Development Environments
- Deploying SQLJ Programs
- Running SQLJ Programs

Contents

Part A. Troubleshooting

1. Troubleshooting Checklist

2. Problems Translating and Compiling SQLJ Programs

2.1 Errors When Starting the Translator "Error in sqlj stub: invalid argument"
"Unable to initialize threads: ..."
"An application error has occurred... Exception:access violation ..." (in trying to run Sun's JDK 1.1.x on Windows NT/Windows 95)
"ExceptionInInitializerError: NullPointerException"
"NoClassDefFoundError: sqlj/tools/Sqlj"
"NoClassDefFoundError: sun/io/CharToByteConverter"
"Error: SQLJ runtime library is missing" 2.2 Error Messages Encountered During Translation "Cannot load JDBC driver class oracle.jdbc.driver.OracleDriver"
"Return type XXXX ... is not a visible Java type"
"Missing equal sign in assignment"
"Warning: Cannot determine default arguments for stored procedures and functions. May need to install SYS.SQLJUTL."
"Error: unable to load ... java.lang.NoClassDefFoundError"
"Unable to convert ...Xxx.ser to a class file"
My code declares a block-level iterator class, and an instance of this class is later created and used in the same block. SQLJ appears to translate my code without difficulty, but javac gives the following error: "Error: Class Xxx not found in type declaration"
"Error in Java compilation: CreateProcess: javac" 2.3 Additional Translation Issues SQLJ hangs during translation
SQLJ translates but does not produce any .class files
I encounter a core-dump/stack-trace/out-of-memory condition during translation
I encounter an out-of-memory condition during translation
Is there a way to speed up translation of a .sqlj file with online checking enabled?
Why are database errors reported as warnings? When I use the Oracle online checker, why do I get one error and one additional warning from the database?
Type class_name of host item #nn is not permitted in JDBC 3. Problems Deploying and Running SQLJ Applications and Applets

3.1 Error Messages Encountered During Deployment or Runtime "SQLException: No suitable driver"
"SQLException: The network adapter could not establish the connection"
"SQLException: Connection refused"
"SQLException: ORA-01017: invalid username/password; logon denied"
"InvalidClassException: Serializable is incompatible with Externalizable"
"ClassNotFoundException: xxx.yyy_SJProfile0 for class xxx.yyy_SJProfileKeys"
"ORA-29541: class class_name could not be resolved"
"SQLNullException: cannot fetch null into primitive data type"
"SQLException: Invalid column type error"
"NullPointerException at java.util.zip.ZipFile.read" 3.2 Additional Deployment and Runtime Issues How can I speed up execution of my SQLJ application?
I developed a SQLJ application with Oracle JDeveloper 3.0 but can't get it to run in my JDK 1.2 environment
I'm having problems with retrieval of CHAR fields in SELECT statements.
Is SQLJ ignoring my UPDATE statements?
I am running against an Oracle 8.0 database and my SQL object updates are not working.
Does SQLJ support connection objects obtained from JDBC Connection Pools?
How can I use SQLJ in middle-tier (or EJB, or XXX) environment Y?
Can I use host variables in SQLJ DDL statements?
Using "WHERE column IN (value_list)" with a value_list of unknown size Part B. General Questions

4. SQLJ (and JDBC) Basics

4.1 SQLJ Resources Are there SQLJ books and other resources that would help a newcomer?
Is there an Oracle e-mail address for SQLJ questions?
Where can I find the SQLJ source code (known as the "reference implementation") that Oracle has made available freely to the public and other database vendors?
Where can I download the SQLJ translator for a given platform?
Why do I find information mentioning JSQL, I thought it is called SQLJ
Can SQLJ be faster than JDBC? 4.2 SQLJ Overview Is SQLJ Y2K-compliant?
What are the pros and cons of choosing Java and SQLJ over C/C++?
Does SQLJ implement the ANSI SQLJ specification?
Does SQLJ implement the ISO SQLJ specification?
What software components are required to translate a SQLJ application? to run a SQLJ application?
Can I use the Oracle SQLJ translator to translate an application to run against a non-Oracle SQLJ runtime?
Is SQLJ really database neutral? 4.3 JDBC Drivers What should I know about the Oracle JDBC drivers?
Can Oracle SQLJ be used with non-Oracle JDBC drivers? 4.4 SQLJ, JDBC, and JDK Versions What are the different versions of Oracle SQLJ and how do I get them?
How do the Oracle SQLJ 8.0.5 and 7.3.4 versions differ from the 8.1.5 versions?
Which versions of Oracle JDBC and the Sun JDK does each version of Oracle SQLJ support?
Do I need a different set of SQLJ class files depending on whether I'm running under JDK 1.1.x or JDK 1.2? 5. SQLJ Language and Programming In the sample programs, I see the following import clauses at the beginning of the source code. What are these packages? Do I need to use the same import statements in my own SQLJ files?
What's a connection "context"?
What's an iterator?
How do I create iterator classes and connection context classes?
What's an execution "context"?
How do I specify which connection context instance and/or execution context instance a SQLJ statement should use?
Where is the "Oracle" class and what does it provide?
Can I use SQLJ to write multithreaded applications?
Given that SQLJ supports only static SQL, can I intermix SQLJ and JDBC statements in my source code so that I can use dynamic SQL in the same application? 6. Oracle-Specific Features Do I need to do anything special to use Oracle-specific extensions?
What Oracle-specific features does Oracle SQLJ support?
Can SQLJ interact with PL/SQL in my source code?
Does Oracle SQLJ support PL/SQL BOOLEAN, RECORD, and TABLE types as input and output parameters?
Does Oracle SQLJ support the WHERE CURRENT OF construct?
Does Oracle SQLJ support DML returning?
Can I use the SQL object features with a JDBC 8.1.x driver against an 8.0.x database?
Can I use SQLJ to return PL/SQL arrays from stored procedures?
Does Oracle SQLJ support REF CURSORS? 7. Translation (and Compilation and Customization) Process

7.1 Basic Functionality How do I run the SQLJ translator?
What are the fundamental steps in translating a SQLJ application? What is input and output during the translation process?
Do I have to customize my application? Where do I get the customizer utility?
For basic use of SQLJ, how much do I need to know about profiles (.ser files)?
What's the difference between online semantics-checking and offline semantics-checking? What kinds of checking are done?
I know I can enable online checking by giving the option -user=scott. How can I disable online checking? 7.2 Java Configurations Can I use Java compilers other than javac (the standard compiler included with the Sun JDKs)?
Is it possible to use the JDK 1.0.2 version of the javac compiler to compile .java files generated by the SQLJ translator? 7.3 National Language Support Does the Oracle SQLJ translator provide NLS support?
Can I specify the encoding for SQLJ to use? 8. Development Environments Can I develop and debug SQLJ programs with Oracle JDeveloper?
Can I develop and debug SQLJ programs with other IDEs such as Visual Café or Visual J++? 9. Deploying SQLJ Programs Can SQLJ be used in Java applets?
Can an SQLJ Applet open a connection to a third machine?
For end-users, what browsers will work with SQLJ applets?
Can SQLJ be used in middle-tier Java applications?
Can SQLJ be used inside servlets?
Can SQLJ be used inside JavaServer Pages?
Can SQLJ applications work across firewalls?
Can I use operating system authentication to connect from SQLJ? 10. Running SQLJ Programs What debugging support does SQLJ offer?
If I translate an application with one version of the Oracle SQLJ translator, will I be able to run the application against a future version of the Oracle SQLJ runtime?

Part A. Troubleshooting

The items in this section provide information regarding common problems and errors encountered by SQLJ users.

1. Troubleshooting Checklist

This list should help you to systematically identify a problem you are encountering and point you to where specific issues are being addressed in this FAQ.

1. Do you have a JDK installed in your system, and can you say javac? You can determine your JDK version by issuing
java -version
See also "Unable to initialize threads: ...", "Exception:access violation", "Error in Java compilation: CreateProcess: javac", "NoClassDefFoundError: sun/io/CharToByteConverter".
2. Do you have the Oracle JDBC drivers installed and in your PATH/CLASSPATH? Can you compile and run JDBC programs?
See also "Cannot load JDBC driver class oracle.jdbc.driver.OracleDriver",, "SQLException: No suitable driver", "SQLException: The network adapter could not establish the connection", "SQLException: Connection refused", "SQLException: ORA-01017: invalid username/password; logon denied".
3. Do you have the SQLJ translator.zip and runtime.zip files in your CLASSPATH? Can you issue
javap sqlj.tools.Sqlj
See also "NoClassDefFoundError: sqlj/tools/Sqlj", "Error: SQLJ runtime library is missing".
4. Can you start the SQLJ translator and have it print out its environment by issuing
sqlj -version-long
See also "Error in sqlj stub: invalid argument", "ExceptionInInitializerError: NullPointerException", "Unable to initialize threads: ...".
5. Can you translate and compile .sqlj programs offline? You need to have "." (dot) in your CLASSPATH to compile and run the demo programs supplied with SQLJ. Additionally, if you use the translator option -d directory, you need to have directory in your CLASSPATH so that the SQLJ translator can properly resolve Java classes during all translation phases.
See also SQLJ hangs during translation, SQLJ translates but does not produce any .class files, I encounter a core-dump/stack-trace/out-of-memory condition during translation, I encounter an out-of-memory condition during translation, "NullPointerException at java.util.zip.ZipFile.read".
6. Can you translate and compile .sqlj programs online?
See also "Cannot load JDBC driver class oracle.jdbc.driver.OracleDriver", "Warning: Cannot determine default arguments for stored procedures and functions. May need to install SYS.SQLJUTL.".
7. Can you run your SQLJ program?
See also Error Messages Encountered During Deployment or Runtime, "InvalidClassException: Serializable is incompatible with Externalizable", "ClassNotFoundException: xxx.yyy_SJProfile0 for class xxx.yyy_SJProfileKeys", "ORA-29541: class class_name could not be resolved".

If your issue is not resolved by this FAQ, you may want to use Oracle support or the SQLJ&JDBC discussion forum on http://technet.oracle.com. Please make sure to provide sufficient information about your environment and about the problem you have. Below is a list of information you may want to supply.

SQLJ Error Report

Environment Description

Platform/OS Version:

Database version:

PATH value:

CLASSPATH value:

SQLJ_OPTIONS value:

JDK version (java -version):

JDBC version:

SQLJ version (sqlj -version-long):

Problem Description

Problem Area:

_ unable to start translator

_ translation problem - _ offline or _ online

_ runtime problem

_ deployment problem

Error Message:

Error Description:

2. Problems Translating and Compiling SQLJ Programs

The following problems might be encountered when trying to invoke the translator, or during translation itself. The first and second group of questions address specific error messages; the third group addresses somewhat more general questions.

In either group, some problems may be indicated as being general configuration issues, not specific to your SQLJ code. In these cases, or for general information about SQLJ installation and configuration, see the "Getting Started" chapter of the SQLJ Developer's Guide and Reference.

In brief, before concerning yourself with particular code issues in your application, you should be sure that you can already run the Java compiler, connect to the database using JDBC, and invoke the translator.

2.1 Errors When Starting the Translator

"Error in sqlj stub: invalid argument"

(This is likely a general configuration issue, not something specific to your code.)

The SQLJ translator issues: "Error in sqlj stub: invalid argument" when it is launched. This may happen with SQLJ 8.1.6 on a Windows platform. The problem occurs when the SQLJ wrapper executable sqlj.exe calls

java <java_arguments> sqlj.tools.Sqlj <sqlj_arguments>

The problem may have to do with the size of the CLASSPATH. Also note that SQLJ does not currently support a CLASSPATH containing one or more spaces.

You can have SQLJ display (but not run) the full Java command line above by issuing

sqlj -n <options>

You can try to resolve this issue with one or more of the following:

- Obtain a different sqlj.exe stub (such as from the SQLJ 8.1.7 or later distribution, or from SQLJ 8.1.5 or another earlier SQLJ download)
Also note that the SQLJ downloads on OTN contain the C-source code for the wrapper executable.
- You can try to reduce the size of the CLASSPATH to a minimum, for example to "." (dot), the JDBC classes XXX.zip, the SQLJ translator.zip, and the SQLJ runtime.zip.
- As a workaround, you can also issue
java sqlj.tools.Sqlj <options>

"Unable to initialize threads: ..."

(This is likely a general configuration issue, not something specific to your code.)

If you are using the Java Development Kit from Sun, you may be experiencing problems from conflicts with previously installed Java environments. The easiest way to avoid such problems is to customize your CLASSPATH setting to include only what you need for the JDK, the JDBC driver, and SQLJ. Essentially, you should start with a clean slate.

You can accomplish this as follows:

1. Clear the CLASSPATH.
2. Add "." (current directory) to the CLASSPATH and then make sure you can run java and javac.
3. Add the appropriate JDBC ZIP file--classes111.zip for JDK 1.1.x, or classes12.zip for JDK 1.2. These files are in the JDBC lib directory, such as the following on Solaris:
[Oracle Home]/jdbc/lib/classes12.zip
or the following on Windows NT:
[Oracle Home]\jdbc\lib\classes12.zip
4. Add the SQLJ ZIP file translator.zip. This file is in the sqlj/lib directory, as with the JDBC classesXX.zip files above.
5. Add the SQLJ ZIP file runtime.zip. This file is in the sqlj/lib directory.

Notes:

- You do not need to add the runtime zip if you are using SQLJ 8.1.6 or earlier, but it will not hurt, either.
- For Sun JDK 1.1.3 or higher, you should not need the JDK directory to appear in the CLASSPATH (in fact, it may be advisable to not have it in the CLASSPATH). (This discussion is regarding the CLASSPATH environment variable, as opposed to the Java/SQLJ -classpath option. When using the -classpath option, you do have to include the JDK directory.)
- A convenient approach to going back and forth between your normal CLASSPATH and your CLASSPATH for SQLJ would be to create a script (for Solaris) or a batch file (for Windows) to set up each configuration.

"An application error has occurred... Exception:access violation ..." (in trying to run Sun's JDK 1.1.x on Windows NT/Windows 95)

(This is likely a general configuration issue, not something specific to your code.)

This may also be caused by PATH or CLASSPATH problems. See the answer to the previous question.

"ExceptionInInitializerError: NullPointerException"

(This is likely a general configuration issue, not something specific to your code.)

If you see the following stack trace: unexpected error occurred... java.lang.ExceptionInInitializerError: java.lang.NullPointerException
at sqlj.framework.ClassFileReader.attribute_info(Compiled Code)
...
at sqlj.tools.Sqlj.statusMain(Compiled Code)
at sqlj.tools.Sqlj.main(Sqlj.java:117) then you are likely running SQLJ version 8.1.5 or earlier under JDK 1.2.x or later.

If you are using the command-line version of SQLJ, download and install SQLJ 8.1.6 or later.

If you are using SQLJ from JDeveloper 3.0, download the SQLJ 8.1.6 SDK patch, which contains a translator.zip version to replace the one included in JDeveloper 3.0.

"NoClassDefFoundError: sqlj/tools/Sqlj"

(This is likely a general configuration issue, not something specific to your code.)

The error "Exception in thread main java.lang.NoClassDefFoundError: sqlj/tools/Sqlj" indicates that the SQLJ translator class files cannot be found. Most likely, your CLASSPATH is missing the SQLJ translator.zip file. This file can usually be found in [Oracle Home]/sqlj/lib/. Also remember to add one of the SQLJ runtime zip files to the CLASSPATH — this is required in SQLJ version 8.1.7 and later.

"NoClassDefFoundError: sun/io/CharToByteConverter"

(This is likely a general configuration issue, not something specific to your code.)

Running sqlj results in the following error message. java.lang.NoClassDefFoundError: sun/io/CharToByteConverter
at sqlj.tools.Sqlj.initializeErrors(Sqlj.java:519)
... This happens if you are running under a JRE environment, and not a full JDK environment. You need to download and install a full JDK environment. Note that the Oracle database installation will only set up a Java Runtime Environment. Oracle does not distribute the Java Development Kit - you have to get it from http://java.sun.com

"Error: SQLJ runtime library is missing"

(This is likely a general configuration issue, not something specific to your code.)

This indicates that your CLASSPATH contains the translator.zip file, but is missing the runtime library. The SQLJ library files can usually be found in [Oracle Home]/sqlj/lib/.

- Add runtime.zip to your CLASSPATH if you want to use SQLJ with any JDBC driver — not just the one that corresponds in version to your SQLJ version. For example, if you have SQLJ 8.1.7 and want to use it with any one of the following JDBC versions: 7.3.4, 8.0.5, 8.1.5, 8.1.6, or 8.1.7.
- Add runtime11.zip to your CLASSPATH if your SQLJ and JDBC versions match and you are running in a JDK 1.1.x environment. This runtime provides a slightly better performance and is also the recommended runtime for applet environments.
- Add runtime12.zip if your SQLJ and JDBC versions match and you are running in a JDK 1.2 or later environment. This is necessary for certain JDBC 2.0 features, such as support for java.sql.SQLData through type maps.
You can also use runtime12ee.zip if your SQLJ and JDBC versions match and you are running in a JDK 1.2 or later environment that provides support for the packages javax.naming and javax.sql.

2.2 Error Messages Encountered During Translation

"Cannot load JDBC driver class oracle.jdbc.driver.OracleDriver"

When SQLJ translation results in the following warning:

Cannot load JDBC driver class oracle.jdbc.driver.OracleDriver.

You need to have the JDBC classes111.zip (for JDK 1.1.x) or classes12.zip (for JDK 1.2 or later) in your CLASSPATH environment variable. The following command line should print out the methods on the OracleDriver class.

javap oracle.jdbc.driver.OracleDriver

Subsequently, the following should print out all sorts of version information on SQLJ, JDBC and the JDK you are using.

sqlj -version-long

If this shows the JDBC driver version as 0.0, then the Oracle JDBC driver is not yet in the CLASSPATH.

"Return type XXXX ... is not a visible Java type"

You may be trying to return an iterator instance from a stored procedure, or as a column of a result set, and this iterator type is declared as follows: #sql iterator MyIter (String brand_name); Change this declaration to read as follows (assuming the iterator is declared as a nested class): #sql public static iterator MyIter (String brand_name); The problem is that the SQLJ runtime has to manufacture an instance of the MyIter iterator type. This only works if the iterator type is a public class.

"Missing equal sign in assignment"

This may be caused by using the pre-ANSI style of connection contexts, using parentheses instead of brackets. Instead of: #sql (context_instance) { DROP TABLE test }; use: #sql [context_instance] { DROP TABLE test }; "Warning: Cannot determine default arguments for stored procedures and functions. May need to install SYS.SQLJUTL."

(This is a general configuration issue.)

The SQLJUTL package should be installed automatically in the SYS schema. It is used for semantics-checking of Oracle stored procedures and functions that have been defined to have default arguments.

If the translator indicates that it cannot find SQLJUTL, use the following SQL command (from SQL*Plus, for example) to see if it exists: describe package sqljutl This will provide a brief description of the package if it can be found. If not, you will have to install it manually in the SYS schema, which on Solaris (for example) can be accomplished using the following script: [Oracle Home]/sqlj/lib/sqljutl.sql You must connect to the SYS schema, such as by logging in as INTERNAL, to install this package. Consult your installation instructions if necessary.

"Error: unable to load ... java.lang.NoClassDefFoundError"

This may indicate that the translator cannot find your compiled .class files during customization, and is particularly likely if you are using a Java package structure and are not using the SQLJ -d option during translation.

As a first step, rerun the translator with the -status flag enabled. If this error occurs after the [Customizing] line in the status output, this indicates a problem in finding your .class files during customization.

You can avoid this problem by using the SQLJ -d option when you translate. This option allows you to specify a root directory, and all profiles and .class files are placed underneath that root directory according to the package structure. Also, note that this directory must be in your CLASSPATH.

"Unable to convert ...Xxx.ser to a class file"

This occurs if you are using the SQLJ -ser2class option (to convert .ser profiles to .class files) and the translator cannot find the .ser files to convert. This problem is similar to the NoClassDefFoundError discussed in the previous question, and can also be resolved by using the SQLJ -d option during translation.

My code declares a block-level iterator class, and an instance of this class is later created and used in the same block. SQLJ appears to translate my code without difficulty, but javac gives the following error: "Error: Class Xxx not found in type declaration"

This problem, where Xxx is the iterator class name, results from a known bug in the javac compiler, version 1.1.x. Here is an example of a method that would result in this error: void method() throws SQLException
{
#sql iterator BlockIter (int col1, String col2);
BlockIter i;
#sql i = { SELECT col1, col2 FROM tab };
while (i.next()) { ... }
} The error location is somewhere within the code generated for the SELECT operation. The problem is that block-level classes can be referenced in the same block as they were declared, but not from within blocks within the declaring block. SQLJ generates code for the above SELECT operation as a statement block, and thus cannot instantiate a BlockIter instance within the generated block. A workaround is to declare the iterator at the class-level rather than the block-level. (This problem does not occur with JDK 1.2.)

"Error in Java compilation: CreateProcess: javac"

If the following error occurs during translation. Error in Java compilation: CreateProcess:
javac -J-Djavac.pipe.output=true <filename> error=2 Try one or more of the following.

- Ensure that you have installed the Java Development Kit from http://java.sun.com . Specifically, you should be able to run javac from the command line.
- Reduce your PATH and CLASSPATH setting to the bare minimum to exclude possible conflicts of JavaVM's (you can do that most easily with a script or .bat file - see below).
- Add the -passes option to invoke the Java compiler in a different way.

Note: If you want to use a non-JDK command line environment to compile your SQLJ programs, please refer to "7.2 Java Configurations - Can I use Java compilers other than javac (the standard compiler included with the Sun JDKs)?".

2.3 Additional Translation Issues

SQLJ hangs during translation.

If the SQLJ translator appears to hang during translation, interrupt the translation and add the -status flag to diagnose the problem: sqlj -status .... If, after doing this, you find that the last message issued by the SQLJ translator is the following line: [Compiling] then the problem occurs during invocation of the Java compiler by the SQLJ translator. In this case you need to always add the -passes option to the SQLJ command line: sqlj -passes ... Alternatively, you can add -passes to the SQLJ_OPTIONS environment variable: SQLJ_OPTIONS=-passes ... If, however, the hang occurs before the SQLJ compilation process, you might be translating with a 7.3.x JDBC driver with online semantics-checking enabled. In this case, you must either forego online checking, or upgrade to a newer JDBC driver version (at least an 8.0.x JDBC driver instead of a 7.3.x driver).

Note: If you are using SQLJ 8.1.5, 8.0.5, or 7.3.4 on NT, you should always use the -passes options. Otherwise you will experience this hang.

SQLJ translates but does not produce any .class files

If you run the SQLJ translator, but Java compilation appears to fail silently (you can verify with the -status command line option whether compilation was started) you can try one or more of the following.

- Ensure that you have installed the Java Development Kit from http://java.sun.com .
- Reduce your PATH and CLASSPATH setting to the bare minimum to exclude possible conflicts of JavaVM's (you can do that most easily with a script or .bat file - see below).
- Add the -passes option to invoke the Java compiler in a different way.

I encounter a core-dump/stack-trace/out-of-memory condition during translation.

If no previously discussed diagnosis fits your problem, you may want to try the following.

- Turn off your JavaVM's JIT (just-in-time) compiler. You might be able to use one of the following to accomplish this:
Add the -J-Djava.compiler=none command-line flag to the translator invocation.
or:
Set the JAVA_COMPILER=NONE environment variable.
- Re-set your CLASSPATH variable to only contain . (current directory), the JDBC driver (either classes111.zip, or classes12.zip), the SQLJ translator (translator.zip), and any other classes that are actually referenced by your source, other than classes that are part of your JDK (the JDK classes do not have to be in your CLASSPATH for JDK 1.1.3 or higher).

I encounter an out-of-memory condition during translation.

If you have a genuine out-of-memory condition during SQLJ translation (as opposed to the issue described in the preceding question), you can increase your Java VM's memory allocation by passing additional flags to the SQLJ translator.

For example, you can set a heap size of 128 MBytes for the JDK 1.1.x Java VM with the -mx128M flag. By prefixing this flag with -J, you can use it with the SQLJ translator as follows:

sqlj -J-mx128M ...

Note that you must either pass this flag on the command line, or place it in the SQLJ_OPTIONS environment variable.

Also note that the -mx flag has changed to -Xmx in JDK 1.2.

Is there a way to speed up translation of a .sqlj file with online checking enabled?

If you enable the translator cache option (-cache=true), then SQLJ remembers the result of online checking and stores it in the file SQLChecker.cache. This removes the need to connect to the database for every #sql statement in your program. Note, however, that only those SQL statements that do not result in error or warning messages are being cached. Whenever SQLChecker.cache has become too large, or you want to start with a clean cache, you can just delete file SQLChecker.cache before running SQLJ.

Why are database errors reported as warnings? When I use the Oracle online checker, why do I get one error and one additional warning from the database?

Errors reported by the database are passed on as warnings by SQLJ. This is because the database reporting may not be fully accurate, resulting in spurious errors. The signature of stored functions and procedures is analyzed directly from the SQLJ client. But these function and procedure invocations are also passed to the database for explicit analysis. This results in duplicate reporting of certain errors or warnings concerning stored procedures/functions.

"Type class_name of host item #nn is not permitted in JDBC"

What does the following warning message mean?

Type package_name.class_name of host item #1 is not permitted in JDBC. This will not be portable.

This warning is issued if you use Java types that are supported by Oracle's JDBC driver (and thus in the Oracle SQLJ runtime), but that are not JDBC types. You would only care about this warning if you want to write fully portable code. You can turn off portability warnings in JDeveloper under project properties on the SQLJ tab. On the SQLJ command line you could say: -warn=noportable.

3. Problems Deploying and Running SQLJ Applications and Applets

For general information about deploying and running SQLJ programs, see "Deploying SQLJ Programs" and "Running SQLJ Programs" later in this FAQ.

3.1 Error Messages Encountered During Deployment or Runtime

"SQLException: No suitable driver"

(This is likely a general configuration issue, not something specific to your code.)

If you see the exception trace: java.sql.SQLException: No suitable driver
at java.sql.DriverManager.getConnection(Compiled Code) ...
at oracle.sqlj.runtime.Oracle.getConnection(Compiled Code)
at oracle.sqlj.runtime.Oracle.connect(Compiled Code) then you probably have not added the Oracle JDBC driver ZIP file to your CLASSPATH. Either use: [Oracle Home]/jdbc/lib/classes111.zip (for JDK 1.1) or: [Oracle Home]/jdbc/lib/classes12.zip (for JDK 1.2) Furthermore, you need to ensure that your JDBC driver is registered with the java.sql.DriverManger. If you are using the server-side (kprb) JDBC driver, or if you used one of the methods connect() or getConnection() on oracle.sqlj.runtime.Oracle to obtain a SQLJ connection context, then this will happen automatically. Otherwise you need to register the Oracle JDBC driver, for example as follows: java.sql.DriverManager.registerDriver
(new oracle.jdbc.driver.OracleDriver()); Additionally, you need to ensure that you are specifying a correct URL. For example, if you are using the connect method: oracle.sqlj.runtime.Oracle.connect
(MyApp.class,"connect.properties"); then you should verify that connect.properties is available in the same directory as MyApp.class, and contains something equivalent to the following: sqlj.url=jdbc:oracle:thin:@localhost:1521:orcl
sqlj.user=scott
sqlj.password=tiger (Use the name of your host instead of localhost, your port number instead of 1521, and the name of your database instance instead of orcl.)

"SQLException: The network adapter could not establish the connection"

(This is likely a general configuration issue, not something specific to your code.)

The message: "The network adapter could not establish the connection." means one of two things:

1. The host could not be reached or does not exist. Please use the ping program to verify that the host is accessible on the network.
2. The host does not have a TNS listener running on the specified IP address. You can use the Net8 Configuration assistant to configure a database listener for TCP/IP. Alternarively -for example under Unix- you can do this by editing your listener.ora file, adding an additional line to:
LISTENER = (ADDRESS_LIST=
(ADDRESS=(PROTOCOL=ipc)(KEY=oracle-sid)) )
as follows:
LISTENER = (ADDRESS_LIST=
(ADDRESS=(PROTOCOL=ipc)(KEY=oracle-sid))
(ADDRESS=(PROTOCOL=tcp)(HOST=hostname)(PORT=port)) )
Now you must stop and then re-start your listener to pick up the new settings:
lsnrctl stop; lsnrctl start

"SQLException: Connection refused"

(This is likely a general configuration issue, not something specific to your code.)

If a listener is up and running as specified, but there is no database with the specified Oracle SID, you will see the message: java.sql.SQLException: Io exception: Connection refused(...) "SQLException: ORA-01017: invalid username/password; logon denied"

If the username and/or password is not valid, you get: java.sql.SQLException:
ORA-01017: invalid username/password; logon denied "InvalidClassException: Serializable is incompatible with Externalizable"

(This is likely a general configuration issue, not something specific to your code.)

If you see the exception: java.sql.SQLException: profile xxx.yyy_SJProfile0 not found:
java.io.InvalidClassException:
[java.lang.Object; Serializable is incompatible with Externalizable then you may have a discrepancy between the Java environment that you use to translate SQLJ and the environment that you use to customize/run SQLJ.

- If you are using SQLJ from JDeveloper 3.0, download the SQLJ 8.1.6 SDK patch, which contains a new translator.zip version for replacing the translator.zip file from the JDeveloper 3.0 installation. You must also ensure that the following all match: the JDK version (such as JDK 1.2.2) with which JDeveloper is started, the JDK version used by your project (see your project properties), and the JDK-compatible JDBC ZIP file (such as classes111.zip or classes12.zip).
- If you are using the command-line version of SQLJ, download and install SQLJ 8.1.6 or later or the SQLJ 8.1.6 SDK patch release.
- If you are deploying compiled SQLJ code into an Oracle database (for example, as a Java Stored Procedure, or as an Enterprise Java Bean), then you may want to use the same JDK and SQLJ versions for client compilation that are used in your server JavaVM. Specifically, for Oracle 8.1.7 or higher you may want to use the corresponding runtime12.zip and JDK 1.2, for Oracle 8.1.6 you want to compile under JDK 1.2, and for Oracle 8.1.5 you want to compile using JDK 1.1.x.

"ClassNotFoundException: xxx.yyy_SJProfile0 for class xxx.yyy_SJProfileKeys"

If you see an exception such as: java.sql.SQLException: profile xxx.yyy_SJProfile0 not found:
java.lang.ClassNotFoundException:
xxx.yyy_SJProfile0 for class xxx.yy_SJProfileKeys then you must ensure that the SQLJ profile(s), such as xxx/yyy_SJProfile0.ser, is available in the SQLJ runtime environment. This includes JARing this file as part of an applet deployment, or publishing it to the server via loadjava.

Setting a root directory. You may want to use the SQLJ -d <rootdir> flag to ensure that all files required by your project are deposited under a particular directory hierarchy before you run jar or loadjava.

Applets and converting .ser to .class. There is an additional consideration for applets. Older browser versions that are based on JDK 1.0.2, such as Netscape Navigator 3.0 and Microsoft Internet Explorer 3.0, did not have support for loading a serialized object from a resource file associated with the applet. Additionally, the Navigator browser does not permit resources to be loaded from files with a ".ser" extension. These limitations also result in the ClassNotFoundException when you try to run the applet. As a work-around, specify the SQLJ translator -ser2class option when you translate the code. This instructs SQLJ to convert profiles into Java class format in .class files. If you translate MyApplet.sqlj this way, for example, the profile would be in MyApplet_SJProfile0.class instead of MyApplet_SJProfile0.ser. Then you would have to ensure that the profile .class file is available in the SQLJ runtime environment, as with a profile .ser file.

Deploying code to the server, such as Java Stored Procedures and Enterprise Java Beans. Essentially, you have three choices in uploading your code with loadjava: (1) you can upload source code and have the server compile your code, (2) you can upload .class and .ser files, and (3) you can convert .ser files to .class files and upload these together with the other .ser files. If you use method (2) or (3) and omit one or more .ser and -respectively- converted .class files, you will encounter the ClassNotFoundException when your program is run.

Notes:

- In JDeveloper 3.0 and earlier the -ser2class flag is not supported. You will have to use the sqlj command-line translator to obtain this functionality. Additionally, SQLJ provides a stand-alone tool ("profconv") for converting .ser files into .java files (and subsequently .class files) that permits full control over the conversion process. Issue the following to optain a synopsis of the tool:
java sqlj.runtime.profile.util.SerProfileToClass
- In SQLJ 8.1.6 and earlier only .ser files of less than 32KB can be transformed in this way.

"ORA-29541: class class_name could not be resolved"

My SQLJ program precompiles and compiles successfully, resulting in a .class file which I load without error using loadjava. I then create a procedure to run the stored procedure. When I run the procedure, I get the error: ORA-29541: class class_name could not be resolved Any of the following things should help:

- Add the generated .ser file(s) to be loaded by loadjava.
- Use the -ser2class option when translating your SQLJ source and add the additional .class files to be loaded by loadjava.
- Use loadjava to load SQLJ source rather than .class (and .ser) files.

See also the question "ClassNotFoundException: xxx.yyy_SJProfile0 for class xxx.yyy_SJProfileKeys" above.

"SQLNullException: cannot fetch null into primitive data type"

You cannot assign a null value to a Java primitive type (such as int or float), but you can work around this by using a Java object type (one of the java.lang classes). For example, replace a declaration of the form: #sql public static iterator MyIter(..., int rate, ...); with: #sql public static iterator MyIter(..., Integer rate, ...); Then you can use it as follows, for example: if (iter.rate()==null)
{ ... // null processing }
else
{ value = iter.rate().toString(); ... } "SQLException: Invalid column type error"

An SQLJ statement that calls a stored function or procedure which returns a REF CURSOR issues the exception: "SQLException: Invalid column type error".

This can be caused by one of the following:

- You may have changed the way you obtain a connection to using a DataSource connection pool or to wrapping OracleConnections in some other way. The solution is to use Oracle SQLJ version 8.1.7 or later, or —if you need to continue using an earlier version of SQLJ— to obtain a patch from http://technet.oracle.com
- The profile (.ser file) was not customized to use the Oracle SQLJ runtime. Make sure that you set the option -profile=false when translating. Also, if you use the option -compile=false, so that you can control compilation of the generated .java files, you need to perform a separate customization step after Java compilation by issuing sqlj *.ser on all of the generated profile files.

"NullPointerException at java.util.zip.ZipFile.read"

(This is likely a general configuration issue, not something specific to your code.)

If you encounter the error message: java.lang.NullPointerException
at java.util.zip.ZipFile.read(ZipFile.java)
... then you may want to try one or more of the following:

- You may have superfluous, conflicting CLASSPATH components in your environment. Try to only have the SQLJ runtime.zip, the JDBC classes XXX.zip, and your application's zips in your CLASSPATH. If your program now works, you can add the other class libraries back step by step to determine who the culprit is.
- Turn off the Java Just-In-Time compiler (JAVA_COMPILER=NONE).
- Try another JavaVM version.

3.2 Additional Deployment and Runtime Issues

How can I speed up execution of my SQLJ application?

Tips on improving performance with SQLJ.

- Conversions from SQL data into and out of Java types are rather costly.
If you do not need Java native representations - for example, you
are just copying data from one place to another, you should use
instances of oracle.sql.XXXX types (NUMBER, DATE, CHAR, RAW, etc.)
- Beginning with release 8.1.6, Oracle SQLJ mirrors performance enhancements available with Oracle:
— statement caching: by default, the last five SQLJ statements are being reused.
— batching of inserts/updates: you can enable batching of DML statements that are executed in a loop.
— registration of parameter and column sizes.
- Also, consider adjusting the number of rows that are automatically prefetched on result sets. This is available through the method setFetchSize() on sqlj.runtime.ExecutionContext - see sqlj/demo/jdbc20/FetchSize.sqlj. If you are using SQLJ 8.1.6 or earlier, you have to set this directly through the Oracle JDBC driver - see sqlj/demo/PrefetchDemo.sqlj for more details.

Refer to the SQLJ Developer's Guide and Reference, Appendix A-Performance and Debugging for full information. Statement caching and batching can provide significant performance improvements.

I developed a SQLJ application with Oracle JDeveloper 3.0 but can't get it to run in my JDK 1.2 environment.

JDeveloper 3.0 was released prior to SQLJ release 8.1.6, so uses release 8.1.5, which does not support JDK 1.2. To run the application under JDK 1.2, you will have to download the SQLJ 8.1.6 SDK runtime patch from the Oracle Technology Network (OTN) Web site (technet.oracle.com).

I'm having problems with retrieval of CHAR fields in SELECT statements.

If your table has a CHAR column, such as TITLE CHAR(120), then beware of SQL blank padding behavior.

Instead of selecting only the exact string, as follows:

#sql iter =
{ SELECT NAME, TITLE FROM Tab WHERE TITLE = :("Dawn") };

you will have to use wildcard search parameters, as in the following:

#sql iter =
{ SELECT NAME, TITLE FROM Tab WHERE TITLE LIKE :("Dawn%") };

Is SQLJ ignoring my UPDATE statements?

When I try to update a record using SQLJ, the data remains unchanged. What is going on?

A couple of notes on this.

- JDBC connections have auto-commit on, but SQLJ connections usually have auto-commit off by default. Thus you need to remember to issue a COMMIT to make the update visible.
#sql { COMMIT };
- You can use an ExecutionContext to see how many rows got updated.
import sqlj.runtime.ExecutionContext;
...
ExecutionContext ec=new ExecutionContext();
#sql [ec] { UPDATE table SET ... WHERE ... };
System.out.println("Updated "+ec.getUpdateCount()+" rows.");
- Remember that if the WHERE clause selects no rows, then 0 rows get updated and you will also not see a SQLException.
If your WHERE clause compares any CHAR columns to Java strings, it very likely will not work: you have to blank-pad the Java strings if you want the comparison to succeed. Or you can declare the column as VARCHAR2. Or you could use a LIKE comparison and append a "%" to the Java string.

I am running against an Oracle 8.0 database and my SQL object updates are not working.

Even though the JDBC 8.1.x drivers are backward compatible to 8.0.x databases, they require an 8.1.x database to support SQL object features. (JDBC 8.0.x drivers do not support SQL objects.)

Does SQLJ support connection objects obtained from JDBC Connection Pools?

In SQLJ version 8.1.7 or later you can use connections obtained from a JDBC ConnectionCache, or connection classes that wrap or delegate to Oracle JDBC connections. If you need support for this in an earlier version of SQLJ, check http://technet.oracle.com for availability of a patch.

How can I use SQLJ in middle-tier (or EJB, or XXX) environment Y?

This is easiest if the middle tier directly supports SQLJ. Although -in principle- SQLJ can be used in any environment that provides JDBC connectivity, a few issues need to be addressed in practice.

- The SQLJ runtime classes must be available in the environment.
- Obtaining connections. If you can use the Oracle JDBC driver in the environment, this is straightforward. If the environment uses a non-Oracle JDBC driver, then you establish and use SQLJ connection contexts as follows. (You can supply the DefaultContext constructor with an existing connection.)
import sqlj.runtime.ref.DefaultContext;
...
<load/register JDBC driver, if necessary>
DefaultContext ctx = new DefaultContext(...);
#sql [ctx] { ..SQL statement.. };
- If you do not use an Oracle JDBC driver, then add the following flag to your sqlj command line:
-profile=false. This omits Oracle customization and makes the .ser file smaller. In this case you can also remove the whole oracle.* hierarchy from runtime.zip.
Also remember that you cannot use any features specific to Oracle JDBC or another vendor's JDBC, unless you use a vendor-specific SQLJ runtime and customization step.
- You need to ensure that the .ser files get deployed alongside the class files into the environment. Or you can use the -ser2class option during translation and then deploy .class files.
- The main question is whether the deployment tool has any knowledge about .sqlj files - it may only care about .java files. In this case you would have to translate all .sqlj files (and their corresponding .ser files) into .java files before deploying them into the environment. This can be accomplished as follows.
(a) run SQLJ over the .sqlj source with the -compile=false option. This produces .java files.
(b) turn the .ser files into .java files by running
java sqlj.runtime.profile.util.SerProfileToClass -nc *.ser
Issue the line without arguments to get an option synopsis.
You would want to do (a) and (b) via a makefile and not by hand.
(c) During deployment time and runtime you must have runtime.zip in the respective CLASSPATHS of the deployment tool and of the middle-tier environment.

Note: If you use vendor-specific features and a vendor-specific SQLJ runtime you likely have to compile the .java files and perform vendor-specific customization of .ser files between step (5a) and (5b).

Can I use host variables in SQLJ DDL statements?

Is it possible to use host variables to substitute values into a SQLJ DDL Statement, such as an "ALTER SEQUENCE" statement where the sequence increment is reset?

No. Oracle's SQL engine does not let you use bind variables in DDL statements. In this case you have to revert to JDBC. For example, if you are using the SQLJ default context, you could say the following: Connection conn = sqlj.runtime.ref.
DefaultContext.getDefaultContext().getConnection();
PreparedStatement ps = conn.prepareStatement
("...statement..."+increment+"...rest of stmt…");
ps.execute();
ps.close(); Using "WHERE column IN (value_list)" with a value_list of unknown size

My SQL statement has the following form.

SELECT * FROM TAB WHERE col IN (value1,value2,…)

The list value1, value2, … is a list of host variables. However, I do not know ahead of time, how many variables will be in the list. How can I write this in my SQLJ program?

You have several alternatives:

- Use JDBC and build the query string dynamically.
String nums = ...; //comma-separated list of numbers
Connection conn = DefaultContext.getDefaultContext()
.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery
("SELECT * FROM table WHERE nr IN ("+nums+")");
If you want to use the result set as a SQLJ iterator, you can do so as follows.
MySqljIterator it;
#sql it = { CAST :rs };
...
it.close(); // also closes rs
- If you have set a maximum number of different values and you do have fewer actual values, then you can use a single SQLJ statement and re-bind the last value multiple times.
For example, if there are at most 5 bind variables, you could write the following.
int a[] = new int[4];
… // populate mynumbers
#sql { SELECT * FROM tab WHERE col in (:(a[0]),:(a[1]),…};
If there are fewer than 5 actual ints, then would just repeat the same int in the rest of the array.
- Another -much less elegant- possibility is to have a different SQLJ statement for every bind variable count.

Part B. General Questions

Answers here are only intended to give you a general grasp or idea; they do not go into detail. For further information about any of these topics, please refer to the SQLJ Developer's Guide and Reference.

4. SQLJ (and JDBC) Basics

4.1 SQLJ Resources

Are there SQLJ books and other resources that would help a newcomer?

Extensive documentation on SQLJ is available either from the Oracle Technology Network (OTN) Web site (technet.oracle.com: click on "Technologies", then Java -> SQLJ & JDBC) or from the Oracle SQLJ distribution:

- the exhaustive Oracle 8i SQLJ Developer's Guide and Reference, which contains a "Getting Started" chapter that should help you to get up and running.
Notes:

- This is also available on technet.oracle.com: click on "Documentation", then "Data Servers -> Oracle8i", then "General Documentation", and finally "Oracle8i Java Developer's Documentation", which should take you to a menu with all of the Java related manuals, including SQLJ, JDBC, and JPublisher.
- Additional Java products related documentation is available at http://technet.oracle.com/docs/tech/java/sqlj_jdbc/listing.htm.

- the examples in the demo directory in the SQLJ distribution
- the primer "SQLJ: Tips, Traps, and Gems"

The OTN site also includes additional examples, articles, and discussions.

In addition, you can reference the following:

- the first SQLJ book on the market--Nirva Morisseau-Leroy, Martin K. Solomon, Gerald P. Momplaisir Oracle8i SQLJ Programming, published by Osborne/McGraw-Hill
- chapters on SQLJ programming in the following books: Client/Server Programming (Orfali, Harkey, et. al.) and Oracle8i for Dummies

Also visit the http://www.oracle.com/java Web site.

Is there an Oracle e-mail address for SQLJ questions?

sqljsup@us.oracle.com, or helpsqlj@us.oracle.com.

You can also send suggestions for modifications to this FAQ list.

Where can I find the SQLJ source code (known as the "reference implementation") that Oracle has made available freely to the public and other database vendors?

http://www.sqlj.org

Where can I download the SQLJ translator for a given platform?

SQLJ is available from the Oracle Technology Network (OTN) Web site:

http://technet.oracle.com

Click on the "Software" button, and then "Select a Utility or Driver" -> "SQLJ Translator". We provide downloads for Solaris and Windows NT. However, these versions only differ in the line termination characters used in textual files. If you are using a UNIX platform, you can adapt the sqlj/bin/sqlj shell script for your platform. For Windows platforms, we provide the sqlj\bin\sqlj.exe wrapper executable. However, this executable is only verified for Windows NT. It may not work on other Windows versions.

Why do I find information mentioning JSQL, I thought it is called SQLJ?

I found some Web pages that talk about JSQL, not SQLJ. I thought that the standard for embedding SQL in Java is called SQLJ.

You are right—it is called SQLJ. In the beginning it was called JSQL. However, the name JSQL had been trademarked by Caribou Lake Software for their JDBC driver product, which is not related in any way to SQLJ. The old information that you saw was still using the initial name before it was renamed to SQLJ.

Can SQLJ be faster than JDBC?

There are some papers which notice that SQLJ code could be faster then JDBC. How does this work, if SQLJ is nothing more than a layer on top of JDBC?

To the extent that SQLJ is a layer on top of JDBC it cannot be faster than JDBC. (Incidentally, this is the current situation of Oracle SQLJ.) However, to the extent in which SQLJ can exploit the fact that it represents static SQL statements, rather than dynamic ones, it can become faster than JDBC, for example through precompilation of SQL code, or predetermination of SQL types. In these cases the SQLJ runtime needs to be vendor-specific. A tuned SQLJ runtime can short-circuit several functions that the JDBC runtime always would have to perform dynamically at runtime, such as registration and checking of types, processing of JDBC escape sequences, other special SQL processing (for example to support scrollable result sets).

4.2 SQLJ Overview

Is SQLJ Y2K-compliant?

Yes, both the SQLJ translator and the SQLJ runtime are Y2K-compliant, presuming your Java environment is Y2K-compliant.

What are the pros and cons of choosing Java and SQLJ over C/C++?

Pros:

- a safer and more productive language
- same database API for client, server, and middle tier
- ability to write Java stored procedures in the database
- support for CORBA and EJB in all tiers, including the database
- tighter Java/SQL coupling through typed iterators
- multi-schema abstraction (through connection context types)
- full binary compatibility for all platforms, vendors, and databases (SQLJ only requires JDBC)

Cons:

- lack of support so far for parameter definitions (offline schema definition)
- poorer raw performance
- an additional step between user code and executable code - this step may be all but transparent, depending on the development environment you use

Does SQLJ implement the ANSI SQLJ specification?

Yes, although some minor features, while recognized by Oracle SQLJ, may not be supported by the Oracle JDBC drivers or Oracle database (such as the sensitivity, holdability, and returnability constants you can set in a with clause, and positioned UPDATE/DELETE/INSERT operations).

Does SQLJ implement the ISO SQLJ specification?

Yes, Oracle SQLJ 8.1.7 and later supports the ISO specification. Note that the SQLJ ISO standard requires full support for JDK 1.2 or later. Thus, in order to be fully ISO compliant you would need to use JDK 1.2 or later and translate as well as run your SQLJ program with runtime12.zip (or runtime12ee.zip). Additional features, while recognized by Oracle SQLJ, are not be supported by the Oracle JDBC drivers or Oracle database: the path and transformGroup attributes on connection contexts, as well as type map property entries of the kinds JAVA_OBJECT and DISTINCT are not supported presently by Oracle.

What software components are required to translate a SQLJ application? to run a SQLJ application?

To translate your application you need the following:

- the file translator.zip (typically in [ORACLE_HOME]/sqlj/lib) on your system and in your CLASSPATH
- one of the runtime files runtime.zip (any JDK, any JDBC driver), runtime11.zip (for JDK 1.1.x, JDBC 8.1.7), or runtime12.zip (for JDK 1.2, JDBC 8.1.7) which can typically be found in [ORACLE_HOME]/sqlj/lib) on your system and in your CLASSPATH
- For online checking, the JDBC driver classes—classes111.zip for JDK 1.1.x or classes12.zip for JDK 1.2 (also typically in [ORACLE_HOME]/jdbc/lib) on your system and in your CLASSPATH
- a Java compiler and execution environment compatible with JDK version 1.1.x or 1.2

To run your application, you need (or the end user needs) the following:

- the JDBC driver classes—classes111.zip for JDK 1.1.x or classes12.zip for JDK 1.2 on your system and in your CLASSPATH
- one of the runtime files runtime.zip (any JDK, any JDBC driver), runtime11.zip (for JDK 1.1.x, JDBC 8.1.7), or runtime12.zip (for JDK 1.2, JDBC 8.1.7) which can typically be found in [ORACLE_HOME]/sqlj/lib) on your system and in your CLASSPATH

The classes from one of the runtimeXX.zip files must be available during translation.

IMPORTANT NOTE: In SQLJ 8.1.6 and earlier there was only one runtime.zip library. Furthermore, this library was also contained in translator.zip. Starting with 8.1.7, the runtime classes have been removed from the translator library and an appropriate runtime library must now be provided separately on the CLASSPATH.

Can I use the Oracle SQLJ translator to translate an application to run against a non-Oracle SQLJ runtime?

Yes, if you do not use Oracle-specific features in your code and do not use the default Oracle customizer (for example, if you set -profile=false for translation).

Is SQLJ really database neutral?

Yes. The SQLJ translator makes minimal assumptions about the SQL dialect. We assume, for example, that you can have the following:

#sql positer = { ... SQL operation ...};

if the SQL statement begins with SELECT, but not if it begins with INSERT.

The SQL in such constructs is simply passed to the JDBC driver. If your JDBC driver and database understand the SQL dialect you embed, SQLJ doesn't complain. When semantic analysis is done on a SELECT statement in a #sql construct, SQLJ does not make assumptions that your SELECT statement syntax is SQL92.
Nothing about the SQLJ language is JDBC-specific. It can in principle be implemented with interfaces other than JDBC. The Oracle implementation of SQLJ happens to be based on JDBC.

4.3 JDBC Drivers

What should I know about the Oracle JDBC drivers?

- The OCI drivers (OCI 8 and OCI 7), included with Oracle client installations, are intended for client-side applications in an Oracle client environment. There must be an Oracle client-side installation.
- The Thin driver is 100% Java and is intended for applets; however, it can also be used for client-side applications. It does not require an Oracle client-side installation..
- The server-side internal driver (sometimes cryptically referred to as the KPRB driver) is inside the Oracle server and is used for server-side Java applications--Java stored procedures, Enterprise JavaBeans, and CORBA objects.
- The server-side Thin driver, available with Oracle 8.1.6 and later, is used to connect to a remote server from inside a server-side Java application.
- Unlike the OCI drivers, the Thin drivers only work with TCP/IP-based networks.
- The Thin drivers re-implement SQL*Net protocol in Java. As a result, all necessary packing and unpacking of data packets across the network is done in Java. Performance is therefore typically slower than with the OCI driver, which implements all of this packing and unpacking in C.

Can Oracle SQLJ be used with non-Oracle JDBC drivers?

Yes. Oracle SQLJ is based on the ANSI-standard SQLJ Reference Implementation. If you do not use Oracle-specific features and do not use the Oracle customizer (for example, if you set -profile=false for translation), then you do not have to use an Oracle JDBC driver.

4.4 SQLJ, JDBC, and JDK Versions

What are the different versions of Oracle SQLJ and how do I get them?

Version 8.1.7 | Available with the Oracle8i 8.1.7 database release or from the Oracle Technology Network (OTN) Web site (technet.oracle.com). We anticipate that it will also be available with Oracle Jdeveloper 3.2.
Version 8.1.6 | Available with the Oracle8i 8.1.6 database. Also part of Oracle JDeveloper 3.1.
Version 8.1.6 SDK Beta | Available as a patch from the OTN Web site. In particular, you can use this release to replace the 8.1.5 translator.zip file included in JDeveloper 3.0 (allowing JDeveloper to translate SQLJ applications under JDK 1.2), or you can patch SQLJ 8.0.5/7.3.4 (a.k.a. 8.1.5) to work with JDK 1.2.
Version 8.1.5 | Available with the Oracle8i 8.1.5 database release and with JDeveloper 3.0.
Versions 8.0.5 / 7.3.4 | Available from the OTN Web site. (Identical in functionality to version 8.1.5)

How do the Oracle SQLJ 8.0.5 and 7.3.4 versions differ from the 8.1.5 versions?

They don't. These versions differ in name and packaging only. Since SQLJ 8.1.5 is available with the Oracle 8.1.5 database we provide SQLJ 8.0.5/7.3.4 version for free download, so that programmers can use SQLJ in conjunction with 8.0.x or 7.3.4 JDBC drivers against an 8.0.x or 7.3.x database.

The main discrepancies to keep in mind are restrictions (and some changes) when using the 8.0.x and 7.3.x JDBC drivers:

- Oracle objects and object references are not supported.
- Oracle LOBs and ROWIDs are not supported in the Oracle 7.3.x JDBC drivers and are supported by the oracle.jdbc.driver.OracleBlob, OracleClob, OracleBfile, and OracleRowid classes in the Oracle 8.0.x JDBC drivers (as opposed to the oracle.sql.BLOB, CLOB, BFILE, and ROWID classes used in the Oracle 8.1.x or later JDBC drivers).
- The oracle.sql package (wrapper classes for SQL data) did not exist in the Oracle 8.0.x and 7.3.x JDBC drivers.

Notes:

- All Oracle SQLJ drivers support Oracle JDBC 8.0.x and 7.3.4. However, if you use SQLJ 8.1.7 or later, you need to make sure to specify runtime.zip in your CLASSPATH. (The runtime11.zip and runtime12.zip files were made to work specifically with same-version JDBC drivers.)
- We recommend that you download and use the Oracle8i SQLJ Developer's Guide and Reference for 8.0.x and 7.3.x JDBC which was written especially for JDBC 8.0.x and 7.3.x users. You can obtain it from: http://technet.oracle.com/docs/tech/java/sqlj_jdbc/listing.htm.

Which versions of Oracle JDBC and the Sun JDK does each version of Oracle SQLJ support?

Oracle SQLJ Version | Oracle JDBC versions supported | JDK versions supported
SQLJ 8.1.7 | JDBC 8.1.7, 8.1.6, 8.1.5, 8.0.x, 7.3.4 | JDK 1.2.x, 1.1.x
SQLJ 8.1.6 | JDBC 8.1.6, 8.1.5, 8.0.x, 7.3.4 | JDK 1.2.x, 1.1.x
SQLJ 8.1.5 | JDBC 8.1.5, 8.0.x, 7.3.4 | JDK 1.1.x
SQLJ 8.0.5 / 7.3.4 | JDBC 8.0.x, 7.3.4 | JDK 1.1.x

Oracle SQLJ does not support JDK 1.0.2.

Notes:

- This table applies to both the SQLJ translator and the SQLJ runtime.
- During translation, Oracle SQLJ determines which version of the Oracle JDBC driver and which version of the Oracle database are being used and automatically uses the appropriate semantics-checker. Furthermore, if you have specified the runtime12.zip file during translation (in SQLJ 8.1.7 and later), then SQLJ will generate JDK 1.2-specific code, and you will also need JDK 1.2 and runtime12.zip to run your SQLJ program.
- None of the SQLJ versions prior to SQLJ 8.1.7 will work with the 8.1.7 JDBC drivers. If you want to use 8.1.7 or later JDBC drivers with a pre-8.1.7 version of SQLJ, you need to check the SQLJ downloads at http://technet.oracle.com for availability of patches or updates.

For information about which Oracle database versions are supported by which JDBC driver versions, see the JDBC Developer's Guide and Reference or the JDBC FAQ list.

Do I need a different set of SQLJ class files depending on whether I'm running under JDK 1.1.x or JDK 1.2?

There is only a single translator.zip file for all JDK and JDBC versions. Additionally, if you are using SQLJ 8.1.7 or later, you need to select one of several runtime libraries:

- runtime.zip supports all JDBC drivers — not just the one that corresponds in version to your SQLJ version. For example, the runtime.zip file from SQLJ 8.1.7 can be used in conjunction with any one of the following JDBC versions: 7.3.4, 8.0.5, 8.1.5, 8.1.6, or 8.1.7.
- runtime11.zip supports the JDK 1.1.x environment and the same-version JDBC driver. For example, you would use the SQLJ 8.1.7 runtime11.zip together with JDK 1.1.x and the Oracle 8.1.7 JDBC driver. This runtime provides a slightly better performance and is also the recommended runtime for applets.
- runtime12.zip supports the JDK 1.2 environment and the same-version JDBC driver. For example, you would use the SQLJ 8.1.7 runtime12.zip together with JDK 1.2 and the Oracle 8.1.7 JDBC driver.
You can also use runtime12ee.zip if your SQLJ and JDBC versions match and you are running in a JDK 1.2 or later environment that provides support for the packages javax.naming and javax.sql.

If you are using SQLJ 8.1.6 or earlier, then there are just single versions of the translator.zip and runtime.zip files, for either JDK 1.1.x or JDK 1.2.

5. SQLJ Language and Programming

In the sample programs, I see the following import clauses at the beginning of the source code. What are these packages? Do I need to use the same import statements in my own SQLJ files?

import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import oracle.sqlj.runtime.*;

These packages belong to the standard JDBC API (java.sql.*) and the SQLJ runtime API (sqlj.runtime.*). It's often simplest to import the entire packages; however, you may choose instead to import only those classes that your application will use directly.

- Package java.sql includes:

- the SQLException class—this class and its subclasses are used for all exceptions raised by SQLJ at runtime;
- the JDBC type classes such as java.sql.Date, java.sql.ResultSet, and so on.

- Package sqlj.runtime includes the ExecutionContext class (execution contexts are discussed below) as well as wrapper classes for SQLJ stream types (BinaryStream, for example) and abstract classes that are implemented by connection context classes and iterator classes.
- Package sqlj.runtime.ref includes implementations of some of the sqlj.runtime interfaces and abstract classes—for example, the DefaultContext class (which is the only connection context class you will need if you are connecting to just one kind of schema and if you are not using the Oracle class below).
- Package oracle.sqlj.runtime contains the Oracle class, used in getting and closing connections (discussed later in this FAQ).

What's a connection "context"?

Discussion of connection contexts can get a little deep, but you can think of a connection context as a framework for a set of connections for SQL operations that use a particular set of database resources. This mechanism allows you to implement more robust semantics-checking during translation.

In SQLJ, each database connection uses its own instance of a connection context class. Each connection of a particular connection context uses an instance of a single connection context class. SQLJ provides one connection context class--sqlj.runtime.ref.DefaultContext--and you can declare additional connection context classes as needed.

Each connection context uses its own class, so has its own "type". Such "strong typing" is one of the key advantages of SQLJ, allowing for rigorous semantics-checking during translation.

The fact is, however, that many (even most) applications need only one connection context and so can get by using only the DefaultContext class without declaring any additional classes.

(In case you do want to use multiple connection context classes, see How do I create iterator classes and connection context classes? later in this FAQ.)

What's an iterator?

An iterator is SQLJ's version of a result set, but a strongly typed version--column types and (optionally) column names are specified.

You declare an iterator class for each kind of iterator you want to use (where "kind of iterator" refers to iterators with a given set of columns). As with connection contexts, this strong typing is a key advantage of SQLJ. There are two categories of iterators--"named iterators", where you specify column names as well as column types, and "positional iterators", where you specify only column types (which SQLJ references by position instead of by name).

How do I create iterator classes and connection context classes?

SQLJ provides syntax for declaring (i.e., creating) iterator classes and connection context classes.

Here is an example of a named iterator class declaration (with a String column named ename and a double column named sal):

#sql public iterator NamedIterClass (String ename, double sal);

Here is an example of a positional iterator class declaration:

#sql public iterator PosIterClass (String, sal);

And here is an example of a connection context class declaration:

#sqlj public context MyContextClass; You can declare an iterator or connection context class wherever it would be legal to define a class of any kind. When the SQLJ translator encounters an iterator declaration or connection context declaration, it inserts a class definition into the .java output file.

Note: If you declare an iterator class or connection context class at the class level or nested-class level, it might be advisable to declare it public static as opposed to simply public.

What's an execution "context"?

Execution contexts provide a means of exerting control and checking status of your SQL operations. Each execution context instance is an instance of the standard sqlj.runtime.ExecutionContext class. There is an implicit execution context instance with each connection context instance, but you can explicitly create and use execution context instances as well.
Examples of execution context class methods include:

- getUpdateCount(), which returns the number of rows affected by an update, insert, or delete
- setQueryTimeout(), which sets the timeout limit for your queries

Note that you can use connection context instances and execution context instances independently of each other. Statements that use the same connection context instance can use different execution context instances, and statements that use the same execution context instance can use different connection context instances.

(See the next question regarding how to specify which connection context instance and/or execution context instance to use for a given statement.)

How do I specify which connection context instance and/or execution context instance a SQLJ statement should use?

Suppose you have instantiated a connection context instance connctxt and an execution context instance execctxt. Consider the following examples.

#sql [connctxt] { ...SQL operation...};

The preceding specifies that connctxt should be used for this statement. The default execution context instance will be used.

#sql [execctxt] { ...SQL operation...};

The preceding specifies that exectxt should be used for this statement. The default connection context instance will be used.

#sql [connctxt, execctxt] { ...SQL operation...};

The preceding specifes that connctxt and exectxt should both be used (the connection context instance must precede the execution context instance when specifying both).

Where is the "Oracle" class and what does it provide?

The Oracle class is in the oracle.sqlj.runtime package for release 8.1.5 and higher and provides convenient static methods to create and close instances of the standard sqlj.runtime.ref.DefaultContext class, used for database connections.

Use Oracle.connect() to create a DefaultContext instance and establish it as your default connection.

Use Oracle.getConnection() to simply create a DefaultContext instance.

Use Oracle.close() (available in release 8.1.6 and higher) to close your default connection.

For earlier versions of Oracle SQLJ, you will have to use equivalent functionality (constructors and methods) of the standard sqlj.runtime.ref.DefaultContext class. See the SQLJ Developer's Guide and Reference for more information.

Can I use SQLJ to write multithreaded applications?

The short answer is Yes. The long answer involves connection context instances and execution context instances.

As discussed earlier, each database connection is represented by a connection context instance--an instance of the standard DefaultContext class or a user-declared connection context class. An instance of the standard ExecutionContext class can be used for SQL status and control operations. By default, each connection context instance has an implicit execution context instance; however, you can also explicitly declare and use an execution context instance.
In a multithreaded application, each thread must use its own execution context instance (that is, all SQLJ statements using a thread must use the same execution context instance, and no statements in any other threads should use that execution context instance). You can do this by declaring and specifying separate execution context instances, or by declaring and using separate connection context instances (which would satisfy the requirement, since each connection context instance has its own execution context instance).
If an execution context were shared between threads, then the results of a SQL operation performed in one thread would be visible in the other thread. If both threads are executing SQL operations, a race condition would occur in which the results of an execution in one thread would be overwritten by the results of an execution in the next thread before the first thread has processed the original results. Furthermore, if a thread attempts to execute a SQL operation using an execution context that is currently being used to execute an operation in another thread, a runtime exception is raised. To avoid such problems, each thread should use a distinct execution context whenever a SQL operation is executed on a shared connection context.
Note: SQLJ programs are subject to synchronization limitations imposed by the underlying JDBC driver implementation. If a JDBC driver mandates explicit synchronization of statements executed on the same JDBC connection, then a SQLJ program using that driver would require similar synchronization of SQL operations executed using the same connection context.

Given that SQLJ supports only static SQL, can I intermix SQLJ and JDBC statements in my source code so that I can use dynamic SQL in the same application?

Yes--you can have JDBC statements in your SQLJ source code. Furthermore, features are built into SQLJ to allow convenient interoperability between SQLJ iterators and JDBC result sets and between SQLJ connections and JDBC connections.

To create a JDBC result set rs from a SQLJ iterator iter, use the getResultSet() method of your iterator instance:

ResultSet rs = iter.getResultSet();

To create a SQLJ iterator iter from a JDBC result set rs, use a SQLJ cast statement:

#sql iter = { CAST : rs };

To create a JDBC connection instance conn from a SQLJ connection context instance ctx (inheriting the same underlying connection to the database), use the getConnection() method of your connection context instance:

Connection conn = ctx.getConnection();

To create a SQLJ connection context instance ctx from a JDBC connection instance conn (again inheriting the same underlying connection to the database), use the connection context class constructor that takes a JDBC connection instance as input:

DefaultContext defctx = new DefaultContext(conn);

(This example uses DefaultContext, the default connection context class provided with SQLJ.)

Note: Another way to use dynamic SQL in an Oracle SQLJ application is through PL/SQL, as discussed under Can SQLJ interact with PL/SQL in my source code? later in this FAQ.

6. Oracle-Specific Features

Do I need to do anything special to use Oracle-specific extensions?

No--just do a standard Oracle SQLJ installation, use an Oracle JDBC driver at translation and runtime (as is typical), and use the default settings of the Oracle SQLJ translator.

The Oracle semantics-checkers (in oracle.sqlj.checker) and Oracle customizer (in oracle.sqlj.runtime.util) are included with a standard installation. The SQLJUTL package, required for online checking of stored procedures in an Oracle database, is also included with a standard installation.

By default, when you run the translator it will use the oracle.sqlj.checker.OracleChecker semantics-checker front end, which in turn will run an Oracle semantics checker that is appropriate for your offline/online settings, JDBC driver, and database version.

Also by default, the translator will run the Oracle customizer so that your application can use Oracle-specific features at runtime.

What Oracle-specific features does Oracle SQLJ support?

Oracle SQLJ supports the following Oracle-specific types as host variables and iterator columns:

- Oracle objects, collections, and object references (the Java implementations can either be strongly typed, as produced by the Oracle JPublisher utility, or weakly typed as in the JDBC standard)
- Oracle ROWIDs
- Oracle REF CURSOR types
- Oracle LOBs (BLOBs or CLOBs) and external files (BFILEs)
- Java wrapper classes in the oracle.sql package for raw SQL data (such as the oracle.sql.CHAR class to wrap character data, the NUMBER class for numeric data, and the RAW class for raw binary data

Note: Prior to Oracle JDBC release 8.1.5, LOB support was through classes oracle.jdbc.driver.OracleBlob, OracleClob, and OracleBfile in combination with the PL/SQL DBMS_LOB package. Beginning with JDBC 8.1.5, the DBMS_LOB package is still available and supported, but the old LOB classes have been replaced with classes oracle.sql.BLOB, CLOB, and BFILE, which offer methods equivalent to the DBMS_LOB functionality.

In addition to the preceding type extensions, Oracle SQLJ offers the following extended functionality:

- extended SQLJ stream functionality (as output variables and function return values) extended result set and iterator functionality (as output variables and nested in iterator columns)
- extended BigDecimal Support (mapping to non-default SQL datatypes)
- PL/SQL anonymous blocks and stored procedure or function calls (see the next question)
- performance enhancements (SQLJ release 8.1.6 and later)--statement caching, update batching, and parameter definitions

Can SQLJ interact with PL/SQL in my source code?

Yes, and in fact this is another way (in addition to using JDBC code) to employ dynamic SQL in an Oracle SQLJ application. (Of course using PL/SQL is not a feature of standard SQLJ; your application would not be portable to other platforms.)
Within your SQLJ statements, you can use PL/SQL anonymous blocks and call PL/SQL stored procedures and stored functions, as in the following examples: Anonymous block:

#sql {
DECLARE
n NUMBER;
BEGIN
n := 1;
WHILE n <= 100 LOOP
INSERT INTO emp (empno) VALUES(2000 + n);
n := n + 1;
END LOOP;
END
};

Stored procedure call (returns the maximum deadline as an output parameter into an output host expression):

#sql { CALL MAX_DEADLINE(:out maxDeadline) };

Stored function call (returns the maximum deadline as a function return into a result expression):

#sql maxDeadline = { VALUES(GET_MAX_DEADLINE) };

Does Oracle SQLJ support PL/SQL BOOLEAN, RECORD, and TABLE types as input and output parameters?

Oracle SQLJ will support theses types as soon as the Oracle JDBC drivers do, but it is unclear when or if JDBC will support them. In the meantime, however, there are workarounds--you can create wrapper procedures that handle the data as types supported by JDBC.

For example, say that in your SQLJ application you want to call a stored procedure that takes a PL/SQL BOOLEAN input parameter. You can create a stored procedure that takes a character or number from JDBC and passes it to the original stored procedure as a BOOLEAN. If the original procedure is PROC, for example, you can create a wrapper procedure MY_PROC that takes a 0 and converts it to FALSE or takes a 1 and converts it to TRUE, and then calls PROC.

Similarly, to wrap a stored procedure that uses PL/SQL records, you can create a stored procedure that handles a record in its individual components (such as CHAR and NUMBER). To wrap a stored procedure that uses PL/SQL tables, you can break the data into components or perhaps use Oracle collection types.

Does Oracle SQLJ support the WHERE CURRENT OF construct?

Not as of release 8.1.6, though possibly in the future. As a workaround, you can explicitly select the ROWID column into your iterator, and then use WHERE ROWID=xxx in place of WHERE CURRENT OF in the UPDATE statement.

Does Oracle SQLJ support DML returning?

Not currently. As a workaround, use a PL/SQL block, as follows:

#sql {
BEGIN
UPDATE ...
RETURNING x, y, z INTO :OUT x, :OUT y, :OUT z;
END
};

Can I use the SQL object features with a JDBC 8.1.x driver against an 8.0.x database?

No. Even though the 8.1.x JDBC drivers are backward compatible to 8.0.x databases, they require an 8.1.x database to support SQL object features. In a configuration using an 8.1.x driver and 8.0.x database, you might be able to compile a SQLJ application that uses SQL objects, but it will not work at runtime.

Can I use SQLJ to return PL/SQL arrays from stored procedures?

Although SQL VARRAYs have been supported by SQLJ and JDBC, PL/SQL index tables are not supported by SQLJ or by JDBC at this time. You would have to use a PL/SQL stored procedure wrapper to convert a PL/SQL index table to of from a VARRAY or nested table to access the argument from Java.

For example, if you are trying to call procedure proc01, defined as follows:

package pack01 is
type rec01 is record(n1 number, d1 date);
procedure proc01 (r rec01);
...
end;

you can create a wrapper method as follows:

package pack01_wrapper is
procedure proc01_wrapper (n1 number, d1 date);
...
end;

package body pack01_wrapper is
procedure proc01_wrapper (n1 number, d1 date) is
r pack01.rec01;
begin
r.n1 := n1;
r.d1 := d1;
pack01.proc01;
end;
...
end;

With Oracle 8i, new object types and new collection types (VARRAYs and nested tables) are available in JDBC. Thus, your wrapper package could use an object type with the same attributes as the record, rather than "exploding" the record into individual components as shown here.

Does Oracle SQLJ support REF CURSORS?

Oracle SQLJ supports REF CURSORS along the same lines that Oracle's JDBC drivers do.

Specifically, a REF CURSOR that is a SELECT column, a function return, or an OUT parameter of a procedure can be materialized in SQLJ as a JDBC ResultSet or a SQLJ iterator instance. Currently JDBC (and SQLJ) stored procedures do not permit passing a REF CURSOR out.

7. Translation (and Compilation and Customization) Process

7.1 Basic Functionality

How do I run the SQLJ translator?

The Oracle SQLJ installation includes a front-end utility that automatically runs the Oracle SQLJ translator, your Java compiler, and the Oracle profile customizer.

For example, on Solaris you run the UNIX command-line utility sqlj:

sqlj Foo.sqlj

What are the fundamental steps in translating a SQLJ application? What is input and output during the translation process?

There are three basic steps: translation, compilation, and customization (optional). When you run the SQLJ front-end utility, by default all three steps are executed automatically.
In the translation step, the SQLJ translator processes, checks, and translates your .sqlj source file. It checks it for rudimentary semantics errors and optionally connects to a target database to verify your SQL instructions against the actual resources in the specified database schema. The translator produces the following:

- one or more .java file(s) with calls to the SQLJ runtime (the runtime, in turn, calls the chosen JDBC driver when the application is executed)
- one or more .ser serialized resource file(s) containing the application "profile(s)", which contain information about all of your SQL instructions

In the compilation step, the Java compiler (typically javac) compiles the .java file(s) output by the translator, producing .class file(s).
In the customization step, a default or specified customizer processes the .ser file(s) (profiles) to allow use of vendor-specific features.

Do I have to customize my application? Where do I get the customizer utility?

You only need to customize your application if you are using features that are specific to a particular database or JDBC driver, such as vendor-specific datatypes or performance enhancements. If you are using only standard features, then you can disable the command-line -profile flag to skip the customization step.
Vendors provide vendor-specific customizers. The Oracle customizer is provided with the Oracle SQLJ product and by default is executed automatically when you run the front-end SQLJ utility.

For basic use of SQLJ, how much do I need to know about profiles (.ser files)?

Unless you plan to get fancy, you only need to be aware of their existence and naming conventions. A profile contains all of the information about your SQL statements--commands, input parameters, and output parameters.
If your source file is Foo.sqlj, the profile will be in Foo_SJProfile0.ser. Any additional profiles would be in Foo_SJProfile1.ser, Foo_SJProfile2.ser, and so on.

You will have more than one profile for an application if you use more than one connection context class, but that is an advanced topic. Most applications use only one connection context class and therefore have only one profile. (Connection contexts are explained under What's a connection "context"? earlier in this FAQ.)

What's the difference between online semantics-checking and offline semantics-checking? What kinds of checking are done?

Online checking uses a connection to a specified database to check your SQL operations against database resources.

Both kinds of checking do the following: 1) analyze the types of Java expressions in your SQLJ executable statements; 2) categorize your embedded SQL operations (based on SQL keywords such as SELECT and INSERT).

In addition, online checking (but not offline checking) does the following: 3) analyzes your embedded SQL operations and checks their syntax against the database; 4) checks the Java types in your SQLJ executable statements against SQL types of corresponding database columns and stored procedure and function parameters.

I know I can enable online checking by giving the option -user=scott. How can I disable online checking?

Specify an empty user name: -user=

Similarly, to enable online checking for a particular connection context: -user@Ctx=scott

And to disable online checking for a particular connection context: -user@Ctx=

7.2 Java Configurations

Can I use Java compilers other than javac (the standard compiler included with the Sun JDKs)?

Yes. the SQLJ translator defaults to the standard javac compiler, but lets you specify an alternative compiler through the command-line -compiler-executable option. Any compiler you use, however, must behave as follows:

- It must return a non-zero exit code to the operating system whenever a compilation error occurs.
- When it encounters errors, the source-code line information it provides must be in either Sun javac format or Microsoft jvc format.

Additional relevant command-line options are -compiler-encoding-flag (if you don't want SQLJ to pass its encoding flag to the compiler), -compiler-output-flag (to specify a file name if the compiler output is going to a file), and -compiler-pipe-output-flag (relating to the javac.pipe.output system property and whether compiler output will go to STDERR or STDOUT).

Is it possible to use the JDK 1.0.2 version of the javac compiler to compile .java files generated by the SQLJ translator?

No. You need a Java compiler from JDK 1.1.x or 1.2.

7.3 National Language Support

Does the Oracle SQLJ translator provide NLS support?

Yes, SQLJ provides NLS support in the following areas:

- character encoding for reading and generating .sqlj and .java source files during translation, through the SQLJ translator -encoding option
- character encoding for error and status messages during SQLJ translation or when your application runs, through the Java file.encoding property
- locale for error and status messages during SQLJ translation or when your application runs, through the Java user.language property
- comprehensive globalization/multibyte character support, through support of national language character sets

Additionally, SQLJ fully supports Java's Unicode escape sequences. Naturally, you can also use Unicode characters inside any SQL code fragment. Usage of such characters may be checked during online translation.

Can I specify the encoding for SQLJ to use?

Yes. You can use the command-line -encoding option to specify the NLS encoding that the SQLJ translator will apply to .sqlj and .java files being input and .java files that it outputs. The default is whatever is in your file.encoding system property.

The translator also passes the -encoding value to the Java compiler it will use, unless you have instructed it not to do so by disabling -compiler-encoding-flag.

8. Development Environments

Can I develop and debug SQLJ programs with Oracle JDeveloper?

Yes, JDeveloper fully incorporates Oracle SQLJ.

Developing: Creating SQLJ code in JDeveloper is no different than creating Java code. SQLJ files (.sqlj) can be included in your projects as well as Java files (.java).

Compiling: When you compile a SQLJ source file (identified by the .sqlj file extension), the Oracle SQLJ translator and Oracle profile customizer are automatically invoked. Prior to compiling, you can use JDeveloper to set some of the SQLJ command-line translation options.

Debugging: SQLJ statements can be debugged in-line as your application executes, as with any Java statements. Reported line numbers map back to the original SQLJ source code (as opposed to the Java code that the translator generates).

Note: JDeveloper version 3.0 (and 2.0), were packaged with Oracle SQLJ version 8.1.5. While JDeveloper 3.0 supports JDK 1.2, Oracle SQLJ 8.1.5 does not. If you want to develop a JDK 1.2 application that uses SQLJ in JDeveloper 3.0, you need to download and apply the SQLJ 8.1.6 SDK patch release from the Oracle Technology Network (OTN) Web site (technet.oracle.com). SQLJ versions provided with JDeveloper 3.1 and higher do not have this limitation.

Can I develop and debug SQLJ programs with other IDEs such as Visual Café or Visual J++?

At this time, SQLJ is not integrated into any IDEs other than Oracle JDeveloper. It is possible, however, that it will be integrated into other IDEs in the future. The SQLJ standard incorporates a set of interfaces and APIs designed to ensure that IDE vendors can easily integrate SQLJ development and debugging capabilities.

Current IDEs provide hooks to integrate preprocessors. You may already be able to incorporate SQLJ into your development environment. Consult your IDE documentation for information.

9. Deploying SQLJ Programs

Can SQLJ be used in Java applets?

Yes. The SQLJ runtime environment consists of a thin layer of pure Java code together with the JDBC driver being used. Oracle offers the 100% Java JDBC Thin driver, which is roughly 150K compressed and can be downloaded into a client browser along with the applet. In your applet code, specify the Oracle JDBC Thin driver for your database connections. See the SQLJ Developer's Guide and Reference for more information.

Notes:

- JDK 1.1.x or higher is still required. If the end-user's browser uses an older JDK, then a plug-in or some other means of using JDK 1.1.x or 1.2 becomes necessary.
- With SQLJ 8.1.7 and higher, we are providing the SQLJ runtime11.zip class library that is well-suited for applet deployment, since it minimizes use of the Reflection API (java.lang.reflect.*). By contrast, the runtime.zip library uses reflection extensively in order to provide cross-compatibility with all Oracle JDBC drivers. The runtime11.zip library also requires a same-version JDBC driver. For example, if you use SQLJ 8.1.7 runtime11.zip in your applet, you would also use the Oracle 8.1.7 thin JDBC driver provided in classes111.zip.
- Certain SQLJ statements, such as the CAST statement, or statements that use Oracle SQLJ type extensions, such as REF CURSOR, or oracle.sql.CustomDatum types still require use of Java reflection, which may not be enabled in all browser environments.
- If your applet does not use Oracle-specific features, you may want to set -profile=false during translation so that your application is not customized. If it is not customized, then there will be no requirement for the Oracle runtime (that is, you can remove the oracle.* class hierarchy from the runtime.zip library).

Can an SQLJ Applet open a connection to a third machine?

No, this is prevented by Java applet security. However, you could use the Oracle Net8 Connection Manager product to work around this limitation. Alternatively, you may be able to use browser-specific APIs to obtain the required privileges.

For end-users, what browsers will work with SQLJ applets?

Netscape Communicator 4.x and Microsoft Internet Explorer 4.x include JDK 1.1.x and are known to work. Communicator 5.x and Internet Explorer 5.x include JDK 1.2 and are presumed to work

Netscape Navigator 3.x and Microsoft Internet Explorer 3.x use JDK 1.0.2. To use these browser versions, you must use a plug-in or some other means of employing JDK 1.1.x or above.

Can SQLJ be used in middle-tier Java applications?

Yes, middle-tier SQLJ applications can be executed in any JDK 1.1.x-compliant or 1.2-compliant Java Web server or Java application server, including the Oracle Application Server. In a middle-tier environment, SQLJ applications can use either the JDBC OCI driver or the JDBC Thin driver.

Can SQLJ be used inside servlets?

Yes. Write it as any servlet, but with the .sqlj file name extension for your source file. Then run the SQLJ translator as usual.

Can SQLJ be used inside JavaServer Pages?

Yes. When you download the Oracle JSP translator (ojsp) from the OTN Web site (technet.oracle.com), you will also receive a SQLJ translator.zip file.

The JSP translator accomplishes the following for source files with the .sqljsp extension:

- Generates a .sqlj file. (If you look at the .sqlj file, you will see that the HTML tags are gone but the #sql constructs are still there.)
- Calls the SQLJ translator on the .sqlj file.

Can SQLJ applications work across firewalls?

Yes--there are no firewall limitations specific to SQLJ. Because the runtime environment for a SQLJ application consists of a thin layer of pure Java code on top of a JDBC driver, a SQLJ application will work with any firewall with which the chosen JDBC driver will work.

The Oracle JDBC OCI driver and Thin driver can work in either an intranet or extranet setting. In an extranet deployment, the drivers can be used with firewalls which have been SQL*Net certified.

The following firewalls have been certified with SQL*Net:

- stateful inspection firewalls from Checkpoint, SunSoft, and Cisco Systems
- proxy-based firewalls from Milkyway Networks, Trusted Information Systems, Raptor, Secure Computing Corporation, and Global Internet

For more information, see the JDBC Developer's Guide and Reference.

Can I use operating system authentication to connect from SQLJ?

You can logon using external credentials with the OCI driver by passing in nulls as username and password.

10. Running SQLJ Programs

What debugging support does SQLJ offer?

At the simple end of the spectrum are the translator -linemap option and the server-side debug option.

The -linemap option instructs the SQLJ translator to map line numbers in the SQLJ source code to line numbers in the generated .class file (the .class file produced by the compiler during compilation of the .java file that was generated by the translator). This way, you can trace runtime errors to lines of code in your SQLJ source file.

If you are using the SQLJ translator that is embedded in the server, there is no -linemap option but the same functionality is implemented automatically. You can also use the server-side debug option, which is similar in nature to the -g option of the javac compiler.

At the more complex end of the spectrum is a special profile customizer known as the "auditor installer"--sqlj.runtime.profile.util.AuditorInstaller. This customizer inserts debugging statements--called auditors--into profiles that you specify on the SQLJ command line. The debugging statements will execute during runtime as you execute the application, displaying a trace of method calls and values returned. (Some of the questions under "Basic Functionality" earlier in this FAQ touch on profiles and customizers.)

The -P-debug command-line option will instruct SQLJ to run the auditor installer.

SQLJ debugging support is also built into Oracle JDeveloper. (See Can I develop and debug SQLJ programs with Oracle JDeveloper? earlier in this FAQ.)

If I translate an application with one version of the Oracle SQLJ translator, will I be able to run the application against a future version of the Oracle SQLJ runtime?

Yes, Oracle will maintain this sort of backwards compatibility. For example, an application that you translate with the 8.1.5 version of the translator will run against the 8.1.6 (or, eventually, the 8.2) version of the SQLJ runtime.

Naturally, you must also consider Java version compatibilities. For example, you may not be able to run a particular JDK 1.2 application in a JDK 1.1 environment.