The Java external environment

SQL Anywhere includes support for Java stored procedures and functions. A Java stored procedure or function behaves the same as a SQL stored procedure or function with the exception that the code for the procedure or function is written in Java and the execution of the procedure or function takes place outside the database server (that is, within a Java Virtual Machine environment). It should be noted that there is once instance of the Java VM for each database rather than one instance per connection. Java stored procedures can return result sets.

There are a few prerequisites to using Java in the database support:

  1. A copy of the Java Runtime Environment must be installed on the database server computer.

  2. The SQL Anywhere database server must be able to locate the Java executable (the Java VM).

To use Java in the database, make sure that the database server is able to locate and start the Java executable. Verify that this can be done by executing:

START EXTERNAL ENVIRONMENT JAVA;

If the database server fails to start Java then the problem probably occurs because the database server is not able to locate the Java executable. In this case, you should execute an ALTER EXTERNAL ENVIRONMENT statement to explicitly set the location of the Java executable. Make sure to include the executable file name.

ALTER EXTERNAL ENVIRONMENT JAVA
  LOCATION 'java-path';

For example:

ALTER EXTERNAL ENVIRONMENT JAVA
  LOCATION 'c:\\jdk1.6.0\\jre\\bin\\java.exe';

Note that the START EXTERNAL ENVIRONMENT JAVA statement is not necessary other than to verify that the database server can start the Java VM. In general, making a Java stored procedure or function call starts the Java VM automatically.

Similarly, the STOP EXTERNAL ENVIRONMENT JAVA statement is not necessary to stop an instance of Java since the instance automatically goes away when the all connections to the database have terminated. However, if you are completely done with Java and you want to make it possible to free up some resources, then the STOP EXTERNAL ENVIRONMENT JAVA statement decrements the usage count for the Java VM.

Once you have verified that the database server can start the Java VM executable, the next thing to do is to install the necessary Java class code into the database. Do this by using the INSTALL JAVA statement. For example, you can execute the following statement to install a Java class from a file into the database.

INSTALL JAVA 
NEW 
FROM FILE 'java-class-file';

You can also install a Java JAR file into the database.

INSTALL JAVA 
NEW
JAR 'jar-name'
FROM FILE 'jar-file';

Java classes can be installed from a variable, as follows:

CREATE VARIABLE JavaClass LONG VARCHAR;
SET JavaClass = xp_read_file('java-class-file')
INSTALL JAVA 
NEW
FROM JavaClass;

Java JAR files can be installed from a variable, as follows:

CREATE VARIABLE JavaJar LONG VARCHAR;
SET JavaJar = xp_read_file('jar-file')
INSTALL JAVA 
NEW
JAR 'jar-name'
FROM JavaJar;

To remove a Java class from the database, use the REMOVE JAVA statement, as follows:

REMOVE JAVA CLASS 'java-class'

To remove a Java JAR from the database, use the REMOVE JAVA statement, as follows:

REMOVE JAVA JAR 'jar-name'

To modify existing Java classes, you can use the UPDATE clause of the INSTALL JAVA statement, as follows:

INSTALL JAVA 
UPDATE
FROM FILE 'java-class-file'

You can also update existing Java JAR files in the database.

INSTALL JAVA 
UPDATE
JAR 'jar-name'
FROM FILE 'jar-file';

Java classes can be updated from a variable, as follows:

CREATE VARIABLE JavaClass LONG VARCHAR;
SET JavaClass = xp_read_file('java-class-file')
INSTALL JAVA 
UPDATE
FROM JavaClass;

Java JAR files can be updated from a variable, as follows:

CREATE VARIABLE JavaJar LONG VARCHAR;
SET JavaJar = xp_read_file('jar-file')
INSTALL JAVA 
UPDATE
FROM JavaJar;

Once the Java class is installed in the database, you can then create stored procedures and functions to interface to the Java methods. The EXTERNAL NAME string contains the information needed to call the Java method and to return OUT parameters and return values. The LANGUAGE attribute of the EXTERNAL NAME clause must specify JAVA. The format of the EXTERNAL NAME clause is:

EXTERNAL NAME 'java-call' LANGUAGE JAVA
java-call :
[package-name.]class-name.method-name method-signature
method-signature : 
( [ field-descriptor, ... ] ) return-descriptor
field-descriptor and return-descriptor :
Z 
| B 
| S 
| I 
| J 
| F 
| D 
| C 
| V 
| [descriptor 
| Lclass-name;

A Java method signature is a compact character representation of the types of the parameters and the type of the return value. If the number of parameters is less than the number indicated in the method-signature then the difference must equal the number specified in DYNAMIC RESULT SETS, and each parameter in the method signature in excess of those in the procedure parameter list must have a method signature of [Ljava/SQL/ResultSet;.

The field-descriptor and return-descriptor have the following meanings:

Field type Java data type
B byte
C char
D double
F float
I int
J long
L class-name; an instance of the class class-name. The class name must be fully qualified, and any dot in the name must be replaced by a /. For example, java/lang/String
S short
V void
Z Boolean
[ use one for each dimension of an array

For example,

double some_method(
  boolean a,
  int b,
  java.math.BigDecimal c,
  byte [][] d,
  java.sql.ResultSet[] rs ) {
}

would have the following signature:

'(ZILjava/math/BigDecimal;[[B[Ljava/SQL/ResultSet;)D'

The following procedure creates an interface to a Java method. The Java method does not return any value (V).

CREATE PROCEDURE insertfix() 
EXTERNAL NAME 'JDBCExample.InsertFixed()V' 
LANGUAGE JAVA;

The following procedure creates an interface to a Java method that has a String ([Ljava/lang/String;) input argument. The Java method does not return any value (V).

CREATE PROCEDURE InvoiceMain( IN arg1 CHAR(50) )
EXTERNAL NAME 'Invoice.main([Ljava/lang/String;)V'
LANGUAGE JAVA;

The following procedure creates an interface to a Java method Invoice.init which takes a string argument (Ljava/lang/String;) , a double (D), another string argument (Ljava/lang/String;), and another double (D), and returns no value (V).

CREATE PROCEDURE init( IN arg1 CHAR(50),
                       IN arg2 DOUBLE, 
                       IN arg3 CHAR(50), 
                       IN arg4 DOUBLE) 
EXTERNAL NAME 'Invoice.init(Ljava/lang/String;DLjava/lang/String;D)V'
LANGUAGE JAVA

For more information about calling Java methods, see Accessing methods in the Java class.

For more information on returning result sets, see Returning result sets from Java methods.

The following Java example takes a string and writes it to the database server messages window:

import java.io.*;

public class Hello
{
    public static void main( String[] args )
    {
        System.out.print( "Hello" );
               for ( int i = 0; i  < args.length; i++ )
                   System.out.print( " " + args[i] );
        System.out.println();
    }
}

The Java code above is placed in the file Hello.java and compiled using the Java compiler. The class file that results is loaded into the database as follows.

INSTALL JAVA 
NEW 
FROM FILE 'Hello.class';

Using Interactive SQL, the stored procedure that will interface to the method main in the class Hello is created as follows:

CREATE PROCEDURE HelloDemo( IN name LONG VARCHAR ) 
EXTERNAL NAME 'Hello.main([Ljava/lang/String;)V'
LANGUAGE JAVA;

Note that the argument to main is described as an array of java.lang.String. Using Interactive SQL, test the interface by executing the following SQL statement.

CALL HelloDemo('SQL Anywhere');

If you check the database server messages window, you will find the message written there. All output to System.out is redirected to the server messages window.

For additional information and examples on using the Java in the database support, refer to Java support in SQL Anywhere.