2

I created the Java stored procedure as follows, able to generate a .class file using AS400 Qshell command interpreter.

    import java.sql.*;

    public class sample 
    {
        public sample(){
            super();
        }

        /**
         * @param args
         */
        public static void Test(int test) throws SQLException, Exception {
            // TODO Auto-generated method stub
            try
            {   Class.forName ("com.ibm.as400.access.AS400JDBCDriver").newInstance ();

                String url  = "jdbc:as400://ilava;naming=system;prompt=false;user=IPGUI;password=IPGUI;libraries=IPSRFILI,IPTSFILI,IPWMFILI,IPPAFILI,IPASFILI,IPSAFILI,IPTSUTL;translate binary=true";          
                Connection con = DriverManager.getConnection(url);          
                PreparedStatement ps = con.prepareStatement("INSERT INTO IPTSFILI.TEMP VALUES ('IP', 'WELCOME TO SQLJ')");
                ps.executeUpdate();
                ps.close();
                con.close();                
            } 
            catch (Exception e)
            {  
                System.out.println (e);
                System.exit(1);             
            }                       
    }       
 }

created the respective store procedure as

CREATE procedure IPTSFILI.SPSAMPLE ( 
    IN TEST INTEGER ) 
    LANGUAGE JAVA 
    SPECIFIC IPTSFILI.SPSAMPLE 
    DETERMINISTIC 
    MODIFIES SQL DATA 
    CALLED ON NULL INPUT 
    EXTERNAL NAME 'sample!Test' 
    PARAMETER STYLE JAVA ;

When the procedure is getting called (Using callable Statement in JAVA) it gives below error as

java.sql.SQLException: [SQL4304]  Java stored procedure or user-defined function SPSAMPLE, specific name SPSAMPLE could not load Java class Ä?_ÑÂ_À¦ÀÂÄ/øøàâàÊÑÎÁÊ for reason code 3.
    at com.ibm.as400.access.JDError.throwSQLException(JDError.java:687)
    at com.ibm.as400.access.JDError.throwSQLException(JDError.java:653)
    at com.ibm.as400.access.AS400JDBCStatement.commonExecute(AS400JDBCStatement.java:920)
    at com.ibm.as400.access.AS400JDBCPreparedStatement.execute(AS400JDBCPreparedStatement.java:1018)
    at Exec.main(Exec.java:23)

Placed the .class file in the QIBM\UserData\OS400\SQLLib\Function directory.

Any suggestions on how to solve this?

Buck Calabro
  • 7,558
  • 22
  • 25
Anto
  • 57
  • 2
  • 10
  • Where do you call the stored procedure ? Cant see it in your code. Also, providing the full stack trace would help – ortis Apr 07 '15 at 09:13
  • @Ortis, updated the stack trace. – Anto Apr 07 '15 at 09:27
  • @AntoKris the class should implements `COM.ibm.db2.app.StoredProc` interface right? could you try that and see what happen – kucing_terbang Apr 07 '15 at 09:56
  • 1
    Looks like an encoding issue, how did you create the stored procedure? Can you try recreating it with iSeries access? –  Apr 07 '15 at 09:59

2 Answers2

0

You might not specify the procedure in a correct way. Looking at the documentation of OS400 and Java stored proc (see Chap 7) I think you are missing several steps here. I advise to take the code from the doc and run it, then replace with your own implementation.

ortis
  • 2,203
  • 2
  • 15
  • 18
  • I followed the steps mention in chapter 7, but still getting the same issue as " [SQL4304] Java stored procedure or user-defined function SPSAMPLE, specific name SPSAMPLE could not load Java class Ä?_ÑÂ_À¦ÀÂÄ/øøàâàÊÑÎÁÊ for reason code 3. " could you suggest the way to get rid of this. – Anto Apr 09 '15 at 06:17
  • Have you tried to run the example ? If it works, you can rule out encoding issue. – ortis Apr 09 '15 at 07:28
  • I tried the same tutorial, but i missed the optimization on java program "CRTJVAPGM CLSF(Db2CusInCity.class) OPTIMIZE(40)".is it necessary ? – Anto Apr 09 '15 at 07:40
0

You have some problems with your Java code.

  1. You should not use System.out in your Java stored procedure. Due to the nature of the system, System.out does not work properly if the Java stored procedure is invoked in a recycled QZDASOINIT or QSQSRVR job.

  2. You should not use System.exit(1) in your call. That call will end the JVM and once the JVM is ended, it cannot be restarted.

  3. You probably should be using the native JDBC driver if are accessing tables on the same system where the Java stored procedure is defined. To get a JDBC connection that uses the native driver, you should call DriverManager.getConnection("jdbc:default:connection");

  4. If you don't catch the exception, most JDBC exceptions will come back correctly if you call the stored procedure using the JDBC client.

I updated the program to look like the following.

import java.sql.*;

public class sample 
{
    public sample(){
        super();
    }

    /**
     * @param args
     */
    public static void Test(int test) throws SQLException, Exception {

           String url  = "jdbc:default:connection";
            Connection con = DriverManager.getConnection(url);          
            PreparedStatement ps = con.prepareStatement("INSERT INTO IPTSFILI.TEMP VALUES ('IP', 'WELCOME TO SQLJ')");
            ps.executeUpdate();
            ps.close();
            con.close();                
}       

}

When I called it, I get the following exception (since I did not create the file on my system).

SQLState: 42704
Message:  [SQL0204] TEMP in IPTSFILI type *FILE not found. 
Vendor:   -204

You will also want to check that the JOB CCSID of the database server job is not 65535. You should have received the following error if your JOB CCSID was 65535, but I suspect releases earlier than 6.1 may not have detected this correctly.

 CALL QSYS.QCMDEXC('Chgjob ccsid(65535)                ',000000020.00000)
 call SPSAMPLE(3)

 *** SQLException caught ***
 Statement was call SPSAMPLE(3)
 SQLState: 57017
 Message:  [SQL0332] Character conversion between CCSID 65535 and CCSID 1200 not valid.
 Vendor:   -332
jweberhard
  • 576
  • 3
  • 7
  • Thanks for your reply. I tried the way you suggested but getting the error as SQL State: 42724 Vendor Code: -4304 Message: [SQL4304] Java stored procedure or user-defined function SPSAMPLE, specific name SPSAMPLE could not load Java class Ä?_ÑÂ_À¦ÀÂÄ/øøàâàÊÑÎÁÊ for reason code 3. – Anto Apr 08 '15 at 04:37
  • @AntoKris What IBM i release are you using? Can you drop the procedure and use this create statement instead? CREATE procedure IPTSFILI.SPSAMPLE ( IN TEST INTEGER ) LANGUAGE JAVA PARAMETER STYLE JAVA DETERMINISTIC MODIFIES SQL DATA CALLED ON NULL INPUT EXTERNAL NAME 'sample.Test' – jweberhard Apr 09 '15 at 11:43
  • Version 7.1 .Thanks for your reply. – Anto Apr 09 '15 at 11:45
  • Getting the error like Message: [SQL4304] Java stored procedure or user-defined function MYJAVASTOREPROC, specific name MYJAVASTOREPROC could not load Java class SP for reason code 1. 1 -- The class was not found on the CLASSPATH. – Anto Apr 09 '15 at 11:47
  • Does the following work: --- create function getProperty(key varchar(200)) returns varchar(1024) language java parameter style java external name 'java.lang.System.getProperty' -- then --- select getProperty('java.home') from sysibm.sysdummy1 -- on my 7.1 system, the query returns /QOpenSys/QIBM/ProdData/JavaVM/jdk60/32bit/jre – jweberhard Apr 10 '15 at 04:46
  • I tried gives error message as 'Message: [SQL4304] Java stored procedure or user-defined function GETPROPERTY, specific name GETPROPERTY could not load Java class Ä?_ÑÂ_À¦ÀÂÄ/øøàâàÊÑÎÁÊ for reason code 3. " – Anto Apr 10 '15 at 07:04
  • That is really odd. Can you see if this query return information in the correct CCSID -- select EXTERNAL_NAME from qsys2.sysroutines where ROUTINE_NAME='GETPROPERTY' -- you should get java.lang.System.getProperty as the result. – jweberhard Apr 10 '15 at 21:55
  • Finally figured out working now.The problem is setting the JAVA_HOME environment variable using WRKENVVAR level(*sys), just removed the variable.AS400 takes default java version as 1.6 so there will be no loner need of JAVA_HOME environment variable. Thanks! Guys for all your support .Happy coding. – Anto Apr 15 '15 at 09:06