Scanning…
Test versions are for brave and helpful ONLY. This page is explanation of things being worked with XMLSERVICE. You are welcome to download test version and try it out, but we recommend you try it from test library XMLSERVICE (crtxml-XMLSERVICE), not production libraries (crtxml2-ZENDSVR/crtxml6-ZENDSVR6, crtxmlr-POWER_RUBY, crtxmlq-IBM QXMLSERV). We appreciate any help checking out XMLSERVICE open source project (free programs), our goal is not to be intrusive into your daily activities, but your help testing makes XMLSERVICE better for every one. If you find an overriding issue or need a critical enhancement please let one of the authors know via email (main page).
Unzip xmlservice-rpg.zip to xmlservice.savf FTP xmlservice.savf to QGPL library > crtSAVF FILE(QGPL/XMLSERVICE) > clrSAVF FILE(QGPL/XMLSERVICE) > RSTLIB SAVLIB(XMLSERVICE) DEV(*SAVF) SAVF(QGPL/XMLSERVICE) MBROPT(*ALL) ALWOBJDIF(*ALL) > ADDLIBLE XMLSERVICE > CRTCLPGM PGM(XMLSERVICE/CRTXML) SRCFILE(XMLSERVICE/QCLSRC) > call crtxml > CHGAUT OBJ('/qsys.lib/XMLSERVICE.lib') USER(QTMHHTTP) DTAAUT(*RWX) OBJAUT(*ALL) SUBTREE(*ALL) > CHGAUT OBJ('/qsys.lib/XMLSERVICE.lib') USER(QTMHHTP1) DTAAUT(*RWX) OBJAUT(*ALL) SUBTREE(*ALL) PHP Toolkit users: Make sure you change your toolkit.ini "ZENDSVR" file to point new "XMLSERVICE" ... /usr/local/zendsvr/share/ToolkitAPI/toolkit.ini ; set library where XTOOLKIT lives, most likely XMLSERVICE (testing) or ZENDSVR (production) ;XMLServiceLib = "ZENDSVR" ; production XMLServiceLib = "XMLSERVICE" ; for testing new XMLSERVICE packages
<classpath>
, favour generic solution ADDENVVAR CLASSPATH=
(thanks Martin)raw xml: $ctl="*java" toolkit: 'customControl'=>'*java' Example: // IBM i $conn = db2_connect($database,$user,$password); if (!$conn) die("Bad connect: $database,$user"); // normal RPG java: 'customControl'=>'*java' -- set your own classpath // SP SQL java: 'customControl'=>'*sqljava' or 'customControl'=>'*dbgjava' -- your classpath ignored try { $ToolkitServiceObj = ToolkitService::getInstance($conn); } catch (Exception $e) { die($e->getMessage()); } $options = array('plugSize'=>'4K','customControl'=>'*java','stateless'=>true); $ToolkitServiceObj->setToolkitServiceParams($options); /* setting classpath before calling my pgm ... worked */ echo "setting classpath via cmd ..."; $output = $ToolkitServiceObj->CLCommand("ADDENVVAR ENVVAR(CLASSPATH) VALUE('/home/adc/my.jar:/frog') REPLACE(*YES)"); echo "calling java now ...\n"; $param = array(); $param[] = $ToolkitServiceObj->AddParameterChar ('both', 4096, 'INCHARA', 'var1', 'nothing'); $result = $ToolkitServiceObj->PgmCall('ZZJAVA2', 'XMLSERVICE', $param, null, null); var_dump($result);
raw xml: $ctl="*sqljava" or $ctl="*dbgjava" (port 30000) toolkit: 'customControl'=>'*sqljava' or 'customControl'=>'*dbgjava' (port 30000) -- remains same (see below) --
raw xml: $ctl="*java" toolkit: 'customControl'=>'*java' Example: // IBM i $conn = db2_connect($database,$user,$password); if (!$conn) die("Bad connect: $database,$user"); // normal RPG java: 'customControl'=>'*java' -- set your own classpath // SP SQL java: 'customControl'=>'*sqljava' or 'customControl'=>'*dbgjava' -- your classpath ignored try { $ToolkitServiceObj = ToolkitService::getInstance($conn); } catch (Exception $e) { die($e->getMessage()); } $options = array('plugSize'=>'4K','customControl'=>'*java','stateless'=>true); $ToolkitServiceObj->setToolkitServiceParams($options); echo "custom xml classpath ... "; $xmlRaw = "<?xml version='1.0'?> <script> <classpath>/home/adc:/QIBM/ProdData/OS400/Java400/ext/db2routines_classes.jar:/QIBM/ProdData/OS400/Java400/ext/runtime.zip:/QIBM/ProdData/OS400/Java400/ext/sqlj_classes.jar:/QIBM/ProdData/OS400/Java400/ext/db2_classes.jar</classpath> </script>"; $result = $ToolkitServiceObj->sendXml($xmlRaw); var_dump($result); // -- OR (perhaps easier, still debating) -- /* experiment 1: try setting classpath before calling my pgm ... worked */ echo "setting classpath via cmd ..."; $output = $ToolkitServiceObj->CLCommand("ADDENVVAR ENVVAR(CLASSPATH) VALUE('/home/adc/my.jar:/frog/...whatever makes you classes work')"); /* experiment 2: trying debug green screen (possibly system debugger gui) ... i did not try $output = $ToolkitServiceObj->CLCommand("ADDENVVAR ENVVAR(JAVA_TOOL_OPTIONS) VALUE('-debug')"); */ /* trying debug eclipse on port 8001 ... i did not try $output = $ToolkitServiceObj->CLCommand("ADDENVVAR ENVVAR(JAVA_TOOL_OPTIONS) VALUE('-Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y suspend=y')"); */ echo "calling java now ...\n"; $param = array(); $param[] = $ToolkitServiceObj->AddParameterChar ('both', 4096, 'INCHARA', 'var1', 'nothing'); $result = $ToolkitServiceObj->PgmCall('ZZJAVA2', 'XMLSERVICE', $param, null, null); var_dump($result);
raw xml: $ctl="*sqljava" or $ctl="*dbgjava" (port 30000) toolkit: 'customControl'=>'*sqljava' or 'customControl'=>'*dbgjava' (port 30000) example: // IBM i $conn = db2_connect($database,$user,$password); if (!$conn) die("Bad connect: $database,$user"); // java stored procedure $r = db2_exec($conn, "set schema xmlservice"); $r = db2_exec($conn, "create procedure gc() language java parameter style java external name 'java.lang.System.gc'"); $r = db2_exec($conn, "call gc()"); echo "java stored procedure rc=$r\n"; // java UDF $r = db2_exec($conn, "create function getProperty(prop varchar(1024)) returns varchar(1024) language java parameter style java external name 'java.lang.System.getProperty'"); $stmt = db2_exec($conn, "select getProperty('java.class.path') from sysibm.sysdummy1"); echo "java UDF procedure rc=$stmt\n"; while ($row = db2_fetch_array($stmt)) { var_dump($row); echo "\n"; } // java RPG w/java stored procedure $r = db2_exec($conn, "create procedure sleeper(millis BIGINT) language java parameter style java external name 'java.lang.Thread.sleep'"); // normal RPG java: 'customControl'=>'*java' -- set your own classpath // SP SQL java: 'customControl'=>'*sqljava' or 'customControl'=>'*dbgjava' -- your classpath ignored try { $ToolkitServiceObj = ToolkitService::getInstance($conn); } catch (Exception $e) { die($e->getMessage()); } $options = array('plugSize'=>'4K','customControl'=>'*sqljava','stateless'=>true); $ToolkitServiceObj->setToolkitServiceParams($options); $ms = 5000; // 5 seconds echo "java RPG w/java stored procedure now sleep($ms ms) ...\n"; $param = array(); $param[] = $ToolkitServiceObj->AddParameterInt32('both', "ms", "ms", $ms); $result = $ToolkitServiceObj->PgmCall('ZZJAVA', 'XMLSERVICE', $param, null, null); var_dump($result);
H AlwNull(*UsrCtl) D myfunc S 128A inz('jvmString') D makestring PR O EXTPROC(*JAVA: D 'java.lang.String': D *CONSTRUCTOR) D bytes 30A CONST VARYING D string S O CLASS(*JAVA:'java.lang.String') D Main PR ExtPgm('ZZJAVA2') D ms 40a *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * main(): Control flow *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ D Main PI D ms 40a /free string = makestring('TEST'); ms = 'TEST'; return; /end-free
$conn->setOptions(array('customControl' => '*java')
. Most notable, fix failures with RPG programs using new DB2 REST service, which uses java for REST functions. Using v5r4=true is no longer needed with this fix, therein xmlservice back on track to exclude v5r4=true/mode=‘opm’ in future enhancements. No perfect solution serves two masters flawlessly, there are restrictions, behavior changes, most notable sql naming default in java, but generally works. (Thanks Martin)// "create procedure sleeper(millis BIGINT) language java parameter style java external name 'java.lang.Thread.sleep'" // D Main PI // D ms 10i 0 // /free // Exec Sql call hats/sleeper(:ms); // return; // /end-free var xt = require('../lib/itoolkit'); var conf = require('../../config.js'); function cb(str) {console.log(str);} // {'ctl' : "*java" } (php $conn->setOptions(array('customControl' => '*java')); ) // *java mode, xmlservice does not own DB2 connection created by java opened PASE environment, // therefore xmlservice avoids executing 'change' operations on connection (attributes, free, etc.). // xmlservice toolkit default is system naming, wherein unqualified SQL operations use *libl, // *java mode default is sql naming, wherein *libl is ignored for unqualified SQL operations, // therefore users should expect *libl issues for some mixed DB2 script applications. var conn = new xt.iConn(conf.Database, conf.User, conf.Password, {'xslib':'XMLSERVICE', 'ctl' : '*java' }); var JavaMe = function(callback) { // ** call CMD chglib conn.add(xt.iCmd("CHGLIBL LIBL("+conf.DemoLib+") CURLIB("+conf.DemoLib+")")); // add chglibl to call // ** create the test java elements var sql = new xt.iSql(); sql.addQuery("set schema "+conf.DemoLib); // dunno why i need to do this (db2 bug i think) // ** java stored proc //sql.addQuery("create procedure gc() language java parameter style java external name 'java.lang.System.gc'"); //sql.free(); // ** java stored proc //sql.addQuery("create procedure sleeper(millis BIGINT) language java parameter style java external name 'java.lang.Thread.sleep'"); //sql.free(); // ** java UDF //sql.addQuery("create function getProperty(prop varchar(1024)) returns varchar(1024) language java parameter style java external name 'java.lang.System.getProperty'"); //sql.free(); //sql.addQuery("set current path "+conf.DemoLib); // ** call java stored proc sql.addQuery("call gc()"); sql.free(); // ** call java stored proc sql.addQuery("call sleeper(5000)"); sql.free(); // ** call java UDF sql.addQuery("select getProperty('java.home') from sysibm.sysdummy1"); sql.fetch(); sql.free(); conn.add(sql); // ** RPG program that calls java stored proc var pgm = new xt.iPgm("ZZJAVA",{"lib" : "XMLSERVICE"}); // , "mode": "opm" pgm.addParam(5000, "10i0"); // sleep for 5 seconds in java.lang.Thread.sleep conn.add(xt.iSh("hostname; date")); // start at ... conn.add(pgm); // add pgm to call conn.add(xt.iSh("hostname; date")); // ... run how long??? // ** check the joblog // conn.add('<diag/>'); // ** run xmlservice conn.run(callback); // call xmlservice and callcakc with answer } JavaMe(cb);
see: <overlay io="out" top="1" offset="myOffset2" dim='10' dou='prim' setnext='nextoff'> <ds> <data type='10i0' next='nextoff' comment='Offset to next library record'><![CDATA[...]]></data> example: </pgm> </script>string(4440) "<?xml version="1.0"?> <script> <pgm name='QSZRTVPR'> <parm io="both" comment='Receiver variable'> <ds comment='PRDR0200 Format' len='rec1'> <data type='10i0' comment='Bytes returned'><![CDATA[288]]></data> <data type='10i0' comment='Bytes available' ><![CDATA[288]]></data> <data type='10i0' comment='Reserved'><![CDATA[0]]></data> <data type='7A' comment='Product ID'><![CDATA[5770SS1]]></data> <data type='6A' comment='Release level'><![CDATA[V7R1M0]]></data> <data type='4A' comment='Product option'><![CDATA[0021]]></data> <data type='4A' comment='Load ID'><![CDATA[5050]]></data> <data type='10A' comment='Load type'><![CDATA[*CODE]]></data> <data type='10A' comment='Symbolic load state'><![CDATA[*INSTALLED]]></data> <data type='10A' comment='Load error indicator'><![CDATA[*NONE]]></data> <data type='2A' comment='Load state'><![CDATA[90]]></data> <data type='1A' comment='Supported flag'><![CDATA[0]]></data> <data type='2A' comment='Registration type'><![CDATA[04]]></data> <data type='14A' comment='Registration value'><![CDATA[1-800-IBM-SERV]]></data> <data type='2A' comment='Reserved'><![CDATA[]]></data> <data type='10i0' offset='myOffset' comment='beyond size of PRDR0100'><![CDATA[108]]></data> <data type='4A' comment='Primary language load identifier'><![CDATA[]]></data> <data type='6A' comment='Minimum target release'><![CDATA[V7R1M0]]></data> <data type='6A' comment='Minimum VRM of *BASE required'><![CDATA[V7R1M0]]></data> <data type='1A' comment='Requirements met between base'><![CDATA[1]]></data> <data type='3A' comment='Level'><![CDATA[L]]></data> <data type='2048h' comment='leave some space for PRDR0200'><![CDATA[0]]></data> </ds> </parm> <parm comment='Length of receiver variable'> <data type='10i0' setlen='rec1'><![CDATA[2156]]></data> </parm> <parm comment='Format name'> <data type='8A'><![CDATA[PRDR0200]]></data> </parm> <parm comment='Product information'> <data type='100A'><![CDATA[*OPSYS *CUR 0021*CODE]]></data> </parm> <parm io="both" comment='Error code'> <ds comment='Format ERRC0100' len='rec2'> <data type='10i0' comment='Bytes returned'><![CDATA[0]]></data> <data type='10i0' comment='Bytes available' setlen='rec2'><![CDATA[16]]></data> <data type='7A' comment='Exception ID'><![CDATA[]]></data> <data type='1A' comment='Reserved'><![CDATA[]]></data> </ds> </parm> <overlay io="out" top="1" offset='myOffset'> <ds> <data type='10A' comment='Second language library'><![CDATA[*NONE]]></data> <data type='2A' comment='Reserved'><![CDATA[]]></data> <data type='10i0' enddo='prim' comment='Number of Primary languages'><![CDATA[2]]></data> <data type='10i0' offset="myOffset2" comment='Offset to library records'><![CDATA[128]]></data> </ds> </overlay> <overlay io="out" top="1" offset="myOffset2" dim='10' dou='prim' setnext='nextoff'> <ds> <data type='10i0' next='nextoff' comment='Offset to next library record'><![CDATA[208]]></data> <data type='10A' comment='Primary library name'><![CDATA[QSYSLOCALE]]></data> <data type='10A' comment='Installed library name'><![CDATA[QSYSLOCALE]]></data> <data type='10A' comment='Library type'><![CDATA[*PROD]]></data> <data type='10A' comment='Library authority'><![CDATA[*USE]]></data> <data type='10A' comment='Library create authority'><![CDATA[*CHANGE]]></data> <data type='10A' comment='Postoperation exit program name'><![CDATA[QLGMRM2]]></data> <data type='10i0' comment='Number of preoperation exit program names'><![CDATA[1]]></data> <data type='10A' comment='Preoperation exit program names'><![CDATA[QLGMRM1]]></data> </ds> </overlay> <overlay io="out" top="1" offset="myOffset2" dim='10' dou='prim' setnext='nextoff'> <ds> <data type='10i0' next='nextoff' comment='Offset to next library record'><![CDATA[0]]></data> <data type='10A' comment='Primary library name'><![CDATA[QSYSNLS]]></data> <data type='10A' comment='Installed library name'><![CDATA[QSYSNLS]]></data> <data type='10A' comment='Library type'><![CDATA[*PROD]]></data> <data type='10A' comment='Library authority'><![CDATA[*USE]]></data> <data type='10A' comment='Library create authority'><![CDATA[*CHANGE]]></data> <data type='10A' comment='Postoperation exit program name'><![CDATA[QLGMRM4]]></data> <data type='10i0' comment='Number of preoperation exit program names'><![CDATA[1]]></data> <data type='10A' comment='Preoperation exit program names'><![CDATA[QLGMRM3]]></data> </ds> </overlay> <success><![CDATA[+++ success QSZRTVPR]]></success> </pgm> </script>"
see below: <overlay io="both" top="1" offset="myOffset2" dim='2' dou='prim'> string(3575) "<?xml version="1.0"?> <script> <pgm name='QSZRTVPR'> <parm io="both" comment='Receiver variable'> <ds comment='PRDR0200 Format' len='rec1'> <data type='10i0' comment='Bytes returned'><![CDATA[216]]></data> <data type='10i0' comment='Bytes available' ><![CDATA[216]]></data> <data type='10i0' comment='Reserved'><![CDATA[0]]></data> <data type='7A' comment='Product ID'><![CDATA[5770SS1]]></data> <data type='6A' comment='Release level'><![CDATA[V7R1M0]]></data> <data type='4A' comment='Product option'><![CDATA[0033]]></data> <data type='4A' comment='Load ID'><![CDATA[5111]]></data> <data type='10A' comment='Load type'><![CDATA[*CODE]]></data> <data type='10A' comment='Symbolic load state'><![CDATA[*INSTALLED]]></data> <data type='10A' comment='Load error indicator'><![CDATA[*ERROR]]></data> <data type='2A' comment='Load state'><![CDATA[67]]></data> <data type='1A' comment='Supported flag'><![CDATA[0]]></data> <data type='2A' comment='Registration type'><![CDATA[04]]></data> <data type='14A' comment='Registration value'><![CDATA[1-800-IBM-SERV]]></data> <data type='2A' comment='Reserved'><![CDATA[]]></data> <data type='10i0' offset='myOffset' comment='beyond size of PRDR0100'><![CDATA[108]]></data> <data type='4A' comment='Primary language load identifier'><![CDATA[2924]]></data> <data type='6A' comment='Minimum target release'><![CDATA[V7R1M0]]></data> <data type='6A' comment='Minimum VRM of *BASE required'><![CDATA[*MATCH]]></data> <data type='1A' comment='Requirements met between base'><![CDATA[1]]></data> <data type='3A' comment='Level'><![CDATA[L]]></data> <data type='1024h' comment='leave some space for PRDR0200'><![CDATA[0]]></data> </ds> </parm> <parm comment='Length of receiver variable'> <data type='10i0' setlen='rec1'><![CDATA[1132]]></data> </parm> <parm comment='Format name'> <data type='8A'><![CDATA[PRDR0200]]></data> </parm> <parm comment='Product information'> <data type='100A'><![CDATA[*OPSYS *CUR 0033*CODE]]></data> </parm> <parm io="both" comment='Error code'> <ds comment='Format ERRC0100' len='rec2'> <data type='10i0' comment='Bytes returned'><![CDATA[0]]></data> <data type='10i0' comment='Bytes available' setlen='rec2'><![CDATA[16]]></data> <data type='7A' comment='Exception ID'><![CDATA[]]></data> <data type='1A' comment='Reserved'><![CDATA[]]></data> </ds> </parm> <overlay io="both" top="1" offset='myOffset'> <ds> <data type='10A' comment='Second language library'><![CDATA[*NONE]]></data> <data type='2A' comment='Reserved'><![CDATA[]]></data> <data type='10i0' enddo='prim' comment='Number of Primary languages'><![CDATA[1]]></data> <data type='10i0' offset="myOffset2" comment='Offset to library records'><![CDATA[128]]></data> </ds> </overlay> <overlay io="both" top="1" offset="myOffset2" dim='2' dou='prim'> <ds> <data type='10i0' comment='Offset to next library record'><![CDATA[0]]></data> <data type='10A' comment='Primary library name'><![CDATA[QPASE]]></data> <data type='10A' comment='Installed library name'><![CDATA[QPASE]]></data> <data type='10A' comment='Library type'><![CDATA[*PROD]]></data> <data type='10A' comment='Library authority'><![CDATA[*USE]]></data> <data type='10A' comment='Library create authority'><![CDATA[*CHANGE]]></data> <data type='10A' comment='Postoperation exit program name'><![CDATA[QP2EXMRM]]></data> <data type='10i0' comment='Number of preoperation exit program names'><![CDATA[2]]></data> <data type='10A' comment='Preoperation exit program names'><![CDATA[QP2EXMRM]]></data> </ds> </overlay> <success><![CDATA[+++ success QSZRTVPR]]></success> </pgm> </script>"
<ds ... <ds dim=50> <ds dim='7000' dou='SV07Size' array='on'> </ds> </ds> ../ds> This latest performance improvement is essentially loop dup memory dim='1' beg/end location of first pass of by-ref values, copied dim='n-1' times (cpybytes). This dup loop input method is most effective when using output side dou/enddo labels provided by xmlservice and PHP toolkit, where, all data initialized (call input), but fewer output (call result).
Fixed ... <prepare>select * from animals where NAME LIKE ?</prepare> <execute> <parm>Pea%<parm> </execute>
null='on'
under 32K size LOBs (corrected XML format)Fixed ... <query conn='conn1' stmt='stmt1'> <success><![CDATA[+++ success CREATE TABLE TESTN (COL1 CLOB (16000 ), COL2 CLOB (16000 ))]]></success> </query> <query conn='conn1' stmt='stmt1'> <success><![CDATA[+++ success insert into TESTN values(NULL,NULL)]]></success> </query> <query conn='conn1' stmt='stmt1'> <success><![CDATA[+++ success select col1 from TESTN]]></success> </query> <fetch block='all' desc='on' stmt='stmt1'> <row><data desc='COL1' null='on'><![CDATA[]]></data></row> <success><![CDATA[+++ success stmt1]]></success> </fetch>
<data>junk</data>
<fetch> <row><data desc='NAME' null='on'></data><data desc='ID' null='on'>0</data></row> </fetch>
<fetch> <row><data desc='NAME'>Bee</data><data desc='ID'>3</data></row> <row><data desc='NAME' null='on'></data><data desc='ID'>21</data></row> </fetch>
bash-3.00$ cat ibm_i.ini extension=ibm_i.so ibm_i.pgm_name="XMLSERVICE/XMLSTOREDP" ibm_i.func_name="RUNASCII" ibm_i.profile_reset=true
<query>SELECT 1 + 1 as test from library/table</query> The '+' was mistaken removed by http-based driver interface (apache xmlcgi). Issue ONLY REST interface xmlcgi (rare use), most often RAW XML, not DB2-based interface on majority sites (Toolkit).
$per = "myconn"; // ten character id -- only works when current user/pwd match 'persis' key if ($per) { $data = array( 'db2' => "*LOCAL", 'uid' => $user, 'pwd' => $password, 'ipc' => $ipc, 'ctl' => $ctl, 'xmlin' => $clobIn, 'xmlout' => 4096, // size expected XML output 'persis' => $per // persistent connection ); } else { $data = array( 'db2' => "*LOCAL", 'uid' => $user, 'pwd' => $password, 'ipc' => $ipc, 'ctl' => $ctl, 'xmlin' => $clobIn, 'xmlout' => 4096 // size expected XML output ); } $postdata = http_build_query($data); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context = stream_context_create($opts); $clobOut = file_get_contents($i5resturl, false, $context);
qsh -c /qsys.lib/xmlservice.lib/xmlver.pgm XML Toolkit 1.8.0-sg6
RAW XML Interface (available 1.7.6-sg2) ... $ctl .= " *pase(1208)"; Toolkit interface ... try { $ToolkitServiceObj = ToolkitService::getInstance($database, $user, $password); } catch (Exception $e) { die($e->getMessage()); } $ToolkitServiceObj->setToolkitServiceParams( array('InternalKey'=>$ipc, // route to same XMLSERVICE job /tmp/myjob1 'subsystem'=>"QGPL/QDFTJOBD", // subsystem/jobd to start XMLSERVICE (if not running) 'plug'=>"iPLUG5M", // max size data i/o (iPLUG4K,32K,65K, 512K,1M,5M,10M,15M) 'customControl' => '*pase(1208)'));// 1208 CCSID $Rows = $ToolkitServiceObj->CLInteractiveCommand("wrkactjob"); if(!$Rows) die("Failure: ".$ToolkitServiceObj->getLastError()); var_dump($Rows);
For Sam ... library: ZENDSVR6 clp: crtxml6 -> crtsql6 rpg: plugconf6.rpgle * RPG CLI call stored procedures (xmlcgi) D PLUGCALLSP c const('CALL ZENDSVR6.') * spawn config PLUGSPNLIB/PLUGSPNPGM (plugipc) D PLUGSPNPGM c const('XMLSERVICE.PGM') D PLUGSPNDIR c const('/QSYS.LIB/ZENDSVR6.LIB/') * sbmjob config (plugipc) D PLUGSBMLIB c const('ZENDSVR6') D PLUGSBMPGM c const('XMLSERVICE') * was QGPL/QDFTJOBD D PLUGJOBLIB c const('ZENDSVR6') D PLUGJOBD c const('ZSVR_JOBD') <---- is this correct ??? D PLUGJOBNAM c const('XTOOLKIT') D PLUGJOBASP c const(*BLANKS)
FIX is for Alan 1.3.0 name case ... This format works: <pgm name='ZSXMLSRV' lib='ZENDSVR' func='RTVSYSVAL'> but this format does not: <pgm> <name>ZSXMLSRV</name> <lib>ZENDSVR</lib> <func>RTVSYSVAL</func> ... with 1.7.5-sg3 both formats working
$clob .= "<parm comment='wsopstdcnt'><data var='wsopstdcnt' type='3s0' enddo='wsopstdcnt'/></parm>"; $clob .= "<parm comment='findMe1'>"; $clob .= " <ds var='findMe1' data='records'>"; $clob .= " <ds var='dcRec1_t' array='on'>"; $clob .= " <ds var='dcRec1_t'>"; $clob .= " <data var='dcMyName1' type='10A'/>"; $clob .= " <ds var='dcRec2_t'>"; $clob .= " <data var='dcMyName2' type='10A'/>"; $clob .= " <ds var='dcRec3_t'>"; $clob .= " <data var='dcMyName3' type='10A'/>"; $clob .= " <ds var='dcRec_t' dim='999' dou='wsopstdcnt'>"; $clob .= " <data var='dcMyName' type='10A'/>"; $clob .= " <data var='dcMyJob' type='4096A'/>"; $clob .= " <data var='dcMyRank' type='10i0'/>"; $clob .= " <data var='dcMyPay' type='12p2'/>"; $clob .= " </ds>"; $clob .= " </ds>"; $clob .= " </ds>"; $clob .= " </ds>"; $clob .= " </ds>"; $clob .= " </ds>"; $clob .= "<records delimit=':'>"; $clob .= ":Ranger:B:Good"; for ($i=0; $i<$max; $i++) $clob .= ":nada{$i}:nada{$i}:1:1.1"; $clob .= ":</records>"; $clob .= "</parm>";
$this->AddRecord(':::143.43:My2'); $ds = array(':::143.43:My2', ':Tuno be 2:Toim be 2:143.43:My2::::143.43:My2'; $this->AddRecord($ds); -- or -- maybe something with just PHP arrays and you do the delimted record in/out (people seem to enjoy arrays)
* output (incompatible change hex/ccsid 1.7.4+): * <cmd exec='rexx' hex='on' before='819/37' after='37/819'> * <success><![CDATA[+++ success RTVJOBA USRLIBL(?) SYSLIBL(?)]]></success> * <row><data desc='USRLIBL'><hex><![CDATA[5147504C20202020202020]]></hex></data></row> * <row><data desc='SYSLIBL'><hex><![CDATA[5153595320202020202020]]></hex></data></row> * </cmd> * output (incompatible change hex/ccsid 1.7.4+): * <sh rows='on' hex='on' before='819/37' after='37/819'> * <row><hex>746F74616C2031363636313034</hex></row> * </sh> * output (rows='off' 1.7.4+): * <sh hex='on' before='819/37' after='37/819'> * <hex>746F74616C2031363636313034</hex> * </sh>
toolkit.ini | XMLSERVICE | Description |
error=full | Stop the XML script processing ... <pgm ... error='on'> - default <cmd ... error='on'> <sh ... error='on'> | Stop XML parsing and report full error ... <?xml version='1.0' encoding='ISO-8859-1' ?> <report> <version>XML Toolkit 1.7.4-sg3</version> <error> ... part 1) all normal records ... </error> <jobinfo> ... part 2) all normal records ... </jobinfo> <joblogscan> <joblogrec> ... part 3) all normal records ... </joblogrec> </joblogscan> <joblog job='XTOOLKIT' user='DB2' nbr='745657'> ... part 4) all normal records ... </joblog> </report> |
error=partial | Continue XML parsing and report partial error ... <pgm ... error='off'> <cmd ... error='off'> - default <sh ... error='off'> - default | Continue XML parsing and report partial error ... <?xml version='1.0' encoding='ISO-8859-1' ?> <script> <pgm ... or cmd ... or sh ... > <error> ... part 1) all normal records ... </error> <jobinfo> ... part 2) all normal records ... </jobinfo> <joblogscan> <joblogrec> ... part 3) subset normal records ... </joblogrec> </joblogscan> <joblog job='XTOOLKIT' user='DB2' nbr='745657'> ... part 4) subset normal records ... </joblog> </pgm ... or /cmd ... or /sh ...> |
error=fast | Continue XML parsing and report minimum error ... <pgm ... error='fast'> <cmd ... error='fast'> <sh ... error='fast'> | Continue XML parsing and report minimum error ... <?xml version='1.0' encoding='ISO-8859-1' ?> <script> <pgm ... or cmd ... or sh ... > <error> ... part 1) all normal records ... </error> <jobinfo> ... part 2) all normal records ... </jobinfo> </pgm ... or /cmd ... or /sh ...> |
Example: adopt authority cw layer fails/hangs (could also be bad ds, etc.) XMLSERVICE undesirable trim of returned binary data type (type='12b'). QSYGETPH 00000000196B67A08AA2540 <-- good handle in log QSYSGETPH QWTSETP 0000000196B679D8787E500 <-- this actually returned to CW/PHP layer, which fails subsequent use QWTSETP (+ 30 seconds of pain +) ... x'40' (ebcdic space) trimmed by MISTAKE/ERROR in xmlservice code ... resulting in invalid handle ... resulting in 30 second invalid "attack delay" ... appears random because has to end with any trim combination of x'40', x'4000' ... etc. ... fix in SG6
Example: mismatch autocommit logging vs. user script <?xml version='1.0'?> <script> <sql> <free/> <options options='noauto' autocommit='off'/> <connect conn='myconn' options='noauto'/> <query conn='myconn' stmt='myupdate'>UPDATE animal SET id = 9 where ID = 3</query> <query conn='myconn' stmt='myselect'>select count(*) from animal where ID = 9</query> <fetch stmt='myselect' block='all' desc='off'/> <free stmt='myselect'/> <commit conn='myconn' action='rollback'/> <query conn='myconn' stmt='myselect'>select count(*) from animal where ID = 9</query> <fetch stmt='myselect' block='all' desc='off'/> <free/> </sql> </script>
PHP TOOLKIT toolkit.ini trace=true
RAW XML * -- log to database file -- * *log[(key)] * - log records into database * *nolog * - no log records into database (default) * Note: * - *log key is unique allowing both PHP and XMLSERVICE * to record event log data and produce queries of collected * reports. * Log file layout: * create table XMLSERVLOG/LOG ( * key varchar(64) NOT NULL WITH DEFAULT, * log TIMESTAMP NOT NULL WITH DEFAULT, * text varchar(64) NOT NULL WITH DEFAULT) * Supplemental log dump XML data layout: * create table XMLSERVLOG/DUMP ( * key varchar(64) NOT NULL WITH DEFAULT, * log TIMESTAMP NOT NULL WITH DEFAULT, * text clob(15M) NOT NULL WITH DEFAULT) * - programers/vendors can alter xmlservice log database * with plugconf1-3 (or custom)
* <sh [rows='on|off' * hex='on' before='cc1/cc2/cc3/cc4' after='cc4/cc3/cc2/cc1'] * >(PASE utility)</sh>
************************************************************************* * start/use/stop exclusive use shared IPC (hotel reservation): * <start>KEY</start> - acquire IPC -- first request * <use>KEY</use> - match IPC -- each request * <stop>KEY</stop> - release IPC -- last request * Where KEY anything managed by user (key-2-IPC session data) ... * ... random based key -- scaling open any users, * want benefit of private RPG call (open files, etc), * do not care about reservation multi-request transaction * -> hybrid stateless/private call, * hold IPC for life of script only and release, * but limit jobs * ... user based key -- scaling come/go users, * want benefit of private RPG call (open files, etc), * also want reservation transactions * -> hybrid persistent/private, * transaction across multi-request (browser clicks), * but limited jobs * ... task based key -- everyone uses same task/tasks * limited pool jobs and all must wait a turn * -> hybrid private/persistent with pre-start pool, * transaction across multi-request (browser clicks), * load balancing design to limit machine stress * example many requests exclusive use IPC * -- no time out -- * $ctl .= " *idle(0)" * -- request 1 -- * <?xml version="1.0"?> * <script> * <start>unique-user-key</start> * </script> * -- request 2 (two minutes later) -- * <?xml version="1.0"?> * <script> * <use>unique-user-key</use> * <cmd exec='rexx'>RTVJOBA USRLIBL(?)</cmd> * </script> * -- request 3 (1/2 hour later) -- * <?xml version="1.0"?> * <script> * <use>unique-user-key</use> * <pgm name='ZZCALL'> * <parm> * <data type='1A'>a</data> * </parm> * <return> * <data type='10i0'>0</data> * </return> * </pgm> * </script> * -- request n (2 hours later) -- * <?xml version="1.0"?> * <script> * <stop>unique-user-key</stop> * </script> * Note: * - <start>unique-user-key</start> * acquire exclusive IPC if available, * - <use>unique-user-key</use> * must appear XML every request * job held forever until see <stop> * - <stop>unique-user-key</stop> * release IPC for any other use * - <start>no-match-key</start> * or <use>unique-user-key</use> * non-matching key results in error * almost instantly (no wait) * busy response (1301060): * <error> * <errnoxml>1301060</errnoxml> * <xmlerrmsg>IPC owner busy</xmlerrmsg> * </error> * - thoughtful setting server idle timeout * can control unwanted reservation hangs * due to careless users or errors * $ctl .= " *idle(60)" *************************************************************************
use EITHER format ... <pgm name='fredflin' ... ... but added additional full control option names where names are converted following up to 4 conversions ccsid before attempting to resolve IBM i object name (Alan to wrapper CW/Toolkit) ... <pgm mode='opm|ile'> <name hex='on' before='cc1/cc2/cc3/cc4'>bin2hex('&fredflin')</name> <lib hex='on' before='cc1/cc2/cc3/cc4'>bin2hex('omlated')</lib> <func hex='on' before='cc1/cc2/cc3/cc4'>bin2hex('me&proc')</func> <parm> data ... already available for by user hand ccsid (Alan to wrapper CW/Toolkit) .... <data type='nnnA' hex='on' before='cc1/cc2/cc3/cc4' after='cc4/cc3/cc2/cc1'>bin2hex('ascii_raw_chars')</data> </parm> </pgm>
SYNTAX: <cmd [exec='cmd|system|rexx' hex='on' before='cc1/cc2/cc3/cc4' after='cc4/cc3/cc2/cc1']> INPUT XML: $clob = "<?xml version='1.0'?>\n"; $clob .= "<script>\n"; $clob .= "<cmd exec='rexx' hex='on' before='819/37' after='37/819'>"; $clob .= bin2hex("RTVJOBA USRLIBL(?) SYSLIBL(?)"); $clob .= "</cmd>\n"; $clob .= "</script>\n"; ... make call xmlservice (same as always) ... // dump raw XML (easy test debug) var_dump($clobOut); $xmlobj = simplexml_load_string($clobOut); if (!$xmlobj) die("Bad XML output"); // expected $clobOut = pack("H*",(string)$xmlobj->cmd->hex); var_dump($clobOut); OUTPUT XML (note hex return appears <cmd>...<hex>...</hex></cmd>): string(527) "<?xml version='1.0'?> <script> <cmd exec='rexx' hex='on' before='819/37' after='37/819'><success>+++ success RTVJOBA USRLIBL(?) SYSLIBL(?)</success><hex>3C726F773E0A3C6461746120646573633D275553524C49424C273E5147504C202020202020205154454D5020202020202051444556454C4F5020202051424C445359532020202051424C44535953523C2F646174613E0A3C2F726F773E0A3C726F773E0A3C6461746120646573633D275359534C49424C273E5153595320202020202020515359533220202020202051484C5053595320202020515553525359533C2F646174613E0A3C2F726F773E0A</hex></cmd> </script>" string(176) "<row> <data desc='USRLIBL'>QGPL QTEMP QDEVELOP QBLDSYS QBLDSYSR</data> </row> <row> <data desc='SYSLIBL'>QSYS QSYS2 QHLPSYS QUSRSYS</data> </row>
<pgm name='ZZSHLOMO' lib='XMLSERVICE' mode='opm'>
v5r4=true
Example: grep -i qtm means ipcrm for (QTM)HHTTP ... endTCPSVR SERVER(*HTTP) INSTANCE(ZENDSVR) -- suggest end web server call qp2term > ipcs | grep -i qtm | awk '{print "ipcrm -" tolower($1) " "$2}' -- show action, but NOT do action > ipcs | grep -i qtm | awk '{print "ipcrm -" tolower($1) " "$2}' | sh -- remove semaphores/shared memory strTCPSVR SERVER(*HTTP) INSTANCE(ZENDSVR) -- suggest start web server
<data type='nnnA' hex='on' before='cc1/cc2/cc3/cc4' after='cc4/cc3/cc2/cc1'>bin2hex('ascii_raw_chars')</data>
Note: The classification of BUG vs. NEW is more a statement of work item for the authors, so please feel free to consider a new feature a bug if missing (most people do)
4. Create xmlservice RPG programs (test/production) > ADDLIBLE XMLSERVICE -- test version XMLSERVICE library (will NOT update zend production ZENDSVR library) --- > CRTCLPGM PGM(XMLSERVICE/CRTXML) SRCFILE(XMLSERVICE/QCLSRC) > call crtxml Note redistribution: - ONLY redistribute SAVOBJ/RSTOBJ to XMLSERVICE library will NOT work to RSTOBJ into ZENDSVR library will break your production toolkit (hang/busy) - stored procedures are automatically updated on SAVOBJ/RSTOBJ XMLSERVICE library via Program Associated Space (not need crtsql) - XMLSERVICE lib objects: XMLSERVICE, XMLSTOREDP, XMLCGI, XMLMAIN (again do NOT RSTOBJ into ZENDSVR library) -- or update zend production ZENDSVR library -- > CRTCLPGM PGM(XMLSERVICE/CRTXML2) SRCFILE(XMLSERVICE/QCLSRC) > call crtxml2 Note redistribution: - ONLY redistribute SAVOBJ/RSTOBJ to ZENDSVR library will NOT work to RSTOBJ into XMLSERVICE library will break your test toolkit (hang/busy) - stored procedures are automatically updated on SAVOBJ/RSTOBJ ZENDSVR library via Program Associated Space (not need crtsql2) - ZENDSVR lib objects: XMLSERVICE, XMLSTOREDP, XMLCGI, XMLMAIN (again do NOT RSTOBJ into XMLSERVICE library)