DB2CLI API bindParam Documentation

Issue #6 resolved
Jay Anderson created an issue

Number 14 in the readme. It says that three attributes are needed and they are Value, In/Out Type and Indicator. Value can be an integer or a string. In/Out Type is an integer. If Value is an input value, please set it to 0. Otherwise, set it to 1. Indicator is an integer flag to tell how to process special types. See table for details. 1) There is no table 2) In/Out type should be SQL_PARAM_INPUT or SQL_PARAM_OUTPUT or SQL_PARAM_INPUT_OUTPUT which are 1, 2 and 3 3) Parameters have to be more than integer or string, don't they? Float/Date,etc 4) Can someone shed some light on the Indicator?

Comments (25)

  1. Jay Anderson reporter

    The Node.js Reference does have the table. The readme is the same thing except no table. I have an in/out parameter decimal(9,0), an input parameter string character(40) and an input parameter decimal(9,2). The in/out parameter must have an indicator of 2 which is iteger. The other 2 work with a 1 or a null, it seems. The in/out mechanism has not worked yet. I don't get a return value. The database is updating just fine.

  2. Jay Anderson reporter
    var db = require(
        '/QOpenSys/QIBM/ProdData/Node/os400/db2i/lib/db2'
    );
    var util = require('util');
    var sql = "call test.updnameid(?,?,?)";
    var storedProc =
        " CREATE PROCEDURE test.updnameid (  INOUT IKEY DECIMAL(9, 0) ,  IN INNAME varCHAR(50) ,  IN INNUM DECIMAL(9, 2) ) LANGUAGE SQL  SPECIFIC test.updnameid   NOT DETERMINISTIC   MODIFIES SQL DATA   CALLED ON NULL INPUT   SET OPTION  ALWBLK = *ALLREAD ,   ALWCPYDTA = *OPTIMIZE ,   COMMIT = *NONE ,   DECRESULT = (31, 31, 00) ,   DFTRDBCOL = *NONE ,   DYNDFTCOL = *NO ,   DYNUSRPRF = *USER ,   SRTSEQ = *HEX     BEGIN   IF EXISTS ( SELECT ID FROM TEST . NAMEID WHERE ID = IKEY )  THEN   UPDATE TEST . NAMEID   SET NAME = INNAME ,  SALARY = INNUM   WHERE PLKEY = IKEY ;     ELSE    INSERT INTO TEST . NAMEID ( NAME , SALARY )    VALUES ( INNAME , INNUM ) ;  SET IKEY = IDENTITY_VAL_LOCAL ( ) ;         END IF ;      END";
    
    try {
        db.debug(true); // Enable Debug Mode if needed.
        db.init(function() { // Initialize the environment for database connections.
            db.serverMode(true); // Enable Server Mode if needed
        });
        db.conn("*LOCAL", "user",
            "pass",
            function() { // Connect to a database
                db.autoCommit(true); // Enable the Auto Commit feature if needed.
                db.setConnAttr(db.SQL_ATTR_COMMIT,
                    db.SQL_TXN_NO_COMMIT
                ); //No Journal
            });
        try {
            db.exec(
                "DROP PROCEDURE TEST.UPDNAMEID"
            );
            db.exec(storedProc);
        } catch (e) { // Exception handler
            console.log(e);
        }
        try {
            db.exec(
                "CREATE TABLE TEST.NAMEID ( ID DECIMAL(9, 0) GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE  NO CYCLE NO ORDER CACHE 20 ), NAME VARCHAR(50) CCSID 37 NOT NULL DEFAULT '' , SALARY DECIMAL(9, 2) DEFAULT NULL )"
            ); // Create a new table in the database.
        } catch (e) { // Exception handler
            var ee = util.inspect(e, false,
                null);
            if (ee.indexOf("SQLCODE=7905") ||
                ee.indexOf("SQLCODE=-601")) { //not journaled or already exists
                console.log(
                    'Not journaled but we still have a TABLE'
                );
            } else {
                console.log(ee);
            };
        }
        db.prepare(sql); // Prepare for the SQL statement.
        // ****       from the Docs *** 
        // ParamList is a java script array representing the binding parameter list. 
        // Each parameter has three attributes which are also represented as an array.
        // The three attributes are Value, In/Out Type and Indicator. 
        // Value can be an integer value or a string. In/Out Type is an integer. 
        // If Value is an input value, please set it to 0. Otherwise, set it to 1. 
        // Indicator is an integer flag to tell the function how to process some special types of parameters.
        //  Different type of Value requires corresponding Indicator. Please refer to below table for details.
        // 
        //Indicator 0 CLOB String -- 1 Null Terminated String -- 2 Integer -- 3 NULL
        // ****       from the Docs *** 
    
        //  The inout parameter is giving me trouble -- it is not an integer.  The decimal(9,2) is not a string but it converts.
        //  No parameter comes back. This is adding records.
        //*************************
    
        db.bindParam([ // Bind parameters for each markers in the SQL statement.
            [0, db.SQL_PARAM_INPUT_OUTPUT,
                2
            ],
            ['Bobby', db.SQL_PARAM_INPUT,
                1
            ],
            [345.66, db.SQL_PARAM_INPUT,
                1
            ],
        ]);
        db.execute(function callback(out) { //Out is an array of each output parameters.
            for (i = 0; i < out.length; i++)
                console.log(
                    "Output Param[%d] = %s \n",
                    i, out[i]);
        });
        console.log(
            "There are %d rows affected.",
            db.numRows()); // Get the execution result.
    
        db.exec("SELECT * FROM TEST.NAMEID", // Query the data in the new table.
            function(jsonObj) { // Print the output in a readble way.
                console.log(
                    "Result: %s",
                    JSON.stringify(
                        jsonObj));
                var fieldNum = db.numFields();
                console.log(
                    "There are %d fields in each row.",
                    fieldNum);
                console.log(
                    "Name | Length | Type | Precise | Scale | Null"
                ); // Print all the fields information.
                for (var i = 0; i <
                    fieldNum; i++)
                    console.log(
                        "%s | %d | %d | %d | %d | %d",
                        db.fieldName(i),
                        db.fieldWidth(i),
                        db.fieldType(i),
                        db.fieldPrecise(
                            i),
                        db.fieldScale(i),
                        db.fieldNullable(
                            i));
            }
        );
        //  db.exec("DROP TABLE TEST.NAMEID");  // Delete the example table from the database.
        db.close(); // Release any used resource.
    } catch (e) { // Exception handler
        console.log(e);
    }
    
  3. Jay Anderson reporter

    I discovered this that I am getting this in QEZDEBUG:

    5770SS1 V7R2M0 140418 02/04/15 14:08:02 SQL SERVICE DUMP
    CONNECT FLAGS
    STARTING ADDRESS <80000000 00000000 F64B7ABD 22002090> LENGTH <0000 002F>
    0000 0000 <C7C5E36D C5D9D9D6 D940C640 D7D9C56D> <C5D9D9D6 D940C240 E2D8D36D C3 0000 0020 <4040C140 D8E6E3C3 C8C7D1C2 4040C6 >

  4. Aaron Bartell

    @jay_anderson can you confirm you have all of the PTFs not only loaded but applied? Others have had odd issues because of this.

    Go here to learn more about the PTFs.

  5. Jay Anderson reporter

    I patched. Nothing changed. Did you happen to run my script? Does it work as advertised for you? I have not acquired all that much knowledge in this arena but I find this troubling. Also, all the DB2 stuff seems to be coded as sync even though some have callbacks. This is not the node way! Is it? I need to be able to hand the whole ""Get me this data and let me know when you finish" thing off and supply 1 callback to process the return. Do you have any insight?

  6. Aaron Bartell

    It appears it worked for me. Note I removed the user and password when I ran it. See below for full node REPL:

    $ node
    > var db = require(
    ...     '/QOpenSys/QIBM/ProdData/Node/os400/db2i/lib/db2'
    ... );
    undefined
    > var util = require('util');
    undefined
    > var sql = "call test.updnameid(?,?,?)";
    undefined
    > var storedProc =
    ...     " CREATE PROCEDURE test.updnameid (  INOUT IKEY DECIMAL(9, 0) ,  IN INNAME varCHAR(50) ,  IN INNUM DECIMAL(9, 2) ) LANGUAGE SQL  SPECIFIC test.updnameid   NOT DETERMINISTIC   MODIFIES SQL DATA   CALLED ON NULL INPUT   SET OPTION  ALWBLK = *ALLREAD ,   ALWCPYDTA = *OPTIMIZE ,   COMMIT = *NONE ,   DECRESULT = (31, 31, 00) ,   DFTRDBCOL = *NONE ,   DYNDFTCOL = *NO ,   DYNUSRPRF = *USER ,   SRTSEQ = *HEX     BEGIN   IF EXISTS ( SELECT ID FROM TEST . NAMEID WHERE ID = IKEY )  THEN   UPDATE TEST . NAMEID   SET NAME = INNAME ,  SALARY = INNUM   WHERE PLKEY = IKEY ;     ELSE    INSERT INTO TEST . NAMEID ( NAME , SALARY )    VALUES ( INNAME , INNUM ) ;  SET IKEY = IDENTITY_VAL_LOCAL ( ) ;         END IF ;      END";
    undefined
    >
    undefined
    > try {
    ...     db.debug(true); // Enable Debug Mode if needed.
    ...     db.init(function() { // Initialize the environment for database connections.
    .....         db.serverMode(true); // Enable Server Mode if needed
    .....     });
    ...     db.conn("*LOCAL", "user",
    .....         "pass",
    .....         function() { // Connect to a database
    .......             db.autoCommit(true); // Enable the Auto Commit feature if needed.
    .......             db.setConnAttr(db.SQL_ATTR_COMMIT,
    .........                 db.SQL_TXN_NO_COMMIT
    .........             ); //No Journal
    .......         });
    ...     try {
    .....         db.exec(
    .......             "DROP PROCEDURE TEST.UPDNAMEID"
    .......         );
    .....         db.exec(storedProc);
    .....     } catch (e) { // Exception handler
    .....         console.log("create procedure error:" + e);
    .....     }
    ...     try {
    .....         db.exec(
    .......             "CREATE TABLE TEST.NAMEID ( ID DECIMAL(9, 0) GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE  NO CYCLE NO ORDER CACHE 20 ), NAME VARCHAR(50) CCSID 37 NOT NULL DEFAULT '' , SALARY DECIMAL(9, 2) DEFAULT NULL )"
    .......         ); // Create a new table in the database.
    .....     } catch (e) { // Exception handler
    .....         var ee = util.inspect(e, false,
    .......             null);
    .....         if (ee.indexOf("SQLCODE=7905") ||
    .......             ee.indexOf("SQLCODE=-601")) { //not journaled or already exists
    .......             console.log(
    .........                 'Not journaled but we still have a TABLE'
    .........             );
    .......         } else {
    .......             console.log(ee);
    .......         };
    .....     }
    ...     db.prepare(sql); // Prepare for the SQL statement.
    ...     // ****       from the Docs ***
    ...     // ParamList is a java script array representing the binding parameter list.
    ...     // Each parameter has three attributes which are also represented as an array.
    ...     // The three attributes are Value, In/Out Type and Indicator.
    ...     // Value can be an integer value or a string. In/Out Type is an integer.
    ...     // If Value is an input value, please set it to 0. Otherwise, set it to 1.
    ...     // Indicator is an integer flag to tell the function how to process some special types of parameters.
    ...     //  Different type of Value requires corresponding Indicator. Please refer to below table for details.
    ...     //
    ...     //Indicator 0 CLOB String -- 1 Null Terminated String -- 2 Integer -- 3 NULL
    ...     // ****       from the Docs ***
    ...
    ...     //  The inout parameter is giving me trouble -- it is not an integer.  The decimal(9,2) is not a string but it converts.
    ...     //  No parameter comes back. This is adding records.
    ...     //*************************
    ...
    ...     db.bindParam([ // Bind parameters for each markers in the SQL statement.
    ...         [0, db.SQL_PARAM_INPUT_OUTPUT,
    ...             2
    ...         ],
    ...         ['Bobby', db.SQL_PARAM_INPUT,
    ...             1
    ...         ],
    ...         [345.66, db.SQL_PARAM_INPUT,
    ...             1
    ...         ],
    ...     ]);
    ...     db.execute(function callback(out) { //Out is an array of each output parameters.
    ...         for (i = 0; i < out.length; i++)
    ...             console.log(
    .....                 "Output Param[%d] = %s \n",
    .....                 i, out[i]);
    ...     });
    ...     console.log(
    ...         "There are %d rows affected.",
    ...         db.numRows()); // Get the execution result.
    ...
    ...     db.exec("SELECT * FROM TEST.NAMEID", // Query the data in the new table.
    ...         function(jsonObj) { // Print the output in a readble way.
    .....             console.log(
    .......                 "Result: %s",
    .......                 JSON.stringify(
    .........                     jsonObj));
    .....             var fieldNum = db.numFields();
    .....             console.log(
    .......                 "There are %d fields in each row.",
    .......                 fieldNum);
    .....             console.log(
    .......                 "Name | Length | Type | Precise | Scale | Null"
    .......             ); // Print all the fields information.
    .....             for (var i = 0; i <
    .......                 fieldNum; i++)
    .....                 console.log(
    .......                     "%s | %d | %d | %d | %d | %d",
    .......                     db.fieldName(i),
    .......                     db.fieldWidth(i),
    .......                     db.fieldType(i),
    .......                     db.fieldPrecise(
    .........                         i),
    .......                     db.fieldScale(i),
    .......                     db.fieldNullable(
    .........                         i));
    .....         }
    ...     );
    ...     //  db.exec("DROP TABLE TEST.NAMEID");  // Delete the example table from the database.
    ...     db.close(); // Release any used resource.
    ... } catch (e) { // Exception handler
    ...     console.log(e);
    ... }
    SetEnvAttr() attr = 10004, value = 1, rc = 0
    Connect *LOCAL
    SetConnAttr() attr = 10003, value = 1, rc = 0
    SetConnAttr() attr = 0, value = 1, rc = 0
    SQL: DROP PROCEDURE TEST.UPDNAMEID
    SQL:  CREATE PROCEDURE test.updnameid (  INOUT IKEY DECIMAL(9, 0) ,  IN INNAME varCHAR(50) ,  IN INNUM DECIMAL(9, 2) ) LANGUAGE SQL  SPECIFIC test.updnameid   NOT DETERMINISTIC   MODIFIES SQL DATA   CALLED ON NULL INPUT   SET OPTION  ALWBLK = *ALLREAD ,   ALWCPYDTA = *OPTIMIZE ,   COMMIT = *NONE ,   DECRESULT = (31, 31, 00) ,   DFTRDBCOL = *NONE ,   DYNDFTCOL = *NO ,   DYNUSRPRF = *USER ,   SRTSEQ = *HEX     BEGIN   IF EXISTS ( SELECT ID FROM TEST . NAMEID WHERE ID = IKEY )  THEN   UPDATE TEST . NAMEID   SET NAME = INNAME ,  SALARY = INNUM   WHERE PLKEY = IKEY ;     ELSE    INSERT INTO TEST . NAMEID ( NAME , SALARY )    VALUES ( INNAME , INNUM ) ;  SET IKEY = IDENTITY_VAL_LOCAL ( ) ;         END IF ;      END
    SQL: CREATE TABLE TEST.NAMEID ( ID DECIMAL(9, 0) GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE  NO CYCLE NO ORDER CACHE 20 ), NAME VARCHAR(50) CCSID 37 NOT NULL DEFAULT '' , SALARY DECIMAL(9, 2) DEFAULT NULL )
    
     **** ERROR *****
    SQLSTATE: 42710
    Native Error Code: -601
    NAMEID in TEST type *FILE already exists.
    Not journaled but we still have a TABLE
    SQL: call test.updnameid(?,?,?)
    Bind Parameter [1] = 16777216
    Bind Parameter [2] = Bobby
    Bind Parameter [3] = 345.66
    SQLExecute() rc=0.
    SQLRowCount() rc=0.
    SQLNumResultCols() rc=0.
    There are 0 rows affected.
    SQL: SELECT * FROM TEST.NAMEID
    Result: [{"ID":"1","NAME":"Bobby","SALARY":"345.66"}]
    There are 3 fields in each row.
    Name | Length | Type | Precise | Scale | Null
    ID | 3 | 3 | 9 | 0 | 0
    NAME | 5 | 12 | 50 | 0 | 0
    SALARY | 7 | 3 | 9 | 2 | 1
    undefined
    
  7. Jay Anderson reporter

    That 16777216 should be 0 and I should not have to say that is an integer with that 2. That 2nd float worked by specifying it as a 1 string.

  8. Aaron Bartell

    @jay_anderson I was able to get it working. First decimals need to use strings. Second, your stored proc referenced PLKEY but that didn't exist. I believe that's all I changed.

    Let me know if this works for you.

    var db = require(
        '/QOpenSys/QIBM/ProdData/Node/os400/db2i/lib/db2'
    );
    var util = require('util');
    var sql = "call test.updnameid(?,?,?)";
    var storedProc =
        " CREATE PROCEDURE test.updnameid (  INOUT IKEY DECIMAL(9, 0) ,  IN INNAME varCHAR(50) ,  IN INNUM DECIMAL(9, 2) ) LANGUAGE SQL  SPECIFIC test.updnameid   NOT DETERMINISTIC   MODIFIES SQL DATA   CALLED ON NULL INPUT   SET OPTION  ALWBLK = *ALLREAD ,   ALWCPYDTA = *OPTIMIZE ,   COMMIT = *NONE ,   DECRESULT = (31, 31, 00) ,   DFTRDBCOL = *NONE ,   DYNDFTCOL = *NO ,   DYNUSRPRF = *USER ,   SRTSEQ = *HEX BEGIN   IF EXISTS ( SELECT ID FROM TEST . NAMEID WHERE ID = IKEY )  THEN   UPDATE TEST . NAMEID   SET NAME = INNAME ,  SALARY = INNUM   WHERE ID = IKEY ;     ELSE    INSERT INTO TEST . NAMEID ( NAME , SALARY )    VALUES ( INNAME , INNUM ) ;  SET IKEY = IDENTITY_VAL_LOCAL ( ) ;         END IF ;      END";
    
    try {
        db.debug(true); // Enable Debug Mode if needed.
        db.init(function() { // Initialize the environment for database connections.
            db.serverMode(true); // Enable Server Mode if needed
        });
        db.conn("*LOCAL", 
            function() { // Connect to a database
                db.autoCommit(true); // Enable the Auto Commit feature if needed.
                db.setConnAttr(db.SQL_ATTR_COMMIT, db.SQL_TXN_NO_COMMIT); //No Journal
            });
        try {
            db.exec("DROP PROCEDURE TEST.UPDNAMEID");
            db.exec(storedProc);
        } catch (e) { // Exception handler
            console.log(e);
        }
        try {
            db.exec(
                "CREATE TABLE TEST.NAMEID ( ID DECIMAL(9, 0) GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE  NO CYCLE NO ORDER CACHE 20 ), NAME VARCHAR(50) CCSID 37 NOT NULL DEFAULT '' , SALARY DECIMAL(9, 2) DEFAULT NULL )"
            ); // Create a new table in the database.
        } catch (e) { // Exception handler
            var ee = util.inspect(e, false,
                null);
            if (ee.indexOf("SQLCODE=7905") ||
                ee.indexOf("SQLCODE=-601")) { //not journaled or already exists
                console.log('Not journaled but we still have a TABLE');
            } else {
                console.log(ee);
            };
        }
        db.prepare(sql); // Prepare for the SQL statement.
        // ****       from the Docs *** 
        // ParamList is a java script array representing the binding parameter list. 
        // Each parameter has three attributes which are also represented as an array.
        // The three attributes are Value, In/Out Type and Indicator. 
        // Value can be an integer value or a string. In/Out Type is an integer. 
        // If Value is an input value, please set it to 0. Otherwise, set it to 1. 
        // Indicator is an integer flag to tell the function how to process some special types of parameters.
        //  Different type of Value requires corresponding Indicator. Please refer to below table for details.
        // 
        //Indicator 0 CLOB String -- 1 Null Terminated String -- 2 Integer -- 3 NULL
        // ****       from the Docs *** 
    
        //  The inout parameter is giving me trouble -- it is not an integer.  The decimal(9,2) is not a string but it converts.
        //  No parameter comes back. This is adding records.
        //*************************
    
        db.bindParam([ // Bind parameters for each markers in the SQL statement.
            ['3', db.SQL_PARAM_INPUT, 1],
            ['Bobby', db.SQL_PARAM_INPUT, 1],
            ['345.67', db.SQL_PARAM_INPUT, 1],
        ]);
        db.execute(function callback(out) { //Out is an array of each output parameters.
            for (i = 0; i < out.length; i++)
                console.log("Output Param[%d] = %s \n", i, out[i]);
        });
        console.log("There are %d rows affected.", db.numRows()); // Get the execution result.
    
        db.exec("SELECT * FROM TEST.NAMEID", // Query the data in the new table.
            function(jsonObj) { // Print the output in a readble way.
                console.log("Result: %s", JSON.stringify(jsonObj));
                var fieldNum = db.numFields();
                console.log("There are %d fields in each row.", fieldNum);
                console.log("Name | Length | Type | Precise | Scale | Null"
                ); // Print all the fields information.
                for (var i = 0; i < fieldNum; i++){
                    console.log(
                        "%s | %d | %d | %d | %d | %d",
                        db.fieldName(i),
                        db.fieldWidth(i),
                        db.fieldType(i),
                        db.fieldPrecise(i),
                        db.fieldScale(i),
                        db.fieldNullable(i)
                    );
                }
            }
        );
        //  db.exec("DROP TABLE TEST.NAMEID");  // Delete the example table from the database.
        db.close(); // Release any used resource.
    } catch (e) { // Exception handler
        console.log(e);
    }
    
  9. Jay Anderson reporter

    Technically, I guess you could say it worked, but not correctly. Supplying the key like the way it is, it did update the record, no problem. When you make the key 0 signifying an ADD, it also works, sort of, I get an error about truncation and no key is returned as it should be. Here is how it looks calling from Client Access: call test.updnameid(0,'sam',3.45)

    Return Code = 0

    Output Parameter #1 = 13

    Statement ran successfully (62 ms)

  10. Aaron Bartell

    Could you post the exact code you pasted into Client Access? As I learned when I was walking through your original syntax it wasn't correct, so I am wondering if there is some massaging that happens between the two.

  11. Jay Anderson reporter

    That is the exact way I called the same stored procedure.

    I really appreciate you spending time on this. I will be traveling for the next 2 days.

  12. Jay Anderson reporter

    I am working on other projects so I have not had time to document this fully but there is a problem mapping INOUT parameters on a stored procedure call. I have done a fall-back to just input or output parameters and have had success just like in the examples; however, when I switch to an inout parameter the mapping is not right. Traditionally, my update stored procedures have always sent in a zero key when I want an add and the actual key when I want an update. I always return the new key.

    I will most likely patch up to the lastest and greatest before I proceed with my research.

  13. Jay Anderson reporter

    I am at the "I did not know you could do that in Qsh!" stage of development so I have a lot to learn about 'nix in general but this is very exciting! Where is all of the example code from IBMERS ... not just node? What tools are available? Right now I am editing directly in WINSCP. That works pretty well. To round out node I need Python. Is that coming on the next round?

  14. Aaron Bartell

    >Where is all of the example code from IBMERS ... not just node?

    I think most of that will have to come from the community. Though Tony Cairns is constantly adding stuff to youngiprofessionals.com

    >What tools are available? Right now I am editing directly in WINSCP.

    When I have to be on Windows I use either the Secure Shell Chrome browser plugin or FireSSH Firefox browser plugin.

    >To round out node I need Python. Is that coming on the next round?

    At COMMON IBM announced Python availability and it should be coming out later this month. Check this link for updates.

  15. Jay Anderson reporter

    I ended up shying away from the node DB2 interface directly. This book : Manning Early Access Program hapi.js in Action Mathew Harrison : got me going in a different direction. Since I already have a lot of code in Java Servlets, I started reusing some of that code developing REST APIs. The book clearly separates the API from the front end. I switched exclusively from replys in XML to JSON. I use Wreck to make the api calls and I like SWIG for the templating engine. It is most like JSP for me. Using this article :https://www.ibm.com/developerworks/ibmi/library/i-run-asf-tomcat-on-ibmi/ : I run the api directly on the IBMI on Tomcat. My node development machine is a Ubuntu server and right now node works a lot better there. I have a git repository on the IBMI for code but I am still lacking in knowledge there. I haven't officially put anything into production (with node) but I am having a lot of fun! I do a lot of my front end coding with EJS TreeGrid from www.treegrid.com. I have been using that product since 2008 and am barely scratching the surface of what it can do. I would highly recommend it. I have the extended api and it is awesome. Since switching to node, I am using the JSON interface to configure and talk to Treegrid. I use the Dojo toolkit on top of all of that to do screens and ajax calls. I am switching to all JSON all the time. Hapi fixes up the payload so an object comes in as an object. Anyway.... that's where I am.

  16. Aaron Bartell

    Glad to hear you are making good progress. Just so I am understanding your architecture, is it as follows?

    browser->Node.js(ubuntu)->Tomcat(IBMi)->DB2 for i
    

    > I run the api directly on the IBMI on Tomcat. My node development machine is a Ubuntu server and right now node works a lot better there.

    What types of issues are you having on the IBM i side with Node? Wondering if there is anything I can help with.

  17. Jay Anderson reporter

    Yes, that is correct. I am able to develop using JT400 but Tomcat is configured with the native driver directly on IBMi. According to the article I cited, it is drop-dead fast. I will get back to node directly on IBMi later. The specific problem is Bcrypt which requires Python to get going. It won't load yet.

  18. Marco Kam

    Jay, regarding Bcrypt, you could use Bcryptjs, which is written in pure javascript and does not have a dependency on python.

    I ran this on the IBMi and it works:

    var bcrypt = require('bcryptjs');
    bcrypt.genSalt(10, function(err, salt) {
        bcrypt.hash("password", salt, function(err, hash) {
            console.log('hash', hash);
        });
    });
    
  19. Jay Anderson reporter

    Yes. All the work I did in node had to be shelved in favor of bringing my Websphere Portal up to date. No Node for me in the forseeable future.

  20. Log in to comment