go to post Stefan Wittmann · Apr 13, 2021 Another option is to look into the Request Transformer Advanced, since this plugin support regular expressions and allows for dynamic content: https://docs.konghq.com/hub/kong-inc/request-transformer-advanced/
go to post Stefan Wittmann · Jan 18, 2021 Hi Akshay, this functionality was teased at Virtual Summit but is not released yet. Also, this will be an IRIS for Health feature, as the DTL Generator works on inbound and outbound pairs of HL7 messages. Best, Stefan
go to post Stefan Wittmann · Aug 12, 2019 Hi Duncan,great to hear that you find the community edition beneficial! We are currently working on making the IRIS for Health Community Edition available on the docker store as well. I can't give you an exact time window, but it shouldn't be too far away. Stay tuned, it will be announced on the developer community when it is available.As Sylvain has pointed out, you can always pull the images from the WRC Distribution page if you are a registered partner. The offerings on AWS, Azure or GCP can still be helpful with zero cost, as you often get a voucher when you sign-up for a new account. Enough for playing around for sure.Best,Stefan
go to post Stefan Wittmann · Jun 7, 2019 You have various options, depending on what you want to achieve:Added a property of type %DynamicObject or %DynamicArray to a persistent classStore the JSON content in the Document Data ModelParse a JSON structure as Eduard indicated and generate the corresponding persistent class(es).I would not advise to use %Document.Object. Use the Document Model instead.With option 1) and 2) you don't need to define a schema at all, but can easily persist and manage your JSON content as objects. No SQL access to individual properties of the JSON content for option 1). With the document data model you can add support for SQL queries for individual JSON paths.Option 3) is work, but doable. Figuring out the correct datatypes will be the greatest challenge. If you have JSON schema instead, your life is much simpler.
go to post Stefan Wittmann · Aug 30, 2018 Hi Tosh,it seems your path is not correctly setup as the process is not able to identify the underlying C binding libraries. I assume you are using the 64-bit version of Python. Also I want to point out that we currently only support Python 3 up to version 3.3 as later versions introduced quite significant changes in string handling. We are working on supporting versions beyond 3.3 at the moment.HTH,Stefan
go to post Stefan Wittmann · Aug 30, 2018 While it is true that Generics are not supported by the Java Gateway I would like to provide a little more guidance on why that is the case and how to deal with this not uncommon situation.The Java Gateway (and the dotNet Gateway by the way) allow you to interface between ObjectScript and another language environment and obviously there are concepts in one language foreign to the other. Our approach to the Gateways is to support basic structures and concepts which are similar in both languages or easily translated between them. A "complete" approach would not only take very long to implement, would be hard to verify for correctness and because of the rules you had to apply not easy to understand. It would defeat the basic rule "power through simplicity".Generics is a case which is not easily mapped and therefore not supported. Of course you can come up with ideas how to support such a concept with what the server-side environment has to offer, but keep in mind what I wrote above. Every time you encounter such a situation you find yourself in a situation where the Java API you would like to call from our side of the fence is too complex and properly includes functionality you don't want to interact with in its entirety.The Facade pattern allows you to easily work around this challenge. Build a basic API around the functionality you want to interact with on the Java side and import your handwritten entry point. This makes the interface much more manageable for the gateway and all the participating parties as the contract between Java and ObjectScript is very clear with this pattern.Hope that helps,Stefan
go to post Stefan Wittmann · Feb 21, 2018 I am not sure if I got the question right. If you already have a Zen or Zen Mojo application and would like to add a login page, I strongly recommend to develop the login page as a separate CSP/ZEN or Zen Mojo page. From my experience Zen Mojo is too heavy just to build a single simple login page (as it is designed for a complete SPA - single page application), so CSP or ZEN is recommended. If you are starting from scratch I usually recommend to pick a modern framework like Angular you feel comfortable with and communicate via JSON/REST to the backend. Responsiveness is usually achieved by a mix of picking UI libraries that are responsive by default (e.g. Bootstrap) and your own responsive CSS implementation. If you require a native application for mobile devices on iOS and Android (e.g. to interact with the camera) you have to be a bit more specific. But your options are either a native application (Swift or Java) or a hybrid (e.g. via Cordova or Ionic). The communication channel always is JSON/REST, so you have to start by designing your REST interface first, no matter what your web client looks like. At least for the majority of the use cases. Please let me know if you require additional information. HTH, Stefan
go to post Stefan Wittmann · Oct 12, 2017 I also advice to use a local mailserver, which eases configuration and testing. A popular example is PaperCut:https://github.com/changemakerstudios/papercutIt is much easier to spot configuration issues as you can take a look at the mailserver logs as well.HTH,Stefan
go to post Stefan Wittmann · Oct 12, 2017 Interesting thought Sebastian. We haven't run dedicated benchmarks on this topic, but I can provide some guidelines. You have to acknowledge that creating a dynamic object or a dynamic array is the most expensive part of your code style compared to just using plain variables. You are instantiating an object. If you run a simple benchmark like the following you can observe a difference: ClassMethod TestAll() { set iterations = 1000000 set start = $P($H,",",2) for i=1:1:iterations { do ..TestDynamicObject() } set time = $P($H,",",2) - start w "Dynamic Object test case took "_time_" seconds",! set start = $P($H,",",2) for i=1:1:iterations { do ..TestVariables() } set time = $P($H,",",2) - start w "Variable test case took "_time_" seconds",! } ClassMethod TestDynamicObject() { set do = {} set do.setting1 = "value" set do.setting2 = "value" set do.setting3 = "value" set do.setting4 = "value" set do.setting5 = "value" set do.setting6 = "value" set do.setting7 = "value" set do.setting8 = "value" set do.setting9 = "value" set do.setting10 = "value" } ClassMethod TestVariables() { set setting1 = "value" set setting2 = "value" set setting3 = "value" set setting4 = "value" set setting5 = "value" set setting6 = "value" set setting7 = "value" set setting8 = "value" set setting9 = "value" set setting10 = "value" } The result on my local machine looks like this: USER>do ##class(User.DOAPerf).TestAll() Dynamic Object test case took 13 seconds Variable test case took 0 seconds So there is a significant difference IF your code is called often enough to actually make the overhead noticeable. In the above example I called each method 1 million times. If your code is not called that often you will not observe a difference. As a general advice I would not nest the dynamic objects or dynamic arrays when used as you describe it, as this increases the number of object creations. Long story short: Stick with variables in performance-critical parts of your application. In other parts of your application you can use dynamic objects or dynamic arrays as temporary objects for sure, just make sure you only nest them when absolutely required. Passing complex structures between method calls with dynamic objects can be very elegant. HTH, Stefan
go to post Stefan Wittmann · Sep 28, 2017 Embedding a JLNP file in a CSP page is the same as in a plain HTML page. You have to embed and load the JLNP file using something like the following snippet: <script src="https://www.java.com/js/deployJava.js"></script> <script> var attributes = {} ; <!-- Base64 encoded string truncated below for readability --> var parameters = {jnlp_href: 'your_applet.jnlp', jnlp_embedded: 'PCEtLSANCi8qDQogKiBDb ... bmxwPg==' } ; deployJava.runApplet(attributes, parameters, '1.8'); </script> In order to figure out the value for the jnlp_embedded parameter you have to base64 encode the contents of your JNLP file. The JNLP file has to be accessible from the relative link provided by the parameter jnlp_href. This tutorial explains how to embed JNLP files: http://docs.oracle.com/javase/tutorial/deployment/deploymentInDepth/embe...
go to post Stefan Wittmann · Jun 7, 2017 Hi Lucas,I suggest you open a WRC case with Support so that we can look into the details of what is happening here. This may be a problem specific to the environment.Regards,Stefan
go to post Stefan Wittmann · Jan 30, 2017 Hi Jules,which Perl distribution are you using? We do support the ActiveState Perl distribution. Also, ensure that you are using a bitness version that matches the bitness of your Caché instance (64-bit in your case).HTH,Stefan
go to post Stefan Wittmann · Nov 14, 2016 You are correct in your assumption, you have to work with streams to operate on arbitrarely large JSON. %ToJSON and %FromJSON work with streams. Here is an example how streams can work with %FromJSON to read a file: set fileStream = ##class(%Stream.FileCharacter).%New() $$$THROWONERROR(tsc,fileStream.LinkToFile(<pFile>)) set jsonObject = ##class(%DynamicObject).%FromJSON(fileStream)
go to post Stefan Wittmann · Oct 26, 2016 Hi Simcha, you can easily retrieve the data that you are using in your layout (AlerTList in your case), by calling the function getSourceData() on your documentView component. Assuming the id of your documentView is 'mainView', the following code sample should work in your environment: var view = zen('mainView'); var data = view.getSourceData(); console.log(data.AlerTList); HTH, Stefan
go to post Stefan Wittmann · Oct 21, 2016 Hi Jiri,take a look at this part of the documentation:http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...I recommend using a code structure as described in example 1 (try-catch).HTH,Stefan
go to post Stefan Wittmann · Sep 1, 2016 As I mentioned before the onevent method is not directly called for most events. The onevent method is only called for viewport changes by default. Here is an example how you can register your own events. Everything happens in the homepage class. Step 1) Subscribe to the onPageShow callback Most pageManagers implement the onPageShow method to let you know when a certain layout has finished rendering. This is a complete documentView example: <mojo:documentView id="mainView" ongetdata="return zenPage.getContent('data',key,criteria);" ongetlayout="return zenPage.getContent('layout',key,criteria);" initialDocumentKey="login" initialLayoutKey="login" > <mojo:jQM-1.4.3-PageManager onPageShow="zenPage.onPageShow(layoutkey,documentkey);"> <mojo:HTML5Helper/> <mojo:jQM-1.4.3-Helper/> <mojo:mojoDefaultHelper/> </mojo:jQM-1.4.3-PageManager> </mojo:documentView> Step 2) Implement your logic I'll just paste the code in here, as I have documented the methods individually: /// Gets called when a certain layout has been rendered. /// In this case we are registering additional events and /// forward them to the onevent callback method in the template. ClientMethod onPageShow( layoutKey, documentKey) [ Language = javascript ] { if (layoutKey=='login') { zenPage.registerEventHandler('txt-user','keydown'); } } /// Register an event to a layout object by key. ClientMethod registerEventHandler( key, eventType) [ Language = javascript ] { var element = zen('mainView').getItemByKey(key); element.$findElement('').addEventListener(eventType,new Function('evt','return zenPage.myCustomEventHandler("'+eventType+'","'+key+'");'),false); } /// Forward an event to the onevent method in the template. ClientMethod myCustomEventHandler( evtType, key) [ Language = javascript ] { var item = zen('mainView').getItemByKey(key); var template = zenPage.getTemplate(); template.onevent(evtType,key,item.$findElement('').value,'mainView'); } Zen Mojo does not provide a lot of special methods for this task. It involves some coding.
go to post Stefan Wittmann · Aug 29, 2016 Whether you should be using the default transport layer of Zen and Zen Mojo or built your own REST interface depends on a couple of things:Your skill set and your development resourcesThe size of your applicationHow many different front-end interfaces you have to serveIf you have to serve multiple front-ends, e.g. a native mobile app, a web app and some data to a reporting layer then a REST interface makes you more flexible to actually meet the data needs of each of them without duplicating too much code.If you just want to get your Zen/Zen Mojo application working without too much extra learning, the standard transport way is just fine.In general REST interfaces are just a clean way to build your communication layer. If you make your REST calls in the Zen Mojo onGetContent method you will still get the benefits of client-side caching within Zen Mojo. The only real difference is that your data retrieval code now lives in a separate class (a subclass of %CSP.REST) instead of a Zen Mojo template. REST interfaces are indeed easier to test and debug as they can be tested by tools. The Zen / Zen Mojo client/server communication requires some knowledge if you really want to know what is going on.HTH,Stefan
go to post Stefan Wittmann · Jul 28, 2016 I haven't dealt with SSEs yet, but I can say that WebSockets work like a charm. SSEs are not using a special protocol, they work within the HTTP specification and are build on the server by setting the "Content-Type" header to "text/event-stream". From my understanding, this can be easily implemented with a CSP page. The reasons why SSEs are not as popular as WebSockets are:a WS is bidirectionalWS are supported by all major browsers, while SSEs are not supported by IE and Edge (http://caniuse.com/#search=server-sent%20event)SSEs have some interesting advantages over WS like the use of a simpler protocol, automatic reconnection, and event IDs.
go to post Stefan Wittmann · Jul 19, 2016 Hi Fabio,yes, in theory, there is a way how you can load other templates, but I do not encourage this approach as loading a template can be expensive.It is better to use one of the following two approaches:1) Generic utility functions should be placed in a javascript file that can be included2) You can also build a base template that includes your utility functions and let your other template subclass the base template.The second approach makes sense if it is unlikely that a given template that requires these utility functions will be loaded and you want to save the footprint. Otherwise, I would always stick to option 1.
go to post Stefan Wittmann · Jul 15, 2016 I haven't done this before, but I am pretty sure you have to call %Save in order to apply your changes.