Question

1.for (Field field : fields) {
2.    if (p.contains(field.getName())) {
3.        if(field.getType().toString().split("[.]")[2].equals("String"))
4.            callableStatement.setString(field.getName(), field.get(obj).toString());
5.        else if(field.getType().toString().split("[.]")[2].equals("Integer"))
6.            callableStatement.setInt(field.getName(), (int)field.get(obj));
7.        System.out.println(field.get(obj).toString());
8.    }
9.}

This is my code. Using reflection I fetch the data from the class object and in the above loop, I set parameters for the procedure input. However, it saves some integer values and throws java.lang.NullPointerException for some on line number 7.

These values are accepted:

this.DI_StDate = Common.getDateStamp(date); // Integer
this.DI_StTime = Common.getTimeStamp(date); // Integer

From Common.java

public static Integer getDateStamp(Date d) {
    return Integer.parseInt(requiredDate.format(d));
}

public static Integer getTimeStamp(Date d) {
    return Integer.parseInt(requiredTime.format(d));
}

These throws the exception:

this.FileOpsId = new Integer(1);            // Integer
this.FileTypeOpsId = 1;                     // Integer

Please suggest where I am going wrong.

These are my class members:

public class DIConnect {
    public Integer PROC_ID;
    public String APIKey;
    public String Username;
    public String pwd;
    public String StreamKey;

    public Integer DI_StDate;
    public Integer DI_StTime;

    public String FileNamePath;
    public Integer FileOpsTypeId;
    public String ConfigLabel;
    public Integer FileOpsId;

    public Integer End_Date;
    public Integer End_Time;

    public DIConnect(String FileNamePath, String ConfigLabel, Integer FileOpsTypeId, Integer StartDate, Integer StartTime) {
        this.FileNamePath = FileNamePath;
        this.ConfigLabel = ConfigLabel;
        this.FileOpsTypeId = FileOpsTypeId;
        this.DI_StDate = StartDate; // accepted
        this.DI_StTime = StartTime; // accepted
        this.FileOpsId = new Integer(1); // NOT ACCEPTED
    }
}

This is the call in the main() method.

DIConnect DIC = new DIConnect(filePath, "File", 1, Common.getDateStamp(date), Common.getTimeStamp(date));
DIC.InsertFileOperation();

DIConnect.java:

public Integer InsertFileOperation() {
        String[] params = {"FileNamePath", "FileOpsId", "ConfigLabel", "DI_StDate", "DI_StTime"};
        DatabaseOperation db = new DatabaseOperation();
        if(db.openConnection()) {
            this.PROC_ID = db.executeProcedure("sp_InsertIntoFileOpsMaster", params, this);
            db.closeConnection();
        }
        return this.PROC_ID;
    }

Database.java

public Integer executeProcedure(String proc, String[] params, Object obj) {
        int Id = 0;
        try {
            String paramString = StringUtils.repeat("?, ", params.length + 1).trim();
            paramString = paramString.substring(0, paramString.length() - 1);
            proc = "{CALL " + proc + "(" + paramString + ")}";
            callableStatement = conn.prepareCall(proc);

            Class cls = obj.getClass();
            Field[] fields = cls.getFields();
            List<String> p = Arrays.asList(params);

            for (Field field : fields) {
                if (p.contains(field.getName())) {
                    if(field.getType().toString().split("[.]")[2].equals("String"))
                        callableStatement.setString(field.getName(), field.get(obj).toString());
                    else if(field.getType().toString().split("[.]")[2].equals("Integer"))
                        callableStatement.setInt(field.getName(), (int)field.get(obj));
                    System.out.println(field);                        
//                    System.out.println(field.get(obj).toString());
                }
            }
            callableStatement.registerOutParameter("Id",java.sql.Types.INTEGER);
            callableStatement.executeUpdate();
            Id = callableStatement.getInt("Id");

        } catch (SQLException | IllegalArgumentException | IllegalAccessException ex) {
            Logger.getLogger(DatabaseOperation.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex){
          System.out.println(ex.getMessage());
        } finally {
            return Id;
        }
    }

OUTPUT

public java.lang.Integer airteldemo.DIConnect.DI_StDate
public java.lang.Integer airteldemo.DIConnect.DI_StTime
public java.lang.String airteldemo.DIConnect.FileNamePath
public java.lang.String airteldemo.DIConnect.ConfigLabel
null
Was it helpful?

Solution 3

I found the bug. The callablestatement fetches the signature for the called procedure. The parameters should be passed as case-sensitive parameters. My procedure was recieving them as FileOpsTypeID and I was passing FileOpsTypeId. Changing the case made it work.

Sorry for the delayed response. Also sorry, I didn't provide the complete details (procedure).

OTHER TIPS

As I guessed the field.get(obj) (sometimes) returns null so you should check if it's null or somehow (depending on the logic of your code) don't allow it to become null.

I post this as answer cause given the information you've provided we can just tell you where is the problem, not what is causing it.

There are several problems with your code.


First, fields can have null values in java. If you're taking an argument of type Object you just have to accept this and map null values to SQL values perhaps based on reasoning about the database column type.

Instead of using field.get(obj).toString() which doesn't work with null field values, use String.valueOf(field.get(obj))


Second

else if(field.getType().toString().split("[.]")[2].equals("Integer"))

is broken because it assumes java.lang.Integer so could fail with a ClassCastException, is not null safe because (Integer) null does not correspond to any int value, and it could fail with an IndexOutOfBoundsException when field.getType() is something like shortpackage.Integer.

Instead do

Integer.class.equals(field.getType()) || Integer.TYPE.equals(field.getType())

Integer.TYPE is the pseudo-class for the int primitive type.


Third, you seem to be writing your own database abstraction layer. There's plenty of ORBs out there which should do this for you. I encourage you to use one of those instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top