go to post John Hotalen · Oct 7, 2016 You can use the example method (parseURLquery) that Sergei posted to get at the query (request params) information. You might also consider applying the $zconvert code that Tomas recommended as a good practice to account for any possible encoding and or use of different character sets. Also, Fabian was kind enough to post a link to InterSystems documentation that discusses the built-in (%Net.URLParser) Parse method - which would be useful/helpful, as well.
go to post John Hotalen · Oct 3, 2016 General question: Is this available for all versions of Cache? Or just from 2016.1 and beyond?
go to post John Hotalen · Oct 3, 2016 Two quick questions regarding the Server Side section:1. In the Server() method in the error handling for when the CSP web socket is closed, there is code that is doing "kill ^CacheTemp.ChatWebSockets(..WebSocketID)" - shouldn't this actually be: "kill ^CacheTemp.Chat.WebSockets(..WebSocketID)"? <-- notice the period I added between "Chat" and "WebSockets" in global name.2. In the Server() method in the error handling for when the CSP web socket is closed, shouldn't the code that is doing the kill of "kill ^CacheTemp.Chat.WebSockets(..WebSocketID)" also be doing a kill on "^CacheTemp.Chat.Room(..WebSocketID)"?Thanks. And this was a good article!
go to post John Hotalen · Sep 29, 2016 Correct :) I was just offering an alternate example for those developers who like/prefer While loops versus For loops. From working with a vast array of Cache Developers over the years, I found that looping structures are one of those topics that provide "good discussion/debate" over which is better, faster, more useful, etc.... :) Personally, I do not have a preference - I use both While loops and For loops. Which one I use is based on the content I am implementing.
go to post John Hotalen · Sep 29, 2016 Quick comment/Note regarding the statement "A disadvantage of the 'While' structure is first you need to repeat the iteration construct, e.g. 'Set Sub1=$O(^Trans(Sub1))' before entering the loop and at the end." - this is a common perception for many newer Cache Developers. My suggestion for new folks would be to use a simplified structure, such as follows:Set someVariable=""While(1) { Set someVariable=$Order(^MyGlobal(someVariable)) If (someVariable="") { Quit } // Do your processing here}The above structure keeps the looping construct at the start of the loop and is only needed once. Within your processing logic, you can easily skip to the next iteration of the loop (if needed) via use of the Continue command. Or if you need to exit the while loop, then you can do so via use of the Quit command.Hope this was helpful! And Happy Coding!!!
go to post John Hotalen · Sep 29, 2016 Excellent Article. I have a question about options for running pButtons. Please Note: It has been awhile since I last used pButtons. But I can attest that it is a very useful tool. My question: Is there an option to run pButtons in "basic mode" versus "advanced mode"? I thought I recalled such a feature, but cannot seem to remember how to select the run mode. And from what I recall, basic mode collects less data/information than advanced mode. This can be helpful for support teams and others when they only need the high-level details.Thanks! And I look forward to reading the next 5 articles in this series.
go to post John Hotalen · Aug 22, 2016 Also, you can use the built-in %RD routine. After you enter the routine name or names that you want to see the sizes for, then answer "L" for Long Form at the next prompt. that will display additional attributes about the specified routines - one of which will be the size in bytes.Example Output: Long Listing of Selected Routine/Include Files Namespace: TEST 22 Aug 2016 6:14 PM Page 1NAME .EXT.VER LANG DATE/TIME #BYTESUTTest .MAC 20 May 2016 10:21 am 14252
go to post John Hotalen · Jul 22, 2016 If you just want to see data for the class query, then you can also run the query interactively via your Cache Terminal window (or any other type of terminal emulator, such as Putty, Reflections, PowerTerm, etc...).Here is the command to run the class query from your example:Do ##class(%ResultSet).RunQuery("LastName.BasicClassQuery","Display")Note: If your query accepts input parameters, then you just include them as the 3rd-nth parameters - an example of what that might look like if you needed to pass two input values to your query: Do ##class(%ResultSet).RunQuery("LastName.BasicClassQuery","Display","value1","value2")This will list the data in your terminal window and might look something like this: Notice the first row that is displayed is all your column names (i.e. property names) and all the subsequent rows that are displayed is the data from your table(s).Code:Name:IsActive:ID:AF:Archived Forms:1:31:AR:AdHoc Feedback Report:1:29:AT:Stain/Request Audit Report:1:11:CH:Cyto-Histo Correlation:1:23:CPS:Cytology Population Statistics:1:22:
go to post John Hotalen · Apr 21, 2016 Quick followup note - so folks don't freak out about the output from the query example - the names and birthdates and SSN's displayed in the example were from a SAMPLES testing environment where data was auto-generated at random - so the data is fake and not for real people :)
go to post John Hotalen · Apr 21, 2016 In regards to the first part of your write-up, as a developer, if you want a quick and easy way to test the query from your terminal window (i.e. Cache Terminal, PowerTerm, Putty, Reflections, etc...), then you can run the query as follows: Do ##class(%ResultSet).RunQuery({className},{queryName}) - if you have input parameters, then you would pass those values as subscripts 3 - n; Example of running query with two input parameters: Do ##class(%ResultSet).RunQuery({className},{queryName},{inputValue1},{inputValue2}) So an example of running the first query in your write-up from a terminal window might be: Do ##class(%ResultSet).RunQuery("Sample.Person","ByName","A") The output from the query might be: ID:Name:DOB:SSN:53:Adam,Ralph O.:41730:657-43-6149:33:Adam,Zoe X.:56117:982-36-6928:80:Ahmed,Edgar Q.:33719:546-61-2688:110:Alton,Umberto B.:30116:877-79-1057:146:Avery,Valery P.:39515:310-11-8847: Hope this Helps and Have a Great Day!!! Happy Coding/Testing those queries!
go to post John Hotalen · Apr 21, 2016 Or if you want to display or get that value with a single line of code (assuming you do not care about error handling), then you could do the following: Write ##class(%Routine).%OpenId("hello.mac").SizeGet()
go to post John Hotalen · Apr 21, 2016 Hi Benjamin, As a fellow Cache Developer I can offer a couple of suggestions. If you want the user to have to wait for the server side processing to complete before continuing with their work, then you could override the CSP Gateway Response Timeout: 1. If you are working with a ZEN page (i.e. that extends from %ZEN.component.page), then you could implement an overridden version of the OnPreHyperEvent method Example: /// OnPreHyperEvent - Event handler which is invoked before a hyperevent/// method is called on all Zen pages. The purpose of this method is to/// allow various configuration settings to be overridden prior to making/// the actual hyperevent call (i.e. executing a query for a tablepane).ClassMethod OnPreHyperEvent(class As %String, method As %String) As %Status [ ServerOnly = 1 ]{// Override the CSP Gateway Response TimeoutSet %response.Timeout={numberOfSecondsYouWantToAllowForServerProcessingToCompleteBeforeRequestTimesOut} // Call built-in Zen Controller pre hyperevent methodQuit ##class(%ZEN.Controller).OnPreHyperEvent(..%ClassName(1),$G(method),+..#AUTONS,..#RESOURCE)} 2. If you are working with a CSP page (i.e. that extends from %CSP.Page), then you could implement an overridden version of the OnPreHTTP method Example: /// Event handler for <b>PreHTTP</b> event: this is invoked before/// the HTTP headers for a CSP page have been sent. All changes to the/// <class>%CSP.Response</class> class, such as adding cookies, HTTP headers,/// setting the content type etc. must be made from within the OnPreHTTP() method./// Also changes to the state of the CSP application such as changing/// %session.EndSession or %session.AppTimeout must be made within the OnPreHTTP() method./// It is prefered that changes to %session.Preserve are also made in the OnPreHTTP() method/// as this is more efficient, although it is supported in any section of the page./// Return <b>0</b> to prevent <method>OnPage</method> from being called.ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]{// Override the CSP Gateway Response Timeout Set %response.Timeout={numberOfSecondsYouWantToAllowForServerProcessingToCompleteBeforeRequestTimesOut}Quit $$$OK} But another option to consider is to implement the ZEN page, so the user can provide the input criteria (if any) for retrieving table data and instead of having the user click a [Search] button to run the server side lookup in foreground mode (i.e. where user has to wait for the server processing to complete), you could instead implement a [Run In Background] button where you job off the server side processing, so it can run in the background, which allows the user to do other things with the application and they can check back at a later point for the status. You could have some type of mechanism on the ZEN page that shows the user the status of the background process (i.e. Running, Completed, Error, etc...); You can refer to the built-in %RunBackgroundMethod method or you could implement your own application specific background type processing - example: As the user submits various background jobs to run, you could have a tablepane display the various processes that are running with their status - then when complete, you could have a link in that table the user could click to display the associated data that was retrieved from the server. Hope this helps and Have a Great Day!! Happy Coding!
go to post John Hotalen · Dec 8, 2015 Before I load this code package, I wanted to ask if it will work with any version of Cache. If not, then what versions does it work with. Thanks.