简体   繁体   中英

SQL4306N Java stored procedure or user-defined function could not call Java method

We just upgraded to DB2 10.5 from 9.5, this process was working fine until the upgrade was performed on the server. When i run the jar file from a linux server, I get the following error however when i run the exact same code from eclipse on my windows computer, it works just fine! I am also getting a similar error if I calll this sp from DB2 control center. I am looking to know what is causing this and how can i fix this error?

SQL4306N Java stored procedure or user-defined function "ESADBM.GETNEXTID", specific name "WHDBRMM_UTILS" could not call Java method "GetNextID", signature "(Ljava/lang/String;[I)V". SQLSTATE=42724

Explanation:

The Java method given by the EXTERNAL NAME clause of a CREATE PROCEDURE or CREATE FUNCTION statement could not be found. Its declared argument list may not match what the database expects, or it may not be a "public" instance method.

User response:

Ensure that a Java instance method exists with the "public" flag and the expected argument list for this call.

sqlcode: -4306

sqlstate: 42724.

Here is the code:

    package pkgUtil_v4_0_0_0;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import org.hibernate.exception.JDBCConnectionException;


    public class DBSequence {
      public static final String SEQ_CONTACTID        = "ContactIDSeq"; 
      public static final String SEQ_PROJECTID        = "ProjectIDSeq";
      public static final String SEQ_LOCATIONID       = "LocationIDSeq";
      public static final String SEQ_SOURCEID         = "SourceIDSeq";
      public static final String SEQ_SURVEYID         = "SurveyIDSeq";
      public static final String SEQ_LOGICALSURVEYID  = "WageAreaIDSeq";
      public static final String SEQ_WAGEDETAILID     = "WageDetailIDSeq";
      public static final String SEQ_ORGID            = "OrgIDSeq";
      public static final String SEQ_OFFICEID         = "RegionNumberSeq";
      public static final String SEQ_LETTERID         = "LetterIDSeq";
      public static final String SEQ_DODGEID          = "DodgeIDSeq";
      public static final String SEQ_CRAFTID          = "CraftIDSeq";
      public static final String SEQ_CRAFTTITLEID     = "CraftTitleIDSeq";
      public static final String SEQ_ANALYSTID        = "AnalystIDSeq";
      public static final String SEQ_LETTERTEMPLATEID = "LetterTemplateIDSeq";
      public static final String SEQ_RECRATESID       = "RecRatesIDSeq";
      public static final String SEQ_BRIDGESCDID      = "BridgeSCDIDSeq";


      public static String drvr = "";
      public static Connection con = null;

      // utility function
      public static int getNextId(Connection lcon, String sequence) throws         SQLException {
        Boolean bFlag;
        PreparedStatement stmt = null;
        int id = 0;

        String sql = "select next value for esadbm." +
             sequence + " from SYSIBM.sysdummy1";
    //    System.out.println("String = "+sequence);
        stmt = lcon.prepareStatement(sql);
        ResultSet resultSet = stmt.executeQuery();
        if (resultSet.next()) {
          id = resultSet.getInt(1); 
        }
        resultSet.close();
        stmt.close();

        return id;
      }

      // Stored Procedure Entry Point
      public static void getNextId(String sequence, int[] seq) throws SQLException, Exception {
  System.out.println("String = "+sequence);
  System.out.println("Array = "+seq);
        if (drvr.length() == 0) {
          drvr = "jdbc:default:connection";
          con = DriverManager.getConnection(drvr);
        }
        drvr = "";
        seq[0] = getNextId(con, sequence);
        con.close();
      }

      // test procedure 
      public static void main(String args[])throws SQLException, Exception {

        try {
          System.out.println("Connecting to DB " + args[0]);

          Class.forName("com.ibm.db2.jcc.DB2Driver");
          drvr = "jdbc:db2:" + args[0];
    //      System.out.println(drvr+args[1] + args[2]);
          con = DriverManager.getConnection("jdbc:db2:" + args[0], args[1],args[2]);
    //      System.out.println(con);
            System.out.println("DB Connection Successful");
          con = DriverManager.getConnection(drvr, args[1], args[2]);

          Statement st = con.createStatement();
          String query = "set schema = 'ESADBM'";
          st.execute(query);

          System.out.println("Getting ID");

          int id = getNextId(con, SEQ_SOURCEID);

          System.out.println("Returned : " + Integer.toString(id));
        }
        catch (ClassNotFoundException cnfe) {
          cnfe.printStackTrace();
        }
        catch (SQLException sqle) {
          sqle.printStackTrace();
        }    
        catch (JDBCConnectionException e) {
            System.out.println("Unable to connect to database");
            e.printStackTrace();
        }
      }
    }

Here is the stored procedure:

               CREATE PROCEDURE "ESADBM  "."GETNEXTID" 
                                    ( 
                            IN      SEQUENCE   CHARACTER(40),
                            OUT     ID   INTEGER
                            )
                                    DYNAMIC RESULT SETS 0 
                                    SPECIFIC WHDBRA_UTILS 
                                    EXTERNAL NAME 'pkgUtil_v4_0_0_0.DBSequence!getNextId()' 
                                    LANGUAGE JAVA     
                                    PARAMETER STYLE JAVA     
                                    NOT DETERMINISTIC 
                                    FENCED THREADSAFE 
                                    MODIFIES SQL DATA 
                                    NO DBINFO;

Libraries for external routines, including Java classes and JAR files for Java routines, must be present in a certain location in the DB2 instance directory. When you upgrade your DB2 version, a new instance is created, but those libraries are not copied automatically (which, by the way, makes sense as there is a good chance that they need to be rebuilt).

The error message indicates that the instance cannot find the Java class file that implements GETNEXTID -- that would be DBSequence.class . The class needs to be copied to the sqllib/function directory in the DB2 10.5 instance home on the database server, as explained in the manual . You will probably need also to create pkgUtil_v4_0_0_0 under sqllib/function for the correct package structure. Make sure you compile the Java source using the same JDK version as the one used by the DB2 instance to run the program.

Once you do that, execute CALL SQLJ.REFRESH_CLASSES() in the DB2 client of your choice to make sure DB2 reloads the most current version. After that your stored procedure should work correctly.

Having said that, I don't really understand why you use such a convoluted way of retrieving a SQL sequence value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM