go to post Dmitry Maslennikov · Aug 5, 2016 GlobalsDB, no more developing, thats why this site has some issues.You may find you answer in this exactly the same question, asked few days ago
go to post Dmitry Maslennikov · Jul 26, 2016 You should know, that namespace it is a just definition in which databases stored some types of data, and how it mapped. So, you can only check in which database package stored write ##class(%SYS.Namespace).GetPackageDest("SAMPLES","%Activate.Enum") ^/opt/cache/mgr/cachelib/ delimited output, first part is a system like in ECP-configuration, and second part is a database path you can compare this path with default path for packages in this namespace. w ##class(%SYS.Namespace).GetPackageDest("SAMPLES","") ^/opt/cache/mgr/samples/
go to post Dmitry Maslennikov · Jul 20, 2016 In case when you try to load this file via %Compiler.UDL.TextServices you should know this classname, and you can parse original file. But if it possible, better to use $system.OBJ.Load(), in this case you should not pass classname, only lodaded filename.
go to post Dmitry Maslennikov · Jul 13, 2016 Every routines stores directly in database, so, you can't just open it as any file on your filesystem as well as you do it with csp files. but you can open it with %RoutineMgr class, something like this USER>zn "samples" SAMPLES>set rtn=##class(%RoutineMgr).%OpenId("hello.mac") SAMPLES>while 'rtn.Code.AtEnd { write !,rtn.Code.ReadLine()} hello ; hello world routine write !, "hello world" write !, "bye" end quit ; end if you also need to get list of such files, you can use query StudioOpenDialog in %RoutineMgr class SAMPLES>set st=##class(%SQL.Statement).%New() SAMPLES>set sc=st.%PrepareClassQuery("%RoutineMgr","StudioOpenDialog") SAMPLES>set rs=st.%Execute("*.mac") SAMPLES>do rs.%Display() Dumping result #1 Name IsDirectory Type Size Date Description IconType DocBook . 9 0 badroutine.mac 0 62 2004-09-28 13:05:45 0 CinemaData.mac 0 10258 2016-05-10 22:32:04 0 compareloop.mac 0 1201 2004-12-02 18:23:57 0 datent.mac 0 3089 2002-01-03 12:05:01 0 datentobj.mac 0 2627 2002-09-06 00:15:23 0 dbconvert.mac 0 1532 2002-01-03 12:05:52 0 fibonacci.mac 0 365 2002-01-03 12:06:03 0 forexample.mac 0 502 2004-11-30 16:00:08 0 funcexample.mac 0 333 2002-01-03 12:06:30 0 hello.mac 0 251 2016-07-13 12:07:04.520803 0 LDAP.mac 0 68720 2013-12-16 11:48:09.962335 0 lookup.mac 0 8484 2008-08-21 19:17:48 0 lookup1.mac 0 1465 2002-01-03 12:07:15 0 lookup2.mac 0 5984 2002-01-07 18:08:46 0 lookupobj.mac 0 7857 2008-08-21 21:58:25 0 loopend.mac 0 242 2002-01-03 12:08:12 0 loopstart.mac 0 217 2002-01-03 12:08:21 0 nameloop.mac 0 552 2002-01-03 12:08:33 0 passbyref.mac 0 604 2002-01-07 12:01:47 0 postcond.mac 0 341 2002-01-03 12:08:51 0 procexample.mac 0 423 2002-01-03 12:08:59 0 publicvarsexample.mac 0 357 2002-01-03 12:09:09 0 RightTriangle.mac 0 1836 2011-02-24 18:56:29 0 root.mac 0 149 2004-11-30 15:57:29 0 simpleloop.mac 0 161 2002-01-03 12:09:59 0 SQLGatewayTest.mac 0 2480 2016-05-10 22:32:04 0 survivor.mac 0 179 2002-01-03 12:10:32 0 ZAUTHENTICATE.mac 0 37302 2015-03-10 10:48:43.589807 0 ZAUTHORIZE.mac 0 12120 2016-05-10 22:32:04 0 30 Rows(s) Affected
go to post Dmitry Maslennikov · Jun 7, 2016 but WaitMsg it is on parent's side, my control code ususaly like like this set resName="someresource" job ..someJob(jobsData,resName) set child=$zchild for { set $lb(sc,data)=$system.Event.WaitMsg(resName, 1) if sc<=0 { quit:'$data(^$Job(child)) } continue:data="" // do some staff with incomming data }But if you want to interrupt your child process, of course will be possible only from such process, if your process have some loops you may just check if parent still exists, if not, just stop working.
go to post Dmitry Maslennikov · May 26, 2016 Steve,I would recommend to distant webservers from ECP Application servers. In your case I would install webserver exactly on the server where ECP Application Server have already installed, so in this case your connect via superport will be secured, and in this case only web port should be opened in the firewall. Outside of this servers after firewall you need to use some load balancer, in this case I would recommend to use HAProxy. Connection between extarnal HAProxy and internal webservers could be secured with ssl, but I'm not sure that is really needed.And in this case it is possible to store all static content such as JS, CSS and images on server where load balancer placed, to avoid redundant request to the data servers. It is not a big problem for the production systems.So finally in simple view it my looks like below.
go to post Dmitry Maslennikov · May 4, 2016 Well, you can't write conditions in this way, and compile error which you see, it is actually parsing error for such conditionHow you can change it, You should define some function which may do all this check or partially, just return some value for check. To define such function, you should have your child for Ens.Rule.FunctionSet class, something like this Class Test.Utils Extends Ens.Rule.FunctionSet { ClassMethod GetAt(value As %String = "", index As %String) As %String { if $isobject(value) { quit value.GetAt(index) } quit "" } } and then, you can use it in this way, where GetAt your just created function. <rule name=""> <constraint name="msgClass" value="Test.TestMessage"></constraint> <when condition="GetAt(Document.myList,1)="AA""> <send transform="" target="DummyOperation"></send> <return></return> </when> </rule> But your function should return final value for checking, and you can't use write so, GetAt(Document.myList,1).property1="AA"
go to post Dmitry Maslennikov · Mar 24, 2016 I use such code in one of my projects ClassMethod Test() { set address="One Memorial Drive, Cambridge, MA 02142, USA" do ..GetCoords(address, .latitude, .longitude, .partialMatch) zw latitude, longitude, partialMatch } ClassMethod GetCoords(Address As %String, Output Latitute As %Float = "", Output Longitude As %Float = "", Output PartialMatch As %Boolean) As %Status { set params("address")=Address set sc=..CallGoogleAPI("/maps/api/geocode/json", .params, .data) if data.status="OK" { set result=data.results.$get(0) set PartialMatch = +result."partial_match" set Latitute = result.geometry.location.lat set Longitude = result.geometry.location.lng } quit $$$OK } ClassMethod CallGoogleAPI(Url As %String, ByRef Params, Output Data) As %Status { #;set Params("key")="your api key here" quit ..CallApi("maps.googleapis.com", 1, Url, .Params, .Data) } ClassMethod CallApi(Server As %String, Secure As %Boolean = 1, Url As %String, ByRef Params, Output Data) As %Status { set ht=##class(%Net.HttpRequest).%New() set ht.Server="maps.googleapis.com" set ht.Https=Secure set:Secure ht.SSLConfiguration=..GetSSLCertificate(Server) set param="" for { set param=$order(Params(param),1,value) quit:param="" do ht.SetParam(param, value) } set sc=ht.Get(Url) if $$$ISERR(sc) quit sc set Data={} set Data=Data.$fromJSON(ht.HttpResponse.Data) quit $$$OK } ClassMethod GetSSLCertificate(Server As %String) As %Status { new $namespace znspace "%SYS" do { quit:##class(Security.SSLConfigs).Exists(Server) set tSC=##class(Security.SSLConfigs).Create(Server) $$$ThrowOnError(tSC) } while 0 quit Server }
go to post Dmitry Maslennikov · Mar 22, 2016 Caché doesn't have Zlogin routine, if it is %-routine, it should be in CACHESYS and any others, could be placed in any database. Z-routine means that it is developed outside from InterSystems, they recommend to use such naming to prevent overwriting with system routines, present or future.
go to post Dmitry Maslennikov · Mar 9, 2016 Much better If it would be possible to migrate or merge two accounts here. I have a WRC account on email from my current company, but what happens when I chnage a job. In this case I may loose access to any my content here. And I have another registration with my own email. It would be very nice if I could merge two of this accounts or something else, if I could use WRC and commonity with the same my own not corporate account.
go to post Dmitry Maslennikov · Feb 24, 2016 Hi Kenneth,I've been working in company where we develop WEB-based ECM application. It's a quite big one, and very flexible. We do not use CSP-files at all, only CSP-classes, no Zen. And some my own projects on Caché, also in WEB. I will not recommend to use CSP-files, or Zen. I can't say anything about Zen Mojo, just because when I last time saw it, it was not so better then Zen, now with Native JSON it may be better. I'll recommend CSP-classes, REST and webservices.CSP-Pages. It may be usefull, with all of their tags and stores with files. But unfortunately all of this files, may some time confuse developer, because in any way developer should know is it compiled or not, when some files were changed, it may looks like nothing changed. And at the end anyway it compiles to CSP-classes. ZEN. With ZEN, you get some ready components. In the same time, your application became too big, even if it not, and have just one page. It generate js/css files, and you should care about that files, while you deploy app to production. Data transfered from server to client side, contains waste js code.With CSP-classess, I have flexibility, and can generate different parts of page in very different parts of code. I have much more possibilities to control how I generate HTML, receive and response requests. But I still generate html-code in Caché.As well we have more than 1MB CSS and JS files. For me it is not so comfortably to edit that files in Studio. For HTML in classes I can use embedded &html<>. JS and CSS files I'm editing in Sublime Text. But I'm sure that in modern time application should be SPA, all html should be in static files, and server should speak only in JSON, with a REST and wevservices. And in all my last web-projects, I'm using this way. Static HTML, JS, CSS files, with a Gulp I transform all sperate JS and CSS files to one, implement that files to HTML. And for production version I put all that files in one Class. In this case I can send one XML file which contains full application. For example CacheBlocksExplorer
go to post Dmitry Maslennikov · Feb 16, 2016 You can calculate such property on a class side, something like this. Index by CitizenRef and RelocationDate, and method which looking for the next date, and returns true if nothing found. Index CitizenRelocation On (CitizenRef, RelocationDate); Property IsLastKnownRecord As %Boolean [ Calculated, SqlComputeCode = {set {*}=##class({%%CLASSNAME}).IsLastKnownRecordCheck({CitizenRef}, {RelocationDate})}, SqlComputed ]; Method IsLastKnownRecordGet() As %Boolean { quit ..IsLastKnownRecordCheck(i%CitizenRef, i%RelocationDate) } ClassMethod IsLastKnownRecordCheck(CitizenRef As %Integer, RelocationDate As %Date) As %Boolean [ CodeMode = objectgenerator ] { set storagename="Default" set storageInd=%class.Storages.FindObjectId(%classname_"||"_storagename) set storage=%class.Storages.GetAt(storageInd) set indexLocation=storage.IndexLocation set indexLocation=$name(@indexLocation@("CitizenRelocation")) do %code.WriteLine($c(9)_"quit $order(@($name("_indexLocation_"))@(CitizenRef, RelocationDate))=""""") quit $$$OK } And result you can see below
go to post Dmitry Maslennikov · Feb 8, 2016 Sure, you cando label^routine(arg1, arg2)set result=$$func^routine(arg1, arg2)
go to post Dmitry Maslennikov · Jan 21, 2016 Final method or not it checks only in a compile time. Much helpier would be if you show an error which you get.
go to post Dmitry Maslennikov · Jan 21, 2016 I guess that you writing an function for rule. And your class where you do it extends Ens.Util.FunctionSet where Lookup is located. Lookup is a method and you should call it as a method, now it is as variable. /// Returns the participant code based on MSH-4ClassMethod getParticipant(iSendingFacility As %String) As %String [ Final ]{ set a = $PIECE(iSendingFacility,"^",1) set b = $PIECE(iSendingFacility,"^",2) set sc1 = ..Lookup("ParticipantCodeMap",a) if sc1 = "" { set sc1 = ..Lookup("ParticipantCodeMap",b) } q sc1} And if you want to call it by terminal, it should be so: write ##class(Ens.Util.FunctionSet).Lookup("ParticipantCodeMap","1083601330")
go to post Dmitry Maslennikov · Jan 21, 2016 Well, with this example, I just changed that block, which works for all rest pages in a group except the first one. <masterreference masterReference="rest" pagePosition="rest"><document width="8.5in" height="11in" marginLeft="1.25in" marginRight="1.25in" marginTop="1.0in" marginBottom="1.0in" headerHeight="1.0in"></document><pageheader><table orient="col" layout="fixed" width="6in"><item style="text-align:left" value="Sales Report" /> <item field="@name" width="2in"></item><item style="text-align:right" special="page-number-of-with-xpath" field="@name" /></table></pageheader></masterreference> And it shows Sale rep in a header where page counter was shown before, for exampleSales Report Jack 2 of 5Sales Report Jen 3 of 5You can see my result here. A changed only first section.
go to post Dmitry Maslennikov · Jan 14, 2016 Templates in ZEN, is a quite simple as I think. When you doing template page just add <pane paneName="MainContent"/>. And then in a children, you should add XData with the same name "MainContent", which starting with tag <pane>. XData MainContent{<pane xmlns="http://www.intersystems.com/zen"></pane>} You should not rewrite Contects XData in children pages, and such subpanes could in the same class, or in children.
go to post Dmitry Maslennikov · Jan 13, 2016 In this case, in a table you just add a new column with link <column header="" width="5%" linkCaption="view" link="ZenTutorial.ViewContact.cls?ID=#(%query.ID)#"/> so, now, we got an contact's ID in every row. and then in a ViewContact page, we should add a dataController, to our Model, and define an modelId, from url <dataController id="contactData" modelClass="ZenTutorial.ContactModel" modelId="#(%url.ID)#" /> You can set modelId with URI Parameters as weel, after adding a property: Property ContactID As %ZEN.Datatype.integer(ZENURL = "ID"); and new modelId, which now uses our new Property modelId="#(%page.ContactID)#" and finally form, wich connected with previously added controllerId, and it shows two fields, read only, yet. But it is not so diffucult to add editng. <form id="MyForm" layout="vertical" controllerId="contactData"> <text label="ID:" id="ID" name="ID" dataBinding="%id" size="5" readOnly="true"/> <text label="Name:" id="Name" name="Name" dataBinding="Name" size="30" labelClass="required" required="true"/> </form>