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).
Related
This question already has answers here:
Connect Java to a MySQL database
(14 answers)
Closed 1 year ago.
I am currently making a backend reporting system (for a voting system assignment) using Java on VS Code, I am connecting to a MySQL database using the JDBC library in order to do calculations and stats and so on. So what happens is that once I create a project file and include the mysql-connector-java-8.0.25.jar in the referenced libraries, I can connect to the DB and retrieve data from the tables just fine, but after a few executions I no longer get output and it shows me the error "java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver".
Can anyone tell me why this is happening and how to fix this? There are no changes that I know of taking place in the Environment Variables (at least from what I can see in Windows path list) unless something is being overwritten somewhere or that it's a bug of some sort. Any advice would be greatly helpful, I've been unable to figure this out all day
This is what my ReportSystem.java looks like...
import java.sql.*;
public class ReportSystem
{
public static void main(String[] args)
{
//Test driver connection/registration
try
{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ElectionDB","<username>","<password>");
Statement stmt = conn.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM ElectionDB.Votes");
int typeColumn = 1;
int districtColumn = 2;
//Output results line by line
while(result.next())
{
System.out.println(result.getString(typeColumn));
System.out.println(result.getString(districtColumn));
}
//Remember to close the connection
conn.close();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
My file structure as in the directory is as follows:
ReportSystem
>src > ReportSystem.java
> ReportSystem.class
>lib
>.vscode > settings.json
The JRE system library used is: [jdk-16.0.1]
The Referenced Libraries contains: [mysql-connector-java-8.0.25.jar]
Screenshot for context Project Setup in VS Code
I'm able to get result after running code 20 times continuously by clicking the run button. The only difference is the JDBC connection string, which is copied directly by right clicking the MYSQL connection:
So in my project, the connection string is like:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/?user=username","<username>","<password>");
OR
You could try
String url="jdbc:mysql://localhost:3306/ElectionDB?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"
For your reference, OS Infomation:
MySQL: 8.0 // mysql-connector-java-8.0.25.jar
VSCode: 1.56.2 //
java.home: JDK16 // Debugger for Java: 0.33.1
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
In my application, I need a Java process to run by a trigger-- whenever a change has been made to field dateLastChanged of TrackTable, that process should fire.
I followed through these steps for this:
1.) compiled the following code:
public class UDFClass {
public static int udf(String coCode, String tNo) {
int result = 1;
String command = "<the java command here>"; // line-K
try {
Runtime.getRuntime().exec(command);
} catch (IOException e) {
result = 0;
}
return result;
}
}
2.) put UDFClass.class under sqllib/function directory of the DB2 installation
3.) ran the following function on db2. It ran successfully:
create or replace function theresUpdate(cocode varchar(4), tnumber varchar(20))
returns integer
external name 'UDFClass.udf'
language Java
parameter style Java
not deterministic
no sql
external action
4) successfully ran the following trigger on DB2:
create or replace trigger notify
after update of dateLastChanged
or insert
on TrackTable
REFERENCING new as newRow
for each row
not secured
begin
update performanceParams set thevalue = theresUpdate(newRow.cocode, newRow.tnumber) where thekey = 'theDate';
end
To test, i update TrackTable as follows:
update TrackTable set dateLastChanged = dateLastChanged + 10 where tNumber = ‘21123’
this update query runs successfully without the trigger in (4) above. However, with this trigger, i get the following error:
An error occurred in a triggered SQL statement in trigger "LTR.NOTIFY". Information returned for the error includes SQLCODE "-4301", SQLSTATE "58004" and message tokens "1".. SQLCODE=-723, SQLSTATE=09000, DRIVER=4.18.60
This page indicates that it’s a Java related error. However, the command in line-K of the Java code in (1) is running all fine when I invoke it from the Linux command line.
I tried some other variations of the function in (3)-- deterministic rather than not deterministic, not fenced.
I’m using DB2 version 10.5.
Please help!
I am trying to create a program that will read a database and output it. I have followed the tutorial at http://www.codeproject.com/Articles/35018/Access-MS-Access-Databases-from-Java. But when I run my program, nothing happens. Not even errors...
I probably have missed something, but I don't know what it could be. Here's my code:
import java.sql.*;
public class ReadDB {
public static void ReadDB() {
try{
//Source: http://www.codeproject.com/Articles/35018/Access-MS-Access-Databases-from-Java
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=ratingdb.accdb;";
Connection conn = DriverManager.getConnection(database, "", "");
Statement s = conn.createStatement();
//Read Table
String selTable = "SELECT * FROM RATINGS";
s.execute(selTable);
ResultSet rs = s.getResultSet();
while((rs!=null) && (rs.next()))
{
System.out.println(rs.getString(1) + " : " + rs.getString(2));
}
s.close();
conn.close();
} catch(Exception e){
System.out.println ("Unable to connect to the database");
System.out.println ("Exception: " + e.getMessage());
}
}
}
After Black Panther's comment, I got this error:
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver]General error Unable to open registry key Temporary (volatile) Ace DSN for process 0x13f4 Thread 0x1204 DBC 0x42170d4
EDIT: A new error occured: Exception: [Microsoft][ODBC Microsoft Access Driver] Not a valid file name. Does this mean that the driver I use does not exist?
Even if it throws the exceptions you wouldn't be able to see them because you have handled the errors in a wrong way. You shouldn't just catch the exceptions and move on. That defies the whole concept of exception handling.
You should do something like this for your exceptions to be printed in the console.
try {
//code that throws exceptions
} catch(Exception e) {
e.printStackTrace(); //prints the error to the console and you missed it
}
EDIT:
It seems you are having some permissions issue.
An Excerpt from the site http://support.sas.com/kb/40/228.html
This problem occurs for several reasons, including not having permissions on an ODBC registry key. In such a case, change the permissions on the registry key as follows:
Start the registry editor using the regedit command:
select Start ► Run and enter regedit.
If your SAS PC Files Server is on a 64-bit machine, expand the following key:
HKEY_LOCAL_MACHINE ► SOFTWARE ► WOW6432NODE ► ODBC.
If your SAS PC Files Server is on a 32-bit machine, expand the following key:
HKEY_LOCAL_MACHINE ► SOFTWARE ► ODBC.
Right-click the ODBC folder and select Permissions.
Make sure that the logon ID that is running the SAS process has full control.
The problem might also occur due to older ODBC drivers from Microsoft, particularly from Office 2007.
To install the newer ODBC drivers, go to Microsoft Access Database Engine 2010 Redistributable.
If you have 32-bit Microsoft Office, download the AccessDatabaseEngine.exe file.
Download the other ODBC driver only if you have 64-bit version of Microsoft Office.
If you are trying to create an .mdb file and use it then do this
go to
File -> Options -> General, and set the Default File Format to Access 2002-2003
And change your database URL to
"jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=ratingdb.mdb;";
to use the .mdb file.
To use an .accdb file try doing this,
"jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=ratingdb.accdb;";
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.