I'm trying to load some java stored procedures into an Oracle 10g database through JDBC. The statement I'm executing is -
CREATE OR REPLACE JAVA SOURCE NAMED "test.Test" AS
package test;
public class Test {
public static String myMethod(String a) {
return a;
}
};
Running this through TOAD works just fine, but when running through my JDBC client gives the following error -
Exception in thread "Thread-3" java.lang.NullPointerException
at oracle.jdbc.driver.T4C8Oall.getNumRows(T4C8Oall.java:728)
at oracle.jdbc.driver.T4CStatement.execute_for_rows(T4CStatement.java:478)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1028)
at oracle.jdbc.driver.OracleStatement.executeUpdate(OracleStatement.java:1451)
at ejsdal.CreateDBJavaSQL.executeScript(CreateDBJavaSQL.java:23)
at ejsdal.OperationController.run(OperationController.java:182)
I'm using the java.sql.Statement's "executeUpdate" passing the string in the first code block.
It is possible to load java source through JDBC?
Figured it out - need to set the
statement.setEscapeProcessing(false);
before executing the update. This is because the Java source file's { and } characters are misinterpreted as procedure call syntax by the JDBC driver.
Related
I have been trying to call a java jar file from DB2 stored procedure as external jar.
Below is my external jar file code.
package connection;
public class Connect {
static Connection con = null;
static Statement stmt = null;
public static void main(String[] args) throws SQLException {
javastp("v1");
}
public static void javastp( String name) throws SQLException{
try {
con = DriverManager.getConnection( "jdbc:default:connection" );
stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO SCHEMA_NAME.TEST(NAME, FLAG) VALUES ('"+name+"',true) ");
}catch (Exception e) {
// ...
}finally {
//Close open resources
if (stmt != null) stmt.close();
if (con != null) con.close();
}
}
}
i install it using below command in db2 server
db2 call sqlj.install_jar('file:E:/jarpath../jarname.jar','jarname',0);
Below is the stored procedure for DB2 external jar.
CREATE OR REPLACE PROCEDURE SCHEMA_NAME.PROC6()
LANGUAGE java
PARAMETER STYLE java
FENCED
EXTERNAL NAME 'jarname:connection.Connect.main'
The stored procedure executes successfully without errors.
But when i try to call the stored procedure using below,
CALL SCHEMA_NAME.PROC6()
i get the below error
SQL Error [38503]: A stored procedure process has been terminated abnormally. Routine name: "SCHEMA_NAME.PROC6". Specific name: "SQL201016144125554".. SQLCODE=-1131, SQLSTATE=38503, DRIVER=4.8.86
The java jar works fine when executed directly in the command prompt and the records are being inserted into the table, but i cant seem to figure out why the external stored procedure gives me error when i try to call it that way.
Can somebody here please help me out as am stuck on this since a very long time and i have no background of DB2.
the db2level command gives the below output:
DB21085I This instance or install (instance name, where applicable: "DB2")
uses "64" bits and DB2 code release "SQL10058" with level identifier
"0609010E".
Informational tokens are "DB2 v10.5.800.381", "s160901", "IP24000", and Fix
Pack "8".
Product is installed at "C:\PROGRA~1\IBM\SQLLIB" with DB2 Copy Name "DB2COPY1".
Linux Suse db2 version 11.1.2
Database server = DB2/LINUXX8664 11.1.2
The log is as below:
2020-10-20-09.24.56.746633+330 I4952989679E1230 LEVEL: Error
PID : 31693 TID : 140179352315648 PROC : db2sysc 0
INSTANCE: NODE : 000 DB :
APPHDL : APPID:
AUTHID : HOSTNAME:
EDUID : 2768 EDUNAME: db2agent () 0
FUNCTION: DB2 UDB, routine_infrastructure, sqlerWaitForFencedInvocation, probe:12115
MESSAGE : ZRC=0xFFFFFB38=-1224
SQL1224N The database manager is not able to accept new requests,
has terminated all requests in progress, or has terminated the
specified request because of an error or a forced interrupt.
Error SQL1131N has the following description
The DB2 architecture is designed so that applications run in a different address space than the database server. Running applications in a different address space prevents application programming errors from overwriting database manager internal buffers or files, and prevents application errors from crashing the database manager. The fenced mode process (db2fmp) is responsible for executing fenced stored procedures and user-defined functions in a different address space than the database server.
This message is returned when the db2fmp process terminates abnormally while running the named routine. The db2fmp process could have terminated abnormally for many reasons, including the following reasons:
There was a coding error, such as division by zero or an out-of-bounds pointer reference, in the implementation of the stored procedure or user-defined function that the db2fmp process was executing.
Another process terminated the db2fmp process using a signal, such as the termination signal SIGTERM.
SQLJ.INSTALL_JAR failed while installing a Java routine because the fenced user does not have permission to create or write to the necessary directories on the server.
Db2 is unforgiving when you make mistakes with external non-SQL code, in this case, it just throws an exception and expects you to sort it out.
Only use java for Db2 stored procedures when there is a compelling reason to NOT use SQL PL procedures.
You have these mistakes
You cannot use a main() for a Db2 java stored procedure entry point
The stored procedure entry point should be in your case the javastp() method
The EXTERNAL NAME clause in the DDL must not reference main() but should use javastp instead
The parameters in the create procedure line must match those of the method
in number and type and sequence. (In your case that is (IN name varchar(255) or similar).
I have loaded the class file of a java program (that fetches data from an excel file and pushes it to a database and making connection to database using values from properties file) into the SQL developer.
Now I am trying to invoke the main method of the class file as below:
CREATE OR REPLACE PROCEDURE dataset
AS LANGUAGE JAVA
NAME 'data_design_1.main()';
It gives the following error:
Error: PL/SQL: Compilation unit analysis terminated
Error(3,1): PLS-00311: the declaration of "data_design_1.main()" is incomplete or malformed
Could anyone tell me why is this error occurring??
Thank you.
I think that the declaration of your main is this
public static void main(String[] args)
so the declaration of your PL/SQL wrapper is wrong.
You haven't posted the Java code
Maybe I'm wrong.
Language: Java
Program: Connecting to a database
Question: I'm trying to connect the sqlite database by following TutorialsPoint tutorial but I keep getting the main class not found error.
Implementation: My code is below followed by my terminal commands and folder structure screenshot. But basically all my files are located in one folder including the sqlite jar file.
import java.sql.*;
public class Test {
public static void main(String[] args) {
Connection c = null;
try{
Class.forName("com.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:test.db");
} catch(Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(0);
}
System.out.println("Opened database successfully!");
}
}
Terminal Commands
javac Test.java
java -classpath ".;sqlite-jdbc-3.23.1.jar" Test
Your problem was that you're explicitly trying to load the class com.sqlite.JDBC, whereas the driver class name must've changed somewhere along the way.
JDBC Type 4 drivers have added cleverness which allows you to specify only the connection URL, and the driver loads itself based on the beginning (i.e. jdbc:sqlite). No need to wonder what was the driver class's name.
Rant unrelated to the issue at hand:
Unfortunately people read old tutorials written by less than experts, so we constantly see Class.forName() being used, as well as the more serious issue, which is using Statement instead of PreparedStatement.
My classpath option was incorrect. I was on linux and was trying to do:
java -classpath ".;sqlite-jdbc-3.23.1.jar" Test
the correct way was
java -classpath ".:sqlite-jdbc-3.23.1.jar" Test
colon not semicolon. Unfortunately now it's giving me and error" ClassNotFoundException: com.sqlite.JDBC;
I will look into this.
Thanks for the comments which helped me find the error
I'm currently using Oracle 12c Standard Edition.
I have created a Java class and compiled it using the JDK 6 (because Oracle 12c has default support for JDK 6). The class goes as following:
import java.io.File;
import java.io.IOException;
public class Run_Batch
{
public static void main(String[] args) throws InterruptedException, IOException
{
Runtime.getRuntime().exec("cmd /c start execute_r.bat", null, new File("C:/Users/Admin/workspace/"));
}
}
My goal is to create a Java stored procedure, which I can call through Oracle using PL/SQL. The Java stored procedure would call the main() method from the Run_Batch class, spawn a new OS process (presumably) and run the execute_r.bat batch file found in the C:/Users/Admin/workspace directory. After that, the .bat file would run a .R file, which would create a new table inside the Oracle database, using the ROracle library.
The code for the .bat file goes as follows:
path
Rscript run_signal.R
pause
exit
Both the .bat and the .R files are found inside of the C:/Users/Admin/workspace directory.
The code for the .R file is:
library(ROracle)
drv <- dbDriver("Oracle")
host <- "win-2h3vud23lai"
port <- 1521
sid <- "oracle"
connect.string <- paste(
"(DESCRIPTION=",
"(ADDRESS=(PROTOCOL=tcp)(HOST=", host, ")(PORT=", port, "))",
"(CONNECT_DATA=(SID=", sid, ")))", sep = "")
con <- dbConnect(drv, username = "C##USER",
password = "password",dbname=connect.string)
createTable <- "CREATE TABLE IRIS_TABLE (time_stamp VARCHAR2(55),
category VARCHAR2(15), type VARCHAR2(55),
servername VARCHAR2(15), code VARCHAR2(15), msg VARCHAR2(255))"
I've followed the small Oracle tutorial on Java stored procedure and I have already compiled my Run_Batch.java file using javac and loaded the Java file into the database using:
loadjava -user C##USER/password Run_Batch.class
After that, I have entered SQLPLUS.exe and I have created both a package and a package body:
CREATE OR REPLACE PACKAGE run_r_package AS
PROCEDURE run_test_batch ( ARGUMENTS VARCHAR2 )
END;
CREATE OR REPLACE PACKAGE BODY run_r_package AS
PROCEDURE run_test_batch( ARGUMENTS VARCHAR2)
AS LANGUAGE JAVA
NAME 'Run_Batch.main(java.lang.String[])';
END;
I have created the package with the package body successfully.
However, I'm not able to run the Java stored procedure nor to call the run_r_batch() procedure. Whenever I try to do so I get errors to undefined classes, undefined errors or weird exception names.
I haven't been able to make the Oracle documentation (found here: https://docs.oracle.com/database/121/JJDEV/chseven.htm#JJDEV13283) to work.
Using the sqlplus, if I do:
CALL run_test_batch('123');
I get the following error:
ORA-06576: not a valid function or procedure name
if, instead of using CALL, I use EXECUTE, as follows:
EXECUTE run_test_batch('123');
I get the following error:
ORA-06550: line 1, column 7
PLS-00201: the identifier 'run_test_batch' must be declared
ORA-06550: line 1, column 7
PL/SQL: statement ignored.
If I use SQL Developer instead of SQLPLUS, after I connect to my user C##USER with my password, I try to run the procedure using the following code:
BEGIN
run_r_package.run_test_batch('');
END;
the first time I got the message:
Execution terminated due to unresolved exception:
ORA-29532: java call terminated by uncaught java exception: java.lang.ExceptionInInitializerError
ORA-06512: in "C##USER.RUN_R_PACKAGE", line 2
But now, when I tried to run the code again I get a different message:
ORA-29532: java call terminated by uncaught java exception: java.lang.NoClassDefFoundError
ORA-06512: in "C##USER.RUN_R_PACKAGE", line 2
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
EDIT
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
I tried to refine my class and run a simple Windows command as suggested in the comments.
The new Java file goes as follows:
import java.io.File;
import java.io.IOException;
public class Run_Batch
{
public static void proc() throws InterruptedException, IOException
{
Runtime.getRuntime().exec("cmd /c cmd.exe", null, null);
}
}
My package creation code has been modified as following:
CREATE OR REPLACE PACKAGE run_r_package AS
PROCEDURE run_test_batch
END;
CREATE OR REPLACE PACKAGE BODY run_r_package AS
PROCEDURE run_test_batch
AS LANGUAGE JAVA
NAME 'Run_Batch.proc()';
END;
If I use botch CALL or EXECUTE in sqlplus.exe I get the same error saying run_test_batch must be declared.
If I try to call the procedure via SQL Developer like this:
BEGIN
run_r_package.run_test_batch;
END;
I get the errors:
ORA-29531: no method proc in class Run_Batch
ORA-06512: en "C##USER.RUN_R_PACKAGE", line 2
ORA-06512: en line 2
While the referenced question is similar it speaks to putting the source code into the database not the class, also I would like to use the TOAD utilities to accomplish this.
So as proof of concept I have been attempting to load a java class into an Oracle 12c Database and access it via an Oracle function.
I opened Eclipse and created new project Hello with class Hello:
public class Hello {
public static String world()
{
return "Hello world";
}
}
I compiled it and now on my client I have
C:\Users\me\workspaces\Hello\bin\Hello.class
I opened up TOAD for an oracle 12c database, then I went to utilities / Java Manager and loaded my class:
TOAD says it successfully loaded. However, I'm not sure if it did.
Next, I went into the TOAD editor and created a function:
CREATE OR REPLACE function "DIR\KBD0010".helloworld RETURN VARCHAR2 AS
LANGUAGE JAVA NAME 'Hello.world () return java.lang.string';
Then I attempted to select it with a sql query:
select helloworld()
from dual;
And then I am getting:
ORA-29540: class Hello does not exist