{"id":432,"date":"2019-07-08T13:47:40","date_gmt":"2019-07-08T13:47:40","guid":{"rendered":"http:\/\/www.hammerdb.com\/blog\/?p=432"},"modified":"2019-07-08T13:48:01","modified_gmt":"2019-07-08T13:48:01","slug":"using-hammerdb-as-a-web-service","status":"publish","type":"post","link":"https:\/\/www.hammerdb.com\/blog\/uncategorized\/using-hammerdb-as-a-web-service\/","title":{"rendered":"Using HammerDB as a Web Service"},"content":{"rendered":"\n<p>HammerDB already has 2 interfaces with which to interface with the commands to build and test databases using the GUI interface or CLI. From HammerDB version 3.2 there is an additional interface that enables HammerDB to run as Web Service. This allows HammerDB to be driven with a REST type client using a HTTP interface to call and retrieve output from the CLI commands.\u00a0 Additional\u00a0 json, rest and huddle packges have been added with which to format and process input and output.\u00a0 This interface can be started using the hammerdbws command at which hammerdb will proceed to listen on a predefined port. (see the documentation for setting the port).\u00a0<\/p>\n<pre>$ .\/hammerdbws <br \/>HammerDB Web Service v3.2<br \/>Copyright (C) 2003-2019 Steve Shaw<br \/>Type \"help\" for a list of commands<br \/>The xml is well-formed, applying configuration<br \/>Initialized new SQLite in-memory database<br \/>Starting HammerDB Web Service on port 8080<br \/>Listening for HTTP requests on TCP port 8080<\/pre>\n<p>Using a browser to navigate to that port will show the help screen.<\/p>\n<p><a href=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsapi.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-434\" src=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsapi.png\" alt=\"\" width=\"782\" height=\"493\" srcset=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsapi.png 782w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsapi-300x189.png 300w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsapi-768x484.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>It is important to note that scripts written to drive this interface can be written in any language of choice. When using TCL the additional packages provided can be used for formatting. The following test script shows how this interaction can be done also including deliberate errors to demonstrate error handling.<\/p>\n<pre><br \/>$ more restchk.tcl <br \/>#!\/bin\/sh<br \/>#########################################################################<br \/>## \\<br \/>export LD_LIBRARY_PATH=.\/lib:$LD_LIBRARY_PATH<br \/>## \\<br \/>export PATH=.\/bin:$PATH<br \/>## \\<br \/>exec .\/bin\/tclsh8.6 \"$0\" ${1+\"$@\"}<br \/>########################################################################<br \/>set UserDefaultDir [ file dirname [ info script ] ]<br \/>::tcl::tm::path add \"$UserDefaultDir\/modules\"<br \/>package require rest<br \/>package require huddle<br \/>puts \"TEST DIRECT PRINT COMMANDS\"<br \/>#clear any existing script<br \/>set res [rest::post http:\/\/localhost:8080\/clearscript \"\" ]<br \/>puts \"--------------------------------------------------------\"<br \/>foreach i {db bm dict script vuconf vucreated vustatus datagen}  {<br \/>puts \"Printing output for $i and converting JSON to text\"<br \/>    set res [rest::get http:\/\/localhost:8080\/$i \"\" ]<br \/>puts \"JSON format\"<br \/>puts $res<br \/>puts \"TEXT format\"<br \/>    set res [rest::format_json $res]<br \/>    puts $res<br \/>}<br \/>puts \"--------------------------------------------------------\"<br \/>puts \"PRINT COMMANDS COMPLETE\"<br \/>puts \"--------------------------------------------------------\"<br \/>puts \"TEST PRINT COMMANDS AS OPTION TO PRINT ie print?dict \"<br \/>foreach i {db bm dict script vuconf vucreated vustatus datagen}  {<br \/>puts \"Printing output for $i and converting JSON to text\"<br \/>    set res [rest::get http:\/\/localhost:8080\/print?$i \"\" ]<br \/>puts \"JSON format\"<br \/>puts $res<br \/>puts \"TEXT format\"<br \/>    set res [rest::format_json $res]<br \/>    puts $res<br \/>}<br \/>puts \"PRINT COMMANDS COMPLETE\"<br \/>puts \"--------------------------------------------------------\"<br \/>puts \"TEST DISET\"<br \/>puts \"Setting Warehouse Count to 800\"<br \/>set body { \"dict\": \"tpcc\", \"key\": \"count_ware\", \"value\": \"800\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/><br \/>puts \"Setting password to new password\"<br \/>set body { \"dict\": \"tpcc\", \"key\": \"tpcc_pass\", \"value\": \"new_password\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/><br \/>puts \"Setting password error 1 invalid string\"<br \/>set body { \"dict\": \"tpcc\", \"ke }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/>puts $res<br \/><br \/>puts \"Setting password error 2 invalid number of arguments\"<br \/>set body { \"dict\": \"tpcc\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/>puts $res<br \/><br \/>puts \"Setting password error 3 invalid key\"<br \/>set body { \"dict\": \"tpcc\", \"key\": \"tpcds_pass\", \"value\": \"new_password\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/>puts $res<br \/><br \/>puts \"Setting password error 4 invalid string\"<br \/>set body { \"dict\": \"tpcfg\", \"key\": \"tpcds_pass\", \"value\": \"new_password\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/>puts $res<br \/><br \/>puts \"Setting Driver Script\"<br \/>set body { \"dict\": \"tpcc\", \"key\": \"ora_driver\", \"value\": \"timed\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/>puts $res<br \/><br \/>puts \"Setting Driver Script Error\"<br \/>set body { \"dict\": \"tpcc\", \"key\": \"ora_driver\", \"value\": \"timid\" }<br \/>    set res [rest::post http:\/\/localhost:8080\/diset $body ]<br \/>puts $res<br \/><br \/>puts \"Clearscript\"<br \/>    set res [rest::post http:\/\/localhost:8080\/clearscript \"\" ]<br \/>puts $res<br \/><br \/>puts \"Loadscript\"<br \/>    set res [rest::post http:\/\/localhost:8080\/loadscript \"\" ]<br \/>puts $res<br \/>    set res [rest::get http:\/\/localhost:8080\/print?script \"\" ]<br \/>#uncomment to print script<br \/>#puts $res<br \/>puts \"Script in TEXT format\"<br \/>    set res [rest::format_json $res]<br \/>#uncomment to print script<br \/>#puts $res<br \/><br \/>puts \"VU Status\"<br \/>    set res [rest::get http:\/\/localhost:8080\/vustatus \"\" ]<br \/>puts $res<br \/><br \/>puts \"Testing dbset\"<br \/>set body { \"db\": \"mssqs\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/dbset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing dbset\"<br \/>set body { \"dx\": \"mssqls\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/dbset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing dbset\"<br \/>set body { \"db\": \"pg\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/dbset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing dbset\"<br \/>set body { \"bm\": \"TPC-X\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/dbset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing dbset\"<br \/>set body { \"bm\": \"TPC-H\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/dbset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing vuset\"<br \/>set body { \"vuxx\": \"109\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/vuset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing vuset\"<br \/>set body { \"vu\": \"10\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/vuset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing dgset\"<br \/>set body { \"directory\": \"\/home\/oracle\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/dgset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing Custom Script : Open File convert to JSON and post\"<br \/>set customscript \"testscript.tcl\"<br \/>set _ED(file) $customscript<br \/>if {$_ED(file) == \"\"} {return}<br \/>    if {![file readable $_ED(file)]} {<br \/>        puts \"File \\[$_ED(file)\\] is not readable.\"<br \/>        return<br \/>    }<br \/>if {[catch \"open \\\"$_ED(file)\\\" r\" fd]} {<br \/>      puts \"Error while opening $_ED(file): \\[$fd\\]\"<br \/>        } else {<br \/> set _ED(package) \"[read $fd]\"<br \/>    close $fd<br \/>\t}<br \/>set huddleobj [ huddle compile {string} \"$_ED(package)\" ]<br \/>set jsonobj [ huddle jsondump $huddleobj ]<br \/>set body [ subst { {\"script\": $jsonobj}} ]<br \/>set res [ rest::post http:\/\/localhost:8080\/customscript $body ] <br \/>puts $res<br \/>    set res [rest::get http:\/\/localhost:8080\/print?script \"\" ]<br \/>#uncomment to print script<br \/>#puts $res<br \/>puts \"Custom Script in TEXT format\"<br \/>    set res [rest::format_json $res]<br \/>#uncomment to print script in text<br \/>#puts $res<br \/><br \/>puts \"Testing vuset\"<br \/>set body { \"vu\": \"5\" }<br \/>    set res [ rest::post http:\/\/localhost:8080\/vuset $body ] <br \/>puts $res<br \/><br \/>puts \"Testing vucreate\"<br \/>    set res [ rest::post http:\/\/localhost:8080\/vucreate \"\" ] <br \/>puts $res<br \/><br \/>puts \"Testing vucreate\"<br \/>    set res [ rest::post http:\/\/localhost:8080\/vucreate \"\" ] <br \/>puts $res<br \/><br \/>puts \"VU Status after create\"<br \/>    set res [rest::get http:\/\/localhost:8080\/vustatus \"\" ]<br \/>puts $res<br \/><br \/>puts \"Testing vudestroy\"<br \/>    set res [ rest::post http:\/\/localhost:8080\/vudestroy \"\" ] <br \/>puts $res<br \/><br \/>puts \"VU Status after destroy\"<br \/>    set res [rest::get http:\/\/localhost:8080\/vustatus \"\" ]<br \/>puts $res<\/pre>\n<p>Running this script shows the following output.<\/p>\n<pre>$ .\/restchk.tcl <br \/>TEST DIRECT PRINT COMMANDS<br \/>--------------------------------------------------------<br \/>Printing output for db and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"ora\": \"Oracle\",<br \/>  \"mssqls\": \"MSSQLServer\",<br \/>  \"db2\": \"Db2\",<br \/>  \"mysql\": \"MySQL\",<br \/>  \"pg\": \"PostgreSQL\",<br \/>  \"redis\": \"Redis\"<br \/>}<br \/>TEXT format<br \/>ora Oracle mssqls MSSQLServer db2 Db2 mysql MySQL pg PostgreSQL redis Redis<br \/>Printing output for bm and converting JSON to text<br \/>JSON format<br \/>{\"benchmark\": \"TPC-C\"}<br \/>TEXT format<br \/>benchmark TPC-C<br \/>Printing output for dict and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"connection\": {<br \/>    \"system_user\": \"system\",<br \/>    \"system_password\": \"manager\",<br \/>    \"instance\": \"oracle\",<br \/>    \"rac\": \"0\"<br \/>  },<br \/>  \"tpcc\": {<br \/>    \"count_ware\": \"1\",<br \/>    \"num_vu\": \"1\",<br \/>    \"tpcc_user\": \"tpcc\",<br \/>    \"tpcc_pass\": \"tpcc\",<br \/>    \"tpcc_def_tab\": \"tpcctab\",<br \/>    \"tpcc_ol_tab\": \"tpcctab\",<br \/>    \"tpcc_def_temp\": \"temp\",<br \/>    \"partition\": \"false\",<br \/>    \"hash_clusters\": \"false\",<br \/>    \"tpcc_tt_compat\": \"false\",<br \/>    \"total_iterations\": \"1000000\",<br \/>    \"raiseerror\": \"false\",<br \/>    \"keyandthink\": \"false\",<br \/>    \"checkpoint\": \"false\",<br \/>    \"ora_driver\": \"test\",<br \/>    \"rampup\": \"2\",<br \/>    \"duration\": \"5\",<br \/>    \"allwarehouse\": \"false\",<br \/>    \"timeprofile\": \"false\"<br \/>  }<br \/>}<br \/>TEXT format<br \/>connection {system_user system system_password manager instance oracle rac 0} tpcc {count_ware 1 num_vu 1 tpcc_user tpcc tpcc_pass tpcc tpcc_def_tab tpcctab tpcc_ol_tab tpcctab tpcc_def_temp temp partition false hash_clusters false tpcc_tt_compat false total_iterations 1000000 raiseerror false keyandthink false checkpoint false ora_driver test rampup 2 duration 5 allwarehouse false timeprofile false}<br \/>Printing output for script and converting JSON to text<br \/>JSON format<br \/>{\"error\": {\"message\": \"No Script loaded: load with loadscript\"}}<br \/>TEXT format<br \/>error {message {No Script loaded: load with loadscript}}<br \/>Printing output for vuconf and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"Virtual Users\": \"1\",<br \/>  \"User Delay(ms)\": \"500\",<br \/>  \"Repeat Delay(ms)\": \"500\",<br \/>  \"Iterations\": \"1\",<br \/>  \"Show Output\": \"1\",<br \/>  \"Log Output\": \"0\",<br \/>  \"Unique Log Name\": \"0\",<br \/>  \"No Log Buffer\": \"0\",<br \/>  \"Log Timestamps\": \"0\"<br \/>}<br \/>TEXT format<br \/>{Virtual Users} 1 {User Delay(ms)} 500 {Repeat Delay(ms)} 500 Iterations 1 {Show Output} 1 {Log Output} 0 {Unique Log Name} 0 {No Log Buffer} 0 {Log Timestamps} 0<br \/>Printing output for vucreated and converting JSON to text<br \/>JSON format<br \/>{\"Virtual Users created\": \"0\"}<br \/>TEXT format<br \/>{Virtual Users created} 0<br \/>Printing output for vustatus and converting JSON to text<br \/>JSON format<br \/>{\"Virtual User status\": \"No Virtual Users found\"}<br \/>TEXT format<br \/>{Virtual User status} {No Virtual Users found}<br \/>Printing output for datagen and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"schema\": \"TPC-C\",<br \/>  \"database\": \"Oracle\",<br \/>  \"warehouses\": \"1\",<br \/>  \"vu\": \"1\",<br \/>  \"directory\": \"\\\/tmp\\\"\"<br \/>}<br \/>TEXT format<br \/>schema TPC-C database Oracle warehouses 1 vu 1 directory \/tmp\\\"<br \/>--------------------------------------------------------<br \/>PRINT COMMANDS COMPLETE<br \/>--------------------------------------------------------<br \/>TEST PRINT COMMANDS AS OPTION TO PRINT ie print?dict <br \/>Printing output for db and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"ora\": \"Oracle\",<br \/>  \"mssqls\": \"MSSQLServer\",<br \/>  \"db2\": \"Db2\",<br \/>  \"mysql\": \"MySQL\",<br \/>  \"pg\": \"PostgreSQL\",<br \/>  \"redis\": \"Redis\"<br \/>}<br \/>TEXT format<br \/>ora Oracle mssqls MSSQLServer db2 Db2 mysql MySQL pg PostgreSQL redis Redis<br \/>Printing output for bm and converting JSON to text<br \/>JSON format<br \/>{\"benchmark\": \"TPC-C\"}<br \/>TEXT format<br \/>benchmark TPC-C<br \/>Printing output for dict and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"connection\": {<br \/>    \"system_user\": \"system\",<br \/>    \"system_password\": \"manager\",<br \/>    \"instance\": \"oracle\",<br \/>    \"rac\": \"0\"<br \/>  },<br \/>  \"tpcc\": {<br \/>    \"count_ware\": \"1\",<br \/>    \"num_vu\": \"1\",<br \/>    \"tpcc_user\": \"tpcc\",<br \/>    \"tpcc_pass\": \"tpcc\",<br \/>    \"tpcc_def_tab\": \"tpcctab\",<br \/>    \"tpcc_ol_tab\": \"tpcctab\",<br \/>    \"tpcc_def_temp\": \"temp\",<br \/>    \"partition\": \"false\",<br \/>    \"hash_clusters\": \"false\",<br \/>    \"tpcc_tt_compat\": \"false\",<br \/>    \"total_iterations\": \"1000000\",<br \/>    \"raiseerror\": \"false\",<br \/>    \"keyandthink\": \"false\",<br \/>    \"checkpoint\": \"false\",<br \/>    \"ora_driver\": \"test\",<br \/>    \"rampup\": \"2\",<br \/>    \"duration\": \"5\",<br \/>    \"allwarehouse\": \"false\",<br \/>    \"timeprofile\": \"false\"<br \/>  }<br \/>}<br \/>TEXT format<br \/>connection {system_user system system_password manager instance oracle rac 0} tpcc {count_ware 1 num_vu 1 tpcc_user tpcc tpcc_pass tpcc tpcc_def_tab tpcctab tpcc_ol_tab tpcctab tpcc_def_temp temp partition false hash_clusters false tpcc_tt_compat false total_iterations 1000000 raiseerror false keyandthink false checkpoint false ora_driver test rampup 2 duration 5 allwarehouse false timeprofile false}<br \/>Printing output for script and converting JSON to text<br \/>JSON format<br \/>{\"error\": {\"message\": \"No Script loaded: load with loadscript\"}}<br \/>TEXT format<br \/>error {message {No Script loaded: load with loadscript}}<br \/>Printing output for vuconf and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"Virtual Users\": \"1\",<br \/>  \"User Delay(ms)\": \"500\",<br \/>  \"Repeat Delay(ms)\": \"500\",<br \/>  \"Iterations\": \"1\",<br \/>  \"Show Output\": \"1\",<br \/>  \"Log Output\": \"0\",<br \/>  \"Unique Log Name\": \"0\",<br \/>  \"No Log Buffer\": \"0\",<br \/>  \"Log Timestamps\": \"0\"<br \/>}<br \/>TEXT format<br \/>{Virtual Users} 1 {User Delay(ms)} 500 {Repeat Delay(ms)} 500 Iterations 1 {Show Output} 1 {Log Output} 0 {Unique Log Name} 0 {No Log Buffer} 0 {Log Timestamps} 0<br \/>Printing output for vucreated and converting JSON to text<br \/>JSON format<br \/>{\"Virtual Users created\": \"0\"}<br \/>TEXT format<br \/>{Virtual Users created} 0<br \/>Printing output for vustatus and converting JSON to text<br \/>JSON format<br \/>{\"Virtual User status\": \"No Virtual Users found\"}<br \/>TEXT format<br \/>{Virtual User status} {No Virtual Users found}<br \/>Printing output for datagen and converting JSON to text<br \/>JSON format<br \/>{<br \/>  \"schema\": \"TPC-C\",<br \/>  \"database\": \"Oracle\",<br \/>  \"warehouses\": \"1\",<br \/>  \"vu\": \"1\",<br \/>  \"directory\": \"\\\/tmp\\\"\"<br \/>}<br \/>TEXT format<br \/>schema TPC-C database Oracle warehouses 1 vu 1 directory \/tmp\\\"<br \/>PRINT COMMANDS COMPLETE<br \/>--------------------------------------------------------<br \/>TEST DISET<br \/>Setting Warehouse Count to 800<br \/>Setting password to new password<br \/>Setting password error 1 invalid string<br \/>{\"error\": {\"message\": \"Not a valid JSON string: '{ \\\"dict\\\": \\\"tpcc\\\", \\\"ke }'\"}}<br \/>Setting password error 2 invalid number of arguments<br \/>{\"error\": {\"message\": \"Incorrect number of parameters to diset dict key value\"}}<br \/>Setting password error 3 invalid key<br \/>{\"error\": {\"message\": \"Dictionary \\\"tpcc\\\" for Oracle exists but key \\\"tpcds_pass\\\" doesn't\"}}<br \/>Setting password error 4 invalid string<br \/>{\"error\": {\"message\": \"Dictionary \\\"tpcfg\\\" for Oracle does not exist\"}}<br \/>Setting Driver Script<br \/>{\"success\": {\"message\": \"Set driver script to timed, clearing Script, reload script to activate new setting\"}}<br \/>Setting Driver Script Error<br \/>{\"error\": {\"message\": \"Error: Driver script must be either \\\"test\\\" or \\\"timed\\\"\"}}<br \/>Clearscript<br \/>{\"success\": {\"message\": \"Script cleared\"}}<br \/>Loadscript<br \/>{\"success\": {\"message\": \"script loaded\"}}<br \/>Script in TEXT format<br \/>VU Status<br \/>{\"Virtual User status\": \"No Virtual Users found\"}<br \/>Testing dbset<br \/>{\"error\": {\"message\": \"Unknown prefix mssqs, choose one from ora mssqls db2 mysql pg redis\"}}<br \/>Testing dbset<br \/>{\"error\": {\"message\": \"Invalid option to dbset key value\"}}<br \/>Testing dbset<br \/>{\"success\": {\"message\": \"Database set to PostgreSQL\"}}<br \/>Testing dbset<br \/>{\"error\": {\"message\": \"Unknown benchmark TPC-X, choose one from TPC-C TPC-H\"}}<br \/>Testing dbset<br \/>{\"success\": {\"message\": \"Benchmark set to TPC-H for PostgreSQL\"}}<br \/>Testing vuset<br \/>{\"error\": {\"message\": \"Invalid option to vuset key value\"}}<br \/>Testing vuset<br \/>{\"success\": {\"message\": \"Virtual users set to 10\"}}<br \/>Testing dgset<br \/>{\"success\": {\"message\": \"Set directory to \\\/tmp for data generation\"}}<br \/>Testing Custom Script : Open File convert to JSON and post<br \/>{\"success\": {\"message\": \"Set custom script\"}}<br \/>Custom Script in TEXT format<br \/>Testing vuset<br \/>{\"success\": {\"message\": \"Virtual users set to 5\"}}<br \/>Testing vucreate<br \/>{\"success\": {\"message\": \"6 Virtual Users Created with Monitor VU\"}}<br \/>Testing vucreate<br \/>{\"error\": {\"message\": \"Virtual Users exist, destroy with vudestroy before creating\"}}<br \/>VU Status after create<br \/>{\"Virtual User status\": \"1 {WAIT IDLE} 2 {WAIT IDLE} 3 {WAIT IDLE} 4 {WAIT IDLE} 5 {WAIT IDLE} 6 {WAIT IDLE}\"}<br \/>Testing vudestroy<br \/>{\"success\": {\"message\": \"vudestroy success\"}}<br \/>VU Status after destroy<br \/>{\"Virtual User status\": \"No Virtual Users found\"}<\/pre>\n<p>When the environment is configured you can build schemas and run workloads with the same commands used for the CLI, for example:<\/p>\n<pre>set res [rest::post http:\/\/localhost:8080\/buildschema \"\" ]<\/pre>\n<pre>set res [rest::post http:\/\/localhost:8080\/vurun \"\" ]<\/pre>\n<p>The key difference is that output is now stored in a job format that can be retrieved at a later point. An example is shown where a build generates a jobid. <\/p>\n<pre>{\"success\": {\"message\": \"Building 5 Warehouses with 6 Virtual Users, 5 active + 1 Monitor VU(dict value num_vu is set to 5): JOBID=5D23464E58D203E273738333\"}}<\/pre>\n<p>That is then used to query the status of the build. <\/p>\n<p><a href=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsjob.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-437\" src=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsjob.png\" alt=\"\" width=\"786\" height=\"549\" srcset=\"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsjob.png 786w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsjob-300x210.png 300w, https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2019\/07\/wsjob-768x536.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>The output is stored in a SQLite database that by default runs in in-memory mode that is not persistent over restarts,\u00a0 however it can be configured to use a permanent database.<\/p>\n<p>It is not intended for the web service to replace the GUI or CLI environments that still prove the most popular way to run HammerDB, however the aim is to provide an additional way that HammerDB can be integrated into tests in\u00a0 in cloud environments particular.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>HammerDB already has 2 interfaces with which to interface with the commands to build and test databases using the GUI interface or CLI. From HammerDB version 3.2 there is an additional interface that enables HammerDB to run as Web Service. This allows HammerDB to be driven with a REST type client using a HTTP interface &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.hammerdb.com\/blog\/uncategorized\/using-hammerdb-as-a-web-service\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Using HammerDB as a Web Service&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"ppma_author":[5],"class_list":["post-432","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"authors":[{"term_id":5,"user_id":2,"is_guest":0,"slug":"hammerdb","display_name":"HammerDB","avatar_url":{"url":"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/10\/logo-white.png","url2x":"https:\/\/www.hammerdb.com\/blog\/wp-content\/uploads\/2018\/10\/logo-white.png"},"author_category":"","user_url":"http:\/\/www.hammerdb.com","last_name":"","first_name":"","job_title":"","description":""}],"_links":{"self":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts\/432","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/comments?post=432"}],"version-history":[{"count":6,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts\/432\/revisions"}],"predecessor-version":[{"id":440,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/posts\/432\/revisions\/440"}],"wp:attachment":[{"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/media?parent=432"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/categories?post=432"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/tags?post=432"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.hammerdb.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=432"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}