質問

I am currently working with IBM DB2 v10.1 Enterprise Edition. I need to create a Java Stored Procedure, that connects to a remote TCP Server (again in Java). Therefore, I have coded the following class in Java (file name is SystemClient.java):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class SystemClient {

    public static void callSystemML(String serverIPAddress, Integer serverPort, 
            String script, String args) throws IOException, ClassNotFoundException {

         Socket socket = new Socket(serverIPAddress, serverPort);
         PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
         BufferedReader reader = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));
         writer.println(script + "|" + args);
         String line = reader.readLine();
         writer.close();
         reader.close();
         socket.close();
     }

}

So, I create a Jar file for the class above with the following commands:

javac SystemClient.java
jar cvf SystemClient.jar SystemClient.class

and then from the DB2 command line I invoke the following command:

db2 "call sqlj.install_jar('file:/path/to/jar/SystemClient.jar','SYSTEM_ML_CLIENT_JAR', 0)

After that, I verify that my JAR has been correctly registered by executing:

db2 "select jar_id from sysibm.sysjarcontents"

and checking that the new Jar has been registered. Then, I have the following script for creating my SQL Stored Procedure (file name: create-system-call.sql):

CREATE OR REPLACE PROCEDURE DB2INST1.ML_CLIENT_CALL(
    IN serverIPAddress VARCHAR(255), 
    IN serverPort INTEGER, 
    IN script VARCHAR(255), 
    IN args VARCHAR(255))
LANGUAGE java
PARAMETER STYLE java 
FENCED THREADSAFE 
EXTERNAL NAME 'SYSTEM_ML_CLIENT_JAR:SystemClient.callSystemML(java.lang.String, java.lang.Integer, java.lang.String, java.lang.String)';

And again, I execute the following script to verify that my procedure has been created:

db2 "select routinename from syscat.routines where language='JAVA'"

and I see the name of ML_CLIENT_CALL there. The problem arises when I try to call the new procedure from command line with the following command:

db2 "call ml_client_call('localhost',4444,'sample.dml','someargs')"

That is when I receive the following output:

SQL4306N  Java stored procedure or user-defined function 
"DB2INST1.ML_CLIENT_CAL", specific name "SQL140514162506200" could not call 
Java method "callSystemML", signature "(Ljava/lang/Str".  SQLSTATE=42724

I check the ~/sqllib/db2dump/db2diag.log for the precise error and I see the following:

2014-05-15-09.17.23.080944-420 I944034E848           LEVEL: Warning
PID     : 2987                 TID : 139759180494592 PROC : db2fmp (
INSTANCE: db2inst1             NODE : 000
APPID   : *LOCAL.db2inst1.140515154559
HOSTNAME: oxiro
FUNCTION: DB2 UDB, BSU Java support, sqlejCallJavaRoutine_dll, probe:130
MESSAGE : JNI GetMethodID failed.  class:
DATA #1 : Hexdump, 81 bytes
0x00007F1C3AD73480 : 2F68 6F6D 652F 6462 3269 6E73 7431 2F73    /home/db2inst1/s
0x00007F1C3AD73490 : 716C 6C69 622F 6675 6E63 7469 6F6E 2F6A    qllib/function/j
0x00007F1C3AD734A0 : 6172 2F44 4232 494E 5354 312F 5359 5354    ar/DB2INST1/SYST
0x00007F1C3AD734B0 : 454D 5F4D 4C5F 434C 4945 4E54 5F4A 4152    EM_ML_CLIENT_JAR
0x00007F1C3AD734C0 : 2E6A 6172 3A53 7973 7465 6D43 6C69 656E    .jar:SystemClien
0x00007F1C3AD734D0 : 74                                         t

2014-05-15-09.17.23.081203-420 I944883E455           LEVEL: Warning
PID     : 2987                 TID : 139759180494592 PROC : db2fmp (
INSTANCE: db2inst1             NODE : 000
APPID   : *LOCAL.db2inst1.140515154559
HOSTNAME: oxiro
FUNCTION: DB2 UDB, BSU Java support, sqlejCallJavaRoutine_dll, probe:140
MESSAGE : JNI GetMethodID failed.  method:
DATA #1 : Hexdump, 12 bytes
0x00007F1C3AD734D2 : 6361 6C6C 5379 7374 656D 4D4C              callSystemML

2014-05-15-09.17.23.081294-420 I945339E699           LEVEL: Warning
PID     : 2987                 TID : 139759180494592 PROC : db2fmp (
INSTANCE: db2inst1             NODE : 000
APPID   : *LOCAL.db2inst1.140515154559
HOSTNAME: oxiro
FUNCTION: DB2 UDB, BSU Java support, sqlejCallJavaRoutine_dll, probe:150
MESSAGE : JNI GetMethodID failed.  signature:
DATA #1 : Hexdump, 58 bytes
0x00007F1C3AD73560 : 284C 6A61 7661 2F6C 616E 672F 5374 7269    (Ljava/lang/Stri
0x00007F1C3AD73570 : 6E67 3B49 4C6A 6176 612F 6C61 6E67 2F53    ng;ILjava/lang/S
0x00007F1C3AD73580 : 7472 696E 673B 4C6A 6176 612F 6C61 6E67    tring;Ljava/lang
0x00007F1C3AD73590 : 2F53 7472 696E 673B 2956                   /String;)V
2014-05-15-09.17.23.081575-420 E946039E433           LEVEL: Warning
PID     : 2987                 TID : 139759180494592 PROC : db2fmp (
INSTANCE: db2inst1             NODE : 000
APPID   : *LOCAL.db2inst1.140515154559
HOSTNAME: oxiro
FUNCTION: DB2 UDB, BSU Java support, sqlejLogException, probe:10
MESSAGE : ADM10000W  A Java exception has been caught.  The Java stack
      traceback has been written to the db2diag log file.

2014-05-15-09.17.23.081835-420 I946473E518           LEVEL: Warning
PID     : 2987                 TID : 139759180494592 PROC : db2fmp (
INSTANCE: db2inst1             NODE : 000
APPID   : *LOCAL.db2inst1.140515154559
HOSTNAME: oxiro
FUNCTION: DB2 UDB, BSU Java support, sqlejLogException, probe:10
MESSAGE : java.lang.NoSuchMethodError: SystemClient.callSystemML(Ljava/lang   /String;ILjava/lang/String;Ljava/lang/String;)V
DATA #1 : Hexdump, 4 bytes
0x00007F1C384E9B00 : 0000 0000                                  ....

2014-05-15-09.17.23.081961-420 I946992E445           LEVEL: Warning
PID     : 2987                 TID : 139759180494592 PROC : db2fmp (
INSTANCE: db2inst1             NODE : 000
APPID   : *LOCAL.db2inst1.140515154559
HOSTNAME: oxiro
FUNCTION: DB2 UDB, routine_infrastructure, sqlerJavaCallRoutine, probe:30
MESSAGE : Error from DB2ER CallUDF.  RC:
DATA #1 : Hexdump, 4 bytes
0x00007F1C384EA6A0 : 2EEF FFFF                                  ....

Now, I do not understand why I get the JNI GetMethodID failed message and the java.lang.NoSuchMethodError since I follow the proper steps for registering my JAR.

I wanted to check if something in the steps I followed is wrong, so I did the same for a simpler Java class:

public class TestUdf {
    public static void testMethod(String inStr1, String inStr2, String inStr3, int[] out) {
        String someString = inStr1 + inStr2 + inStr3;
        out[0] = 1;
    }
}

and its creation SQL script:

CREATE PROCEDURE DB2INST1.TESTMETHOD(IN str1 VARCHAR(255), IN str2 
VARCHAR(255), IN str3 VARCHAR(255), OUT out1 INTEGER)
LANGUAGE java 
PARAMETER STYLE java 
FENCED THREADSAFE
EXTERNAL NAME 
'TESTUDF:TestUdf.testMethod(java.lang.String, java.lang.String, java.lang.String,  java.lang.Integer[])';

and it works perfectly fine.

Therefore, my question is: What am I doing wrong in the first case and my Procedure is not executed? Does it have to do anything with my JDK? I am using IBM's JDK and it is installed at the directory:

/opt/ibm/java-x86_64-71/

Also, the db2 configuration manager returns the following:

db2inst1@oxiro:~$ db2 get dbm cfg

          Database Manager Configuration

     Node type = Enterprise Server Edition with local and remote clients

 Database manager configuration release level            = 0x0f00

 Java Development Kit installation path       (JDK_PATH) = /opt/ibm/java-x86_64-71/

Finally, I would like to say that I am working on an Ubuntu 12 (64 bit) machine.

Thank you, and I am sorry for the long post.

役に立ちましたか?

解決

DB2 is looking for a method with the signature (String, int, String, String):

(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V

Note "I" as the second parameter type, it's not "Ljava/lang/Integer".

The SQL INTEGER data type maps to Java int, so you'll need to change your method signature.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top