go to post John Kumpf · Aug 26, 2019 Old thread, but here's the link to that video:https://www.youtube.com/watch?v=Bn5VPKAUs0U(start at 3:50)
go to post John Kumpf · Aug 23, 2019 You could try OnPreDispatch:https://cedocs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cl...Get's called before the request is dispatched to the appropriate handler method in the URL map. I think setting headers you have to set on every request is a great use case for it.
go to post John Kumpf · Aug 7, 2019 You're running into the fact that calling %Get on a dynamic object doesn't return an undefined when data at the index you specify doesn't exist. Instead, it returns "".Both the answers you have here are great if you need a generalized solution. If all you're looking for is a simple work around in a non-general case, all you need to do is check if your %Get returned "", and if so, kill the value before you pass it in: ClassMethod passIncompleteJSON() { set json = ["arg1 val", "arg2 val"] set arg1 = json.%Get(0) kill:(arg1="") arg1 set arg2 = json.%Get(1) kill:(arg2="") arg2 set arg3 = json.%Get(2) kill:(arg3="") arg3 write ..threeArgs(.arg1, .arg2, .arg3) } ClassMethod threeArgs(a, b, c) { set:($get(c)="") c = "default" return a_"."_b_"."_c } Just be sure to pass in the parameters by reference since you're going to be passing in undefined variables. (This does remove the distinction between undefined and "" though; you wouldn't be able to intentionally pass "" with this solution)
go to post John Kumpf · Apr 23, 2019 I'm building classes which contain representations of REST resources. For example, a full (likely for administrators) representation of the "person" resource might contain all fields, and all of them are writable. A limited (maybe authenticated, but non admin) representation might contain most fields, and some like name and email are writable, but others like employment status are not. A minimal (maybe for unauthenticated users) representation would contain only a few, read-only fields.The property parameters would be things like the name for the property we use in the JSON, whether the field is writable, other flags regarding how to represent relationships or object properties, etc.I think what I'm imagining is very similar to the %XML.PropertyParameters class used by %XML.Adaptor(If you're probably wondering why I didn't include all this in my original post, I've been discussing it with Tim Leavitt and my ideas are a lot more formulated than they were 2 hours ago. I suspect that an analogous architecture to what's used with XML will work well.)
go to post John Kumpf · Apr 16, 2019 Oh okay, I see. JSON_ARRAYAGG takes whatever results it gets back, and puts them into a JSON array. Since JSON_OBJECT returns a bunch of results that are json objects, using JSON_ARRAYAGG(JSON_OBJECT( says to take all those json objects, and put them into a json array.As far as the non select part of the query, it looks like you can specify it with a new "select", or without. I.e.: SELECT JSON_ARRAYAGG(JSON_OBJECT('state':Home_State)) FROM Sample.Person WHERE Home_State %STARTSWITH 'A' SELECT JSON_ARRAYAGG(JSON_OBJECT('state':Home_State)) FROM (select state from Sample.Person WHERE Home_State %STARTSWITH 'A') Thanks a lot for taking the time to explain. It's very clear to me what is happening now.
go to post John Kumpf · Apr 16, 2019 Thanks a lot. This worked.I found the page about this function for anyone who sees this later:https://irisdocs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page...Would you mind explaining how exactly this particular line is working? Why do you have to use both JSON_ARRAYARG and JSON_OBJECT and what does that syntax mean? It looks like it's essentially "selecting" the data from one result set into another as JSON, but I'm not sure how. What does the JSON_OBJECT call do here, and what does the JSON_ARRAYAGG call do?
go to post John Kumpf · Apr 12, 2019 Ah, using base-href is a great idea, thanks. A few questions about this:Why did you rename the files to .csp?Why are you using ahead of time compilation?By using:ng build --base-href = /webapp_name/index.htmlI was able to access <cname>/webapp_name/index.html successfully; the index.html file could find the scripts like polyfills.js without me modifying those src arguments by hand.
go to post John Kumpf · Feb 13, 2019 Okay, so if I'm understanding you correctly, even if the user field changes after the initial insertion of the object, the userid field should stay the same?
go to post John Kumpf · Feb 12, 2019 I'm guessing you're looking for the %%ID special reference. Something like this: Class Testing.TestingCalcProps Extends %Persistent{Property user As %String;Property a As %String [ Calculated, SqlComputeCode = {set {*} = {user}_{%%ID}}, SqlComputed];}I'd recommend the Calculated keyword, as elements only gain id's after they're saved, which could perhaps lead to inaccurate values in the calculated property before the saving happens.Here's the resource which talks about these properties: https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY...And here's the one that mentions %%ID: https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY...
go to post John Kumpf · Jan 30, 2019 This is probably a simple syntax error. Let's see the code you're using, from start to finish, setting up, preparing, then executing the query. Perhaps the syntax is wrong on the preparation step.
go to post John Kumpf · Jan 28, 2019 The post build script executes on the node that the Jenkins build ran on. Therefore, that node machine is “local” for the purposes of copying remote files, and the machine where the XML file you want to copy lives is the “remote” machine.You’ve probably seen this, but here’s the documentation for the Secure Copy Protocol (scp) command:https://linuxize.com/post/how-to-use-scp-command-to-securely-transfer-files/The relevant form for you should be:scp user@hostOfFileToCopy:/path/to/fileToCopy /path/to/newCopy“user” needs to be the name of a user who has permissions to copy the file. hostOfFileToCopy identifies the machine on which that XML file lives (could be an IP address). /path/to/fileToCopy is the absolute path, on that machine, of the file you want to copy./path/to/newCopy is the absolute path for the destination of the copy on the machine the Jenkins build is running on, not just the relative path from within the Jenkins workspace. For example, while your path within the Jenkins workspace might be “/ReportFiles/Results.xml", the absolute path on the machine is probably something like “/Jenkins/workspace/ReportFiles/Results.xml”Hope this helps.
go to post John Kumpf · Jan 22, 2019 If you're curious, this is why what you tried originally got you unexpected results.You passed the embedded sql statement an array with a missing subscript, :IDArray(), hoping it would put your first result in IDArray(1), your second in IDArray(2), etc. The problem with that is that a single embedded sql statement like the one you used will only ever return one result row: the first row that matches the criteria. So what you were likely seeing is your first valid ID stored in IDArray(1), and none of the other ones you wanted present.So why can it accept an array as an output argument at all, then? When embedded sql sees an array as an output argument, it gives that array a subscript for each of the columns in the result row. So IDArray(1) wasn't the first ID, but rather the first column of the returned sql row. For example, &sql(select id, name, age into :result() from Person) would return the id into result(1), name into result(2), and age into result(3).Hope this helps. Good luck!
go to post John Kumpf · Jan 15, 2019 This is great, thanks. Just implemented it. Worked like a charm.Also let me just confirm (and this wasn't needed in my particular implementation): if I call giveMeAFalseMe from Cache when it's returning "true" or "false", Cache will translate "true" into a truthy %Boolean return value, right?
go to post John Kumpf · Dec 7, 2018 It appears that, for whatever reason, the System files are not automatically included for every class you write in Cache 2010. When a class inherits from %RegisteredObject, you don't need to worry, because they'll be included via inheritance. For other classes, like the one where I was seeing this issue, the system files are unavailable unless included by hand.Adding Include.%occStatus to the top of the non-compiling classes fixes the issue for the $$$OK macro, although a better practice is to use Include.%occInclude, to get some other standard stuff with the status routines.
go to post John Kumpf · Dec 7, 2018 Here the simplest one I have that had the issue if you want too look at it. Note my answer on what I've discovered (which was enough to solve the issue).
go to post John Kumpf · Dec 7, 2018 <?xml version="1.0" encoding="UTF-8"?><Export generator="Cache" version="25"><Class name="CACHE2010.Build"><TimeCreated>64952,32335.711823</TimeCreated><Parameter name="SrcVer"><Description>Location and Revision of this file in Perforce (Auto-updating)</Description><Default>$Id: //custom_ccrs/_common/tools/CCRToolsBuild/BuildManifests/Cache2010/Build.xml#1 $</Default></Parameter><XData name="BuildManifest"><Description>This is a build manifest. Here we describe build steps in XML format.</Description><Data><![CDATA[<Manifest><!-- Change into namespace --><Namespace Name="CCRClientTools" Ensemble="0" Code="CCRTOOLS-CODE" Data="CCRTOOLS"><Configuration><!-- Have database for code --><Database Name="CCRTOOLS-CODE" Dir="c:\intersystems\cache\mgr\ccrtools-code\" Create="overwrite" InitialSize="200" ExpansionSize="60" /></Configuration></Namespace></Manifest>]]></Data></XData><Method name="Build"><Description>This method is called to pass parameters into generated build method</Description><ClassMethod>1</ClassMethod><ReturnType>%Status</ReturnType><Implementation><![CDATA[ Set pLogLevel=3 Set sc=..RunBuildManifest(.vars, .pLogLevel) Quit sc]]></Implementation></Method><Method name="RunBuildManifest"><Description>This is a standard %Installer method generator whose code is generated by XGL.</Description><Internal>1</Internal><ClassMethod>1</ClassMethod><CodeMode>objectgenerator</CodeMode><FormalSpec><![CDATA[&pVars,pLogLevel:%Integer,pInstaller:%Installer.Installer]]></FormalSpec><ReturnType>%Status</ReturnType><Implementation><![CDATA[ #; Let our XGL document generate code for this method. quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "BuildManifest")]]></Implementation></Method></Class></Export>