Clear filter
Question
Naveenkumar M · Nov 1, 2022
Do we have REST API documentation to retrieve the data available in InterSystems Cache.
I am looking for APIs that will help me to pull the data available in InterSystems Cache. Hi Naveenkumar,
I think the first look does a great job of walking through this. Hope this is helpful:
https://docs.intersystems.com/iris20222/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_rest The "Full Stack Tutorial" link on https://developer.intersystems.com/ is another source of help for building REST APIs. Also there are a plenty of examples in OpenExchange, which you can try via ZPM (IRIS package manager): https://openexchange.intersystems.com/?search=REST&sort=d.desc
Discussion
Vadim Aniskin · Feb 24, 2023
Hi everybody!
Many developers prefer a dark version of applications. Not surprisingly, @Guillaume.Rongier7183 posted an idea of making a dark version for the Developer Community.
So we look forward to hearing from you.
Please send us your feedback by using this Poll on the Ideas Portal, and by voting and commenting on the relevant idea.
Thank you in advance for your votes and have a good day!
if it's not the default I won't care Third choice could be phrased better:
I suggest "Doesn't matter, I will use Community regardless of interface color." Thank you so much, John!I really appreciate your advice.
Please ensure that any dark version uses our white logo as the default color is invisible in dark mode. @Guillaume.Rongier7183 Thank you for your idea.
We got several comments on this idea here and on the Ideas Portal.
We discussed this idea with developers to estimate the resources needed.
We got 3 votes supporting this idea, and based on poll results 56% of users answered that they'll not use the Dark version.
Based on this input we move this idea to the status "Future consideration". We'll discuss the Dark version again during Community portal development planning. Thank for the feedback.
I think I will continue to use my sunglasses to check the community at night for a while
Article
Anastasia Dyubaylo · May 26, 2023
Hi Community,
You probably have already seen this abbreviation SSO on different InterSystems sites: Community, Learning Portal, Global Masters, etc. It basically stands for Single Sign-On. This means that you need only one set of login and password and you can access all the Developer Ecosystem resources.
Thus, you create your account once and then use it everywhere in the InterSystems Ecosystem. Just look at the top menu with all the interesting resources that will help you grow professionally and personally:
Use it well!
Article
Andreas Schneider · Feb 22, 2017
I' have done some tests with Caché and Apache Zeppelin. I want to share my experince to use both systems together. I'll try to describe all steps that are required to config Zeppelin to connect to Caché.
What is Apache Zeppelin?
For all who think: What the heck is Apache Zeppelin?, here some details what the project site (http://zeppelin.apache.org) says:
"A web-based notebook that enables interactive data analytics. You can make beautiful data-driven, interactive and collaborative documents with SQL, Scala and more. Apache Zeppelin interpreter concept allows any language/data-processing-backend to be plugged into Zeppelin. Currently Apache Zeppelin supports many interpreters such as Apache Spark, Python, JDBC, Markdown and Shell"
Install Apache Zeppelin
The next 5 steps describe how to get Apache Zeppelin up and running:
You need a Java Runtime Environment. I you haven't download and install from here
Download Zeppelin from here
Extract the entire Zeppelin Zip-File into a folder like d:\zeppelin
Open a shell (cmd on windows) and navigate into the folder \zeppelin\bin
Execute zeppelin.bat on Windows to start Zeppelin Open up a browser and use this url http://localhost:8080 to open the main page of zeppelin. You should see something like this:
Well done! Zeppelin is now up and running!
Connect to Caché
Now let us introduce Caché. The next steps describe how to create a jdbc connection to a Caché Namespace.
Navigate to the menu item "anonymouse" -> "Interpreter" and scroll down to the "jdbc" section.
Now press edit and go to the end of the jdbc section and enter your Caché JDBC connection string cache.driver = com.intersys.jdbc.CacheDriver cache.password = ??? cache.url = jdbc:Cache://<server\ip>:<port>/<namespace> cache.user = _SYSTEM
Add the path to the Caché JDBC driver in the "Dependencies". This is located at the end of jdbc section.
Press SAVE
Great! All preparations are done, now let us use Zepplin and Caché.
Query Caché
Follow these steps to create a first Notebook to query and visualize some Caché data.
Press create new note and name it like "HELLO WORLD" ...
By typing %jdbc(cache) you inform zeppelin what data source you want to query.In detail: The %jdbc keyword lets zeppelin call the jdbc interpreter and the cache routes the query to the Caché connection. If you want to use more connections to Caché e.g. another namespace you have to create more entries in the jdbc section you've done before. The prefix of the entries are the connection name.
Ok now place a sql statement in the next line. After that press execute and you will immediately see the result:
Happy testing! Nice article Andreas!Have you perhaps also looked into creating a more advanced interpreter, rather than just leveraging the JDBC one? I know that's probably a significantly more elaborate thing to do, but a notebook-style interface for well-documented scripting would nicely complement the application development focus of Atelier / Studio.Thanks,benjamin Thanks Benjamin!Yes I've checked the sourcecode to see how a interpreter is done. It looks not like rocket science.. probably I've not completely understand the details, so I can say that ;-)But! ... I have no idea which functionality would be helpful in an more advanced Caché interpreter. Can you give me a hint on what features do you think, please?It should be very easy to implement something like a simple code completion with Caché Keywords to use in a notebook. But at this time I think all is limited to the JDBC interface, and with that to SQL.Would be really great if we could use also COS to fetch data... !? yes, the two-word feature called "executing COS" would probably be quite a step up. It was more a loose idea than something I've researched thoroughly, but maybe the authors of the Caché Web Terminal have some clues on how the connectivity should work (JDBC won't pull it). I'll created a fork on github (https://github.com/andreas5588/zeppelin) for Apache Zeppelin. My plan is to create a Caché Interpreter (first JDBC based) to learn and unterstand the architecture of Zeppelin.After this it would be great to extend this Interpreter to allow to query the Caché Data via COS. For this I'll contact the "Caché Web Terminal" guys maybe they can help...All are very welcome support this open source Interpreter. So feel free to jump in and support this project by coding, idea, testing ... or what ever ;-) Here's an article on how to write your own zeppelin interpriner. The article is considered as InterSystems Data Platform Best Practice.
Article
Eduard Lebedyuk · Apr 3, 2017
If you're using Firefox, you probably know that there are search engine addons that allow us to use website search directly. Now, docs.intersystems.com is also available as a search engine here. Here's how it looks:And after clicking on InterSystems search engine you're redirected to the docs.intersystems.com:Download here.UPD. Added InterSystems IRIS documentation. Download. Very neat! Would be much better, if InterSystems will add OpenSearch to their documentation. And I think it will be enough only for the public version. And in this case, it will be supported in all modern browsers, without installation anything external.
Something like this.
<?xml version="1.0"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>InterSystems docs latest</ShortName>
<Description>InterSystems Ensemble Documentation latest Version</Description>
<Url type="text/html" method="get" template="https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.SearchPageZen.cls?KEY=&KeyWord={searchTerms}"/>
</OpenSearchDescription>
Well, that's actually exactly what this plugin is.
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>InterSystems</ShortName>
<Description>Latest InterSystems documentation search</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAAAA8AXHiAAAX+klEQVR4nO2dT4hf13XHP0cVpQRViC7aUroIRp0pzSIjSluX1igmtHgTjDFmZhHoYoQZBF1qjFeBrBxNvShGiFBpY0IYgTHBKJTiLroIInKizrimoTMYU0IIppgWgjGKqszJ4t1z77n3vTeSZt54dH76HfHTu+/e+96787vf3/nzvX8ezGUuRyBy3A14LGTz2gmQlxH+DfgvllePu0Xh5cRxN+AxkRMIyyh3UP0nNq/9CZvX59/NIWT+5QGIgCoIXwAuIHIbuMLm9QU2rx1360LKHFiQQOW9Aj0FrCFqAHuKG3OAPYrMgQVFY6GWYd7nGYSLoO+jXGXz2lNzE/lwMv+SgApQVZZ0H5FTiKwBW6BvsHnti9y4/rm3MpLMgQUFV6rU4NImLacRuQjyAapXuHH9LJtzgA3JHFjQmUJxRyjnbZ3OyT+FyEVU74BeYfPa2bmTX8scWCb64CpAC7bTIBcRuQNyhc1rcyc/yRxYUPwp1WL+/FEpZW0dUVA9DXoR2EK5wo3rC0+6DzYHFmQfvdZGdIASOvCIlPLq6M1o8sGU2yidBntCTWToIZ3FcxtnVHVPRH6xs3Xp4De6cf0k8C7wFRr/vSe+3NKd39W/UPkU9DvA6yAfsbK6d/BGxpLYGkt5GritqmuL5y6fOvh9vGnL9+6bPiuwPEnnInX9IqdA1oA7HU1x/eyT4oOF1lgLSxvPCXxfhRMoH4JuAN9F5NPdR9Fgm9dPIrwLWjSWSmcCW/XUZ+mhpShGy/VTlDeB1xH5aJYHu0NrrMoNEj2L8G3gfVTXFpc2Th/8rv7OQ+Spd/CdtmrLoQNouXdHU8D7QEdTzKiTH1pjLS5tPAd8n05jYWBQdA/kI9DXEd5E5bPd7X002I3rJ1F9F+ErNRA8qMzkecAlraY0ee5yj1G0veUvgO8ifAv4b5YvHO4LeYwktMbqRF3HSRqBkRMinEW4ivIB6MWFB2owp6mE4Y+BS7S+zhOsUDSWJ1v9M3I0Kae7oSL5oBuLnB2aYgaAlZSAarJIimZTBSLylCBXQG8vLm2sLSwNOPnmiPshHaUzY+rTxnUNNCDnq8trP54b8/yYOfl6G9WZMJEzACxJikIQNCsDE03/ROSPQa8CWwtLl9cWli6fXjy3ke/RHdohHRxn5e4rUtfFaygr0+Y++9yzPPMMyEXgThqL/P1DfDHHKjMArCS5wwRxQBEVxHWkiJwVuAr8SFXXFpYun37geI6MnuTn9IulX9U0nr9GHcgK2XoauAj61/s37PGV8MBStLJOxepor465Y9p13gIJYH/0D//3svy//mZ1F3U2TJvzoY/4p1Me5lrRMfjuXHXgSLmfDoA4iIQGVg6wpJxJKhGRQkclc6mmEBIfJSKIyIL8ijd+918/+2fgLVTv5Q5VZ6cqG5vSFg2a/5XztYAiY01c3ZSXh4ncvb2fFxdXsYGVQeKOnWJw6aq+DKcVzrz/y/8AloFnQN8C7lc+VfXUJu2AXQBDhZem0cPm04CW1WpcCQ2swQjMDo1trC1bV1jNRgZYvrDHyoX3EFlG+EtU30L1brnhwM28CRvM36ee3debQiU5/g/w+x5zCQ4sM3zD3JO3TpXSMS2XLVrjDy2v7rF84ccJYOdB30K5OxLieV6qfrAM1aNopdyW1hwOqbpYEhpYxcca7gRh4HffAxkDGUk6gL0HLIM8g/I90Ls18WlRXkMv+FZWDrt7ZnWf9h5zjXXMYhGfJ0aLHRRXz8yNpgl6Vl96NrGRlQt7rKz+GPRF4DzK28DdQnLax0eQ1GV5hEBLXejXz+08+DfyOEhoYGW3PTnDIiXaA+9rpUgraQlJqkxKgocyPSvmg/EScB7kbeB+mQiI01hGLwh5loTXTFWAKU1aHqo5j7OEBtagOLMmuYMK0DT1fAm6DhDaL6/usbz6HsKLIH+B8nb2wbxj17d17tjm7ZeOJ8GB1Q3XAGmMMEV8LvrzRKmouS7F1LR1HkmWV2Fl9d9BXgI9j2qnwdoJf95ker6qN4/em9DYtjA4sNLwTTJrnTUqGkiyeaTxWbrrurHnCSKwldViIoW/6/NUZiZdIzyfVY07UpvKoBIaWKatehbEnWciO/s9pV7FEkyhIJYv7AE/G0SF11ZDDc0cyVBZPAkNLMmEgoukMgGaIj7rH6Xmj9xRdUIN0UZ8dUFzTp3n59H31WwoOXncDTi8JMdcHYiGUOI0lWHMzmVK7bCvL55+CLkB+wAnLqaA4BrLy2B/emUwUjcXTtWRlckbapXUqPZ1arQzStwGkNDA0vy/hXvdp/heziT6uqRo0NKTOssNmocWWVRW0JOhI7+EgBIaWOBg45xeYUAj5M4UfE2Y2BQiBUBD0aHl56NFhFprzrjKCgjuYxWTp2VSAC5atHoiKIqo1APOhZqfDlzibm4RaWWHhUGOqvK5gqsrggNLbSxQJI+aqKqLBAs/lId72ntIN1d+Mj7SRwY9V0trbWaLYvP0ZK95Y4MrtCkcIjfFd06LonZjD9FiDCczPS2J1pTlJktz9JebqosroYGVxfVDN3oidVkr0lMl04nYEI1/TlWhPHfU8s011rGLKac8BaanpXxdFxFq8cRs2s000gzR9EhSl5b88H7d2LiaBR8rGTM/q2FEEQ3VtfrT+VjKYCSYWtBLj9WNbQljA6sTc35LCJZdrGQWLTe56fnK7hwm9WmyFdsHqUOWrrcvxAPu8ZhLaGDlscIcYXW5XfQnxdSIzYLw+Ti/eUL1kDE6dE8HYG8qhzTVqI8WQ8L7WICzY+ZnSZ6XJa0pSlFXy3VNpxyawKEaLpL6OS14qiGduKCC4Bqr/P6TsVOyscvTkxunvh5h2XcE8WCStWFzb5u5kOkQ01RG2HoT6E17TAkNrMaeZdMozp7UGsvI06YTtae/Dtemls1QB6KcP+Kox8ZTltDAqodhhrippofGIrQpzc6QbyS9xIgv5vy/IYI3kMyAj9U5MV7n2NZFeQaD0iv3NrE9P5w47qK3DKxxsCzPE2rqL4groTVWFpXqx98bUJaU1/CPZVWWTLdVQtWQJgLshaMNeII77F5Cayz1nTQ2etKeC3knmp5vM02jHlDuTfbDNjyehAaWJzzzMI2aISx5XTm5HuDKSTMipjQ9zgRWZtY59t7sNXRJe5uIEtoUViy6MyN56swA8Vjt7pe0hxrBOoXk+TsUs1iRnimR+Q9rp9YRoZvyE1FCA2tsct7QJiF9q1jTFJNvR5Xv59n2gci1neee82PzDqFNYTF5dt4/Dm0ZmY/NKulppAHDUIDXRqAPOg8ooYFls9tt/LbVB11ZMndW3/OUIkfXhwaoNkDwY4N5Nqn0fxW+PKCEBtbY164ukfl1pzlsOX41/nsUprD1sbqHj6T9ddK/LpiEBpZ3Y2wCDKo1iCruypGSdmGPuDysaP2pIsKRfL9VZKW64iIrtPMOHVjEZgMkFZS1FM5EGhFKoSmKmZTpfCw/pFNhw+VZwuoOac3YuIqtsbz4qcYdVBLopNASNpUmb3WU83S6TsyMeqOZ1OVV3KhXqV6TxZbwGgvIIyVSqagyY3QIZJbnr59E/JsmPH+VjzaW2KgpPxQwA+AKDyzb56oelysdV1Y7+2vcMVuoiTpzjH/KJGhLjjrDPTR+GFTCAwv6Y7f+ZQK+j9tZwPU9JrWFI1lthDhUP7Bj5WQmgGWWpQzDOcdctdZaWuuEzuefOipMTzOzbADPRdKYu4pcK39U4NkOMwGsnsbyZtGPuRkAfdjIlNqqed7oUnvfaBcdzpCEBlbeuwEpWsfRCqYx1JxmjywttEN2qqcQ72PpgBbK9fwz0zW98rgSGlg+6gPyvg2Fo6o1Rl5sYaBKJlOlv1nIYVo1nE6mLeNuiMfy5bElNLCqoL2aDkNOe7E6paqLHCejG5SeCfQnY7jr5cVGWGhg1fpAB8pKbs+Hdg5/2ZZ7ikYNcVEtoeWLtPhlfiV0XEwBwZl39YZQbVMj96repIk6s2eroaXSVJY/XVzouCqzxp6f8tsombR0hF97GFSCa6zCV5X1gk0dN3bo+6lvFqdrVQWUKtmAqm3zAzmuOBIaWJr/9xGVN3q+a2zpRSpXcaZxSuedZsjGbK7UNrgVz3P1eJF4EhpYkIBiXKSfrZDKK4jlE6kUy7Sb27rxxzrRpxhsq8ieY1//OCJKaB/L/8jzRiBQe0xpxkA7Rbma3TClqOxDdjYO/b7mLi6oYCY0VmP2MilaZjFg6wi1Kze9hjn6OqF2aAPAysT5ch+jtryI/R1xwRUeWFW3iHlM3iwqBUT9HvYT/iaVQb7Km0UZqDhyfUAJD6yspYA8V1w180PeeffaI8/LksLATyJ5Kozjs4bu3eZXFjmu024SHlidFNqhOqdx5FvzUwFtqqZ4UOGiwfrROZjwbckNiU+ShnbeoQNO4Ug1R/ZAISYzSdn0lQPitH3oIkOtn997U70v820NDCqYAY3l3ZcheGQTZ8M2Vs9M0ZEohgEzODhzoXlytaw+NrJmQGOpMynk2Q3+3dDew897ZtlUYemPMx5OzN5lPqOJCl15ilJzw3Hp4PPew2ssoMd9VlNTqkhMG602seOOPTM1pLqt0RptuQzUN+I0roQHlo8KjTrImMLRDw3BZMWF+5oKXHVUWjnn+dTl+3nVwbWUlxkwhY2nmxEjnsEycgHwC1qtzhFqLGmKqpkXQ2aQSolFldnQWNlx7zrIDKA4cJnUM7SAqZn3IROYgdI8w2su16ReOqCEB1Yt4v6n882bzsyzRc137xA4XROGhm/2qxt42GY/mQlgafKRzLcqe5NqNnfef+mx7VOPy43dql2n1vOrWm0XV8IDqzfWl2yj6a5s+Hpmxw1fe3Z82sbVUeoQeKXWoMFny2QJDqy0L4PNZPD+cE5LNcdOzP7lhax+nHECMS3k9xXNkSKNqRR6kaDPC2wmgwOrF3JRHCfrIwvrycx7RYiaWZyaI83HJsQr9rpfxw/32J8UVMLTDYVwMDA1FGg1t91IB6nMp/i1fYdvDvlmY8x667RXatZdH1dhzQKwHgEU/d1DgIkVg3fIRWreahAwUrdLeomQEh5YWSm0HKmltX/0+5tpe8EULRrFRMOhVXn7peNJcB/LOeNVXj89tJwvl7dO9SFbNB7ZDWWOsKLBo8PwGss6Up0PY/y7Qv1Rn+fGDNNtpmzSIFKHxgIr9en9sdgyA8AycT4MHZXQ8268Y98EYNP1pQGl0T49h91f43g077wHlvCm0OiFyqC4CXNjW6nXNnFC5n3oHThjFrA3pDOWjiczAKwk1bpBo4TKtttD6wf928OOjIscHS5yJOogiGI7WeGBpQ35CbV5qzYIySAqVPzkrz3pYaEZssl1pGgsj6Ejcfo+fwnvYxX/qeTVwzpFI3U8aN/cHJ228g2EvHjCP77dY97qB59BGh5YJvmt0DabNHOUUs5VqtpH03W9WJTi0Pty9j/GxlV8YGV45DFeGdZekMcJlay+7NIJRajVFC4t1ohy7re09K/1DTwADTMArGpJFwUvnhDN/Zh8sY5m0kw3+Zc6TSLtymxocDYCmthYqiS8826OTH5ZE9o443XkpZSZDGOv/p2uaaZGvQYaMnPOs29XTgeV8Bqr9IFUxGQ3y6FeRlGz7VJFjZN5XNXmtkljZSZeC8habdbyasGdrPDAghL5+fc654WpJQcofSiibgujNlo8jNg9W2AMcSFtlZbVjQuu8Kaw2tEvs97lDaq26rmawOnnnpupmqoPPfcxdM8hzGSeK2k7jW8LwwPLeqUaukmmRxygzBxJQRN9LTJZc0bu22vkcN7Qfg/BZAZM4Rgqiq8F1kcNBWDDPo9r/wWmHMIDS92/nOeW3JeXXda1VNX5ZBMjq+JCtc5v+dF205DSwGnb9DlLaFOYjGBvvDbPc3dltXNujnsqm3L5V48XleGyoXJ/elRL0j4nCQ0sIwqA2jnv1ZP83sL8Cl+tZz1MZ3W0GjrqNWpoyVeVL+W6wKYwNLAgDeHkdJGyrC+ZmuwQm09lJugIOq96fa+4PMZB5Y+peYGDwvjA6lmTpk/rd0JrMwUqsfCTmh2vonzU+SgRqIQGFcyA8w5UoGj95RowxoRLk2bCjtSHJ87bSQ2DhTFlNoDlpFrKB4OA0WoaywhRfvAWNM/d58aZFHUNmQFyFGYFWPsQ3aPOfB4jzJefWljaOPz30U7c6wGkaVH1I2h+FYGVVnhgVTMUkiaycUKvmbT555dcqegJRb8NemXh3OWzi0sbh2iRlCGiaoPd9EwVl/blA/UDK63wwKotTvnF29yGUk/SzOC6ROgCNhE5hbAG3AG9unDu8hcXzx0QYNmFkyYtTdqXW/td/cASHliA80uMk5K8HbcMOlxOz0kLPjmNyJoo/6no1YWlywsHBljLtDOU3odADSzhgaXYPqMdkPKMBszquNXPksykw2G9Ylr98QvAGnAb7QD28I2q7FunEi3Pq1jLH1oJ3Q71BJMZ4bEKd5RZq5Fff0db+fpdOs9AzZxT59YregaRNUG/vrB0+U2EfxT4cGdrfe8BjSqkaL6vgS3ZO22BZnUIr73Ca6wi2VFpsmtTWK8zLHX6E/0SREv9UyJyUeBHqLyxeG7ERLZkbW/w0IYEtObTzOmv0nElPLDy6Mx+H4ol6vJ0pK4609nWyeenFS6i3FbVq4tLG08tLF1uW+SOdupNHoXtr0yevzawHWRWTCG0FqyT5EPlmaXar1JrmDRI7QeD2zG/fJ2cEWUN9OvAdxaXNl5H+HDHX9eLGxrytKckZ8eRD6+xKoc4+yzFT6m2gcyvnUt7NlSgKmV2bRZ/T/fcFCScEpE10DuqevW3f/LLp4ZR4dDev3n154RHFTMALHVaoDZh7ohZIcnmrru2MX9GrCa6otxPS1SZjtb5znidBtZ+718+ewXVb6D6cbbTldgwgYsEfTo+poAZAJa4ri1LvmqOUZwjVnOSWte3uqruHk05KZLUZlPd9LzfuLt3F+GbwDlEvwHy8bDbVQcPlabq0DvJ93NcEhpYiv5E4aaq3jONA92UY+OwugDLayhc0CWdFrL6CR3izyn9XEZckhGUQink+wEsX4CVCx+DfBP4U9DXgE9qZLXOvCWadFAJDazd7fWfCvIC8Cwq7wjcy6ixhaEJFeIWiNrWR+UlmkVv5b0dnMaopjGbnspAkyrirDTR8iosr/4ckVdRvgy8hur/pJu6T37QUX5dn6uEBhbAzvalvd3t9VugLyjyVVRviuj91pSh1oeS0umIK7dzdf1tSiRzXZo3dSvLzNJ1TSCYZXkVVhLA4M9QfQ3434oPgdrXCi7hgWWyu72+t7t96QeIfA04r+hNpTOR2bHPkV93jYhUG7y0NIA6mqJ0teT7dWCUahhpX1lehZULP00a7EsgryF8Ut5IIeUYXHvFbv0+snDuWydAnhaVV4HngJN+4xCkLLBwainlNdIsdOhSPt2Jdi7X9s72+rmHbuiNa3+A8vcgL4P+TkPIvcTy6lsH/AqOVWZGY7Wyu/XK3u7W+i3gedC/Am6KyD0L3zry20LEoiEkpTuoSaNFcHW6cnG+klRq7yFl+cLPQV4FvoTwGiqfHPJPfyxkZoFlsrN9aW9ne/094HmUZ1X1HVW9lycEjnyAyoS2e8TnTUdyYKfV8ZFkZRVWVj/uAKZfTj5YaIDNrCkck4WlyyeBP0fkVYHnUE4WP2rg5Zg53/hL56FrR2X4hbGqbO9uX3p4Uzgkm9cA/hARWF792aHudUzyxAHLZPHcxgngaVRfUfhbRH5LstbxX4zzwaq0L3ei+mg+1ozKzJvCMdnZurS3s3XpFvAi8Deg7yhyz7h4VeO1wIeMxl0V7p5xRv0JlicWWCY72+v3d7fXfwC8gOp5VG+qci8zD8Wxwsatjd/KQ3vi6swFmAMry+7W+t7u9voPEXke9NmOB+OeH76rByAbqukAAeEsyxxYjexuGZMvzwPPqupN0PukSDAPBUEVQZbIca62YA6sUdndvrS3u3Xplog8j8gzwPdEuG8elvFgZftcP+wzlzmwHiDJyf+hCC+inFfkHZD7GT7i/Ky5ZJkD6yFlZ2t9b2d7/RbwAvBMIlrvlvFimZtBJ3NgPaLsbncaDORF4KvATVIUOTeDRebAOqDsbl+6v7u9fkvgBdBnVTVPOJzL3DOYTBaWLp8Anhbkazvbl1497vbMZcbkwPs8zJj8GnZVp8pys6GiAAAAAElFTkSuQmCC
</Image>
<Url type="text/html" method="GET" template="http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.SearchPageZen.cls" rel="searchform">
<Param name="KeyWord" value="{searchTerms}"/>
</Url>
</OpenSearchDescription>
Added InterSystems IRIS documentation search engine. Download. very comfortable as I always use FFX for searching Hi, Ed!Is it possible to introduce a similar feature for Chrome users too? Sure.Open ChromeGo to Settings | Manage search engines...Scroll to the bottom of the windowIn Add a new search engine, enter InterSystemsFor Keyword, enter iFor URL, enter one of:http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.SearchPageZen.cls?KeyWord=%s - for Ensemble docshttp://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.SearchPageZen.cls?KeyWord=%s - for InterSystems Iris docsClick DoneAfter that you'll be able to search InterSystems documentation in Chrome address bar by typing:
i keyword
and pressing Enter. Cool!That works, thank you!
Announcement
Evgeny Shvarov · Mar 17, 2017
Hi, Community!
Let me share the news about InterSystems Technology Student Contest we just have launched!
The contest has two online stages:
Registration and the online test stage: March 17 - April 5, 2017.
Online tasks stage: April 7 -15, 2017.
After that, the best participants would be invited to the International finals of the International IT-Planet Olympiad 2016/17, on May 26-29 in Sochi, Black Sea resort city in Russia.
If you are a student under the age of 25 you are very welcome to participate!
If you know students or professors who might be interested please share the announcement!
The admission is free and limited to participants from USA and Europe. InterSystems will cover the flight and accommodation expenses for the finalists for their travel to Russia.
See the additional information on the contest page.
If you have any questions please comment below.
I didn't see any mention of a "USA and Europe" restriction on the website information.Any reason for not including, say, Canada? Hi, John!Thanks for mentioning it.It's an experiment for us, so the list of countries is as it is on behalf of "experiment conditions". UK is included), so the students from UK are very welcome.
Article
Eduard Lebedyuk · Mar 24, 2017
In my previous article, we reviewed possible use-cases for macros, so let’s now proceed to a more comprehensive example of macros usability. In this article we will design and build a logging system.
Logging system
Logging system is a useful tool for monitoring the work of an application that saves a lot of time during debugging and monitoring. Our system would consist of two parts:
Storage class (for log records)
Set of macros that automatically add a new record to the log
Storage class
Let’s create a table of what we need to store and specify when this data can be obtained – during compilation or at runtime. This will be required when working on the second part of the system - macros, where we will aim to have as many loggable details during compilation as possible:
Information
Obtained during
Event type
Compilation
Class name
Compilation
Method name
Compilation
Arguments passed to a method
Compilation
Line number in the cls source code
Runtime
Line number in the generated int code
Runtime
Username
Runtime
Date/Time
Runtime
Message
Runtime
IP address
Runtime
Let’s create an App.Log class containing the properties from the table above. When an App.Log object is created, User Name, Date/Time and IP address properties are filled out automatically.
App.Log class:
Class App.Log Extends %Persistent
{
/// Type of event
Property EventType As %String(MAXLEN = 10, VALUELIST = ",NONE,FATAL,ERROR,WARN,INFO,STAT,DEBUG,RAW") [ InitialExpression = "INFO" ];
/// Name of class, where event happened
Property ClassName As %Dictionary.Classname(MAXLEN = 256);
/// Name of method, where event happened
Property MethodName As %String(MAXLEN = 128);
/// Line of int code
Property Source As %String(MAXLEN = 2000);
/// Line of cls code
Property SourceCLS As %String(MAXLEN = 2000);
/// Cache user
Property UserName As %String(MAXLEN = 128) [ InitialExpression = {$username} ];
/// Arguments' values passed to method
Property Arguments As %String(MAXLEN = 32000, TRUNCATE = 1);
/// Date and time
Property TimeStamp As %TimeStamp [ InitialExpression = {$zdt($h, 3, 1)} ];
/// User message
Property Message As %String(MAXLEN = 32000, TRUNCATE = 1);
/// User IP address
Property ClientIPAddress As %String(MAXLEN = 32) [ InitialExpression = {..GetClientAddress()} ];
/// Determine user IP address
ClassMethod GetClientAddress()
{
// %CSP.Session source is preferable
#dim %request As %CSP.Request
If ($d(%request)) {
Return %request.CgiEnvs("REMOTE_ADDR")
}
Return $system.Process.ClientIPAddress()
}
}
Logging macros
Usually, macros are stored in separate *.inc files containing their definitions. The necessary files can be included into classes using the Include MacroFileName command, which in this case will look as follows: Include App.LogMacro. To start, let’s define the main macro that the user will add to their application’s code:
#define LogEvent(%type, %message) Do ##class(App.Log).AddRecord($$$CurrentClass, $$$CurrentMethod, $$$StackPlace, %type, $$$MethodArguments, %message)
This macro accepts two input arguments: Event Type and Message. The Message argument is defined by the user, but the Event Type parameter will require additional macros with different names that will automatically identify the event type:
#define LogNone(%message) $$$LogEvent("NONE", %message)
#define LogError(%message) $$$LogEvent("ERROR", %message)
#define LogFatal(%message) $$$LogEvent("FATAL", %message)
#define LogWarn(%message) $$$LogEvent("WARN", %message)
#define LogInfo(%message) $$$LogEvent("INFO", %message)
#define LogStat(%message) $$$LogEvent("STAT", %message)
#define LogDebug(%message) $$$LogEvent("DEBUG", %message)
#define LogRaw(%message) $$$LogEvent("RAW", %message)
Therefore, in order to perform logging, the user only needs to place the $$$LogError("Additional message") macro in the application code.All we need to do now is to define the $$$CurrentClass, $$$CurrentMethod, $$$StackPlace, $$$MethodArguments macros. Let’s start with the first three:
#define CurrentClass ##Expression($$$quote(%classname))
#define CurrentMethod ##Expression($$$quote(%methodname))
#define StackPlace $st($st(-1),"PLACE")
%classname, %methodname variables are described in the documentation. The $stack function returns INT code line number. To convert it into CLS line number we can use this code.
Let's use the %Dictionary package to get a list of method arguments and their values. It contains all the information about the classes, including method descriptions. We are particularly interested in the %Dictionary.CompiledMethod class and its FormalSpecParsed property, which is a list:
$lb($lb("Name","Classs","Type(Output/ByRef)","Default value "),...)
corresponding to the method signature. For example:
ClassMethod Test(a As %Integer = 1, ByRef b = 2, Output c)
will have the following FormalSpecParsed value:
$lb(
$lb("a","%Library.Integer","","1"),
$lb("b","%Library.String","&","2"),
$lb("c","%Library.String","*",""))
We need to make $$$MethodArguments macro expand into the following code (for the Test method):
"a="_$g(a,"Null")_"; b="_$g(b,"Null")_"; c="_$g(c,"Null")_";"
To achieve this, we have to do the following during compilation:
Get a class name and a method name
Open a corresponding instance of the %Dictionary.CompiledMethod class and get its FormalSpec property
Convert it into a source code line
Let's add corresponding methods to the App.Log class:
ClassMethod GetMethodArguments(ClassName As %String, MethodName As %String) As %String
{
Set list = ..GetMethodArgumentsList(ClassName,MethodName)
Set string = ..ArgumentsListToString(list)
Return string
}
ClassMethod GetMethodArgumentsList(ClassName As %String, MethodName As %String) As %List
{
Set result = ""
Set def = ##class(%Dictionary.CompiledMethod).%OpenId(ClassName _ "||" _ MethodName)
If ($IsObject(def)) {
Set result = def.FormalSpecParsed
}
Return result
}
ClassMethod ArgumentsListToString(List As %List) As %String
{
Set result = ""
For i=1:1:$ll(List) {
Set result = result _ $$$quote($s(i>1=0:"",1:"; ") _ $lg($lg(List,i))_"=")
_ "_$g(" _ $lg($lg(List,i)) _ ","_$$$quote(..#Null)_")_"
_$s(i=$ll(List)=0:"",1:$$$quote(";"))
}
Return result
}
Let’s now define the $$$MethodArguments macro as:
#define MethodArguments ##Expression(##class(App.Log).GetMethodArguments(%classname,%methodname))
Use case
Next, let's create an App.Use class with a Test method to demonstrate the capabilities of the logging system:
Include App.LogMacro
Class App.Use [ CompileAfter = App.Log ]
{
/// Do ##class(App.Use).Test()
ClassMethod Test(a As %Integer = 1, ByRef b = 2)
{
$$$LogWarn("Text")
}
}
As a result, the $$$LogWarn("Text") macro in the int code converts into the following line:
Do ##class(App.Log).AddRecord("App.Use","Test",$st($st(-1),"PLACE"),"WARN","a="_$g(a,"Null")_"; b="_$g(b,"Null")_";", "Text")
Execution of this code will create a new App.Log record:
Improvements
Having created a logging system, here's some improvement ideas:
First of all, a possibility to process object-type arguments since our current implementation only logs object oref.
Second, a call to restore the context of a method from stored argument values.
Processing of object-type arguments
The line that puts an argument value to the log is generated in the ArgumentsListToString method and looks like this:
"_$g(" _ $lg($lg(List,i)) _ ","_$$$quote(..#Null)_")_"
Let's do some refactoring and move it into a separate GetArgumentValue method that will accept a variable name and class (all of which we know from FormalSpecParsed) and output a code that will convert the variable into a line. We'll use existing code for data types, and objects will be converted into JSON with the help of SerializeObject (for calling from the user code) and WriteJSONFromObject (for converting an object into JSON) methods:
ClassMethod GetArgumentValue(Name As %String, ClassName As %Dictionary.CacheClassname) As %String
{
If $ClassMethod(ClassName, "%Extends", "%RegisteredObject") {
// it's an object
Return "_##class(App.Log).SerializeObject("_Name _ ")_"
} Else {
// it's a datatype
Return "_$g(" _ Name _ ","_$$$quote(..#Null)_")_"
}
}
ClassMethod SerializeObject(Object) As %String
{
Return:'$IsObject(Object) Object
Return ..WriteJSONFromObject(Object)
}
ClassMethod WriteJSONFromObject(Object) As %String [ ProcedureBlock = 0 ]
{
Set OldIORedirected = ##class(%Device).ReDirectIO()
Set OldMnemonic = ##class(%Device).GetMnemonicRoutine()
Set OldIO = $io
Try {
Set Str=""
//Redirect IO to the current routine - makes use of the labels defined below
Use $io::("^"_$ZNAME)
//Enable redirection
Do ##class(%Device).ReDirectIO(1)
Do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(Object)
} Catch Ex {
Set Str = ""
}
//Return to original redirection/mnemonic routine settings
If (OldMnemonic '= "") {
Use OldIO::("^"_OldMnemonic)
} Else {
Use OldIO
}
Do ##class(%Device).ReDirectIO(OldIORedirected)
Quit Str
// Labels that allow for IO redirection
// Read Character - we don't care about reading
rchr(c) Quit
// Read a string - we don't care about reading
rstr(sz,to) Quit
// Write a character - call the output label
wchr(s) Do output($char(s)) Quit
// Write a form feed - call the output label
wff() Do output($char(12)) Quit
// Write a newline - call the output label
wnl() Do output($char(13,10)) Quit
// Write a string - call the output label
wstr(s) Do output(s) Quit
// Write a tab - call the output label
wtab(s) Do output($char(9)) Quit
// Output label - this is where you would handle what you actually want to do.
// in our case, we want to write to Str
output(s) Set Str = Str_s Quit
}
A log entry with an object-type argument looks like this:
Restoring the context
The idea of this method is to make all arguments available in the current context (mostly in the terminal, for debugging). To this end, we can use the ProcedureBlock method parameter. When set to 0, all variables declared within such a method will remain available upon quitting the method. Our method will open an object of the App.Log class and deserialize the Arguments property.
ClassMethod LoadContext(Id) As %Status [ ProcedureBlock = 0 ]
{
Return:'..%ExistsId(Id) $$$OK
Set Obj = ..%OpenId(Id)
Set Arguments = Obj.Arguments
Set List = ..GetMethodArgumentsList(Obj.ClassName,Obj.MethodName)
For i=1:1:$Length(Arguments,";")-1 {
Set Argument = $Piece(Arguments,";",i)
Set @$lg($lg(List,i)) = ..DeserializeObject($Piece(Argument,"=",2),$lg($lg(List,i),2))
}
Kill Obj,Arguments,Argument,i,Id,List
}
ClassMethod DeserializeObject(String, ClassName) As %String
{
If $ClassMethod(ClassName, "%Extends", "%RegisteredObject") {
// it's an object
Set st = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(String,,.obj)
Return:$$$ISOK(st) obj
}
Return String
}
This is how it looks in the terminal:
>zw
>do ##class(App.Log).LoadContext(2)
>zw
a=1
b=<OBJECT REFERENCE>[2@%ZEN.proxyObject]
>zw b
b=<OBJECT REFERENCE>[2@%ZEN.proxyObject]
+----------------- general information ---------------
| oref value: 2
| class name: %ZEN.proxyObject
| reference count: 2
+----------------- attribute values ------------------
| %changed = 1
| %data("prop1") = 123
| %data("prop2") = "abc"
| %index = ""
What’s next?
The key potential improvement is to add another argument to the log class with an arbitrary list of variables created inside the method.
Conclusions
Macros can be quite useful for application development.
Questions
Is there a way to obtain line number during compilation?
Links
Part I. Macros
GitHub repository
Cool article Edward! Nevertheless I have a little note here.
According to my experience working on a huge code base, logging with macros may turn to a big pain as soon as you decide to change (add, etc) arguments to your macro, or in other words, change the macro code.
We had an application full of logging macros with something like you mentioned:
#define LogFatal(%message) $$$LogEvent("FATAL", %message)
And at some point the logging mechanism became working improperly and we needed to change it (yuh, this logger used TCP connections and some other stuff to behave like "universal" logger in the application). But simply changing the macros code was not the case: we needed to recompile everything (as macros is compile-time code generator)! Every class on live system which used this macro. This was not successful (even on test environment) for the reasons I don't remember to be honest. What we did instead is... We spent a few days replacing all the macro code to simple class method calls like do ##class(Logger.Log).Warn(whatever). With this approach, when you change the Warn method and recompile, everything is applied immediately.
The pros I see for using macros to class methods is the thing that you can type around 15 less characters for logging, and optionally have some compile-time expressions about the logged class using macros. But the cons here is using macros itself... I believe the similar approach can be done with class methods and with the help of $stack variable.
Any comments on this? Thanks! Nice article Eduard.
Re: last comment. Not sure how having to change the implementation of a Macro is any less of a pain than having to change hundreds of class method arguments. If anything Macro's are a great way to abstract application wide changes with a single line of code. Granted recompilation is required, but code that can't withstand recompilation all day long has a deeper problem.
My only negative about Macro's is when you can't read the code for Macro soup, less is more for me.
One tip to add. I like to have auto complete work for Macros. If you precede each macro with a triple comment, then they will appear in the auto complete suggestions...
///
#define LogNone(%message) $$$LogEvent("NONE", %message)
///
#define LogError(%message) $$$LogEvent("ERROR", %message)
///
#define LogFatal(%message) $$$LogEvent("FATAL", %message)
I think the issue of compilation order specification is more at fault here. Full compile from scratch (on a new instance) or a full recompile should work without errors every time. If it's not, set DependsOn keyword strategically. Or System. 💡 This article is considered as InterSystems Data Platform Best Practice. Hi
I have developed a Debug Logging system that is not quite as expansive as this version. The Debug Log class has the following properties:
Classname
Username
CreatedTS
Key
Message
It is called with one macro
#define DebugLog(%s1,%s2,%s3,%s4)
where %s1 = Username (defaults to $username)
%s2 is the Key which could be a method name or some other meaningful way to locate logs from a certain area in your code
%s3 is the Message which is a string of Human readable text
%s4 is a %Status returned by reference (in case the code has crashed)
I use it in all of my developments
There is a Configuration class as well that basically determines whether logging is turned on or off depending on whether you are working in DEV or PRODUCTION.
The class comes with a number of methods including a Purge method that will purge all logs older than a certain number of days.
If anyone is interested in this please let me know
Nigel
Announcement
Evgeny Shvarov · Jun 9, 2017
Hi, Community!We are introducing Telegram Channel for Developer Community most interesting articles, discussions, events and announcements! If you already use this messenger, join the DC Channel so you can easily follow what's new on Developer Community.See how it looks:Join! The permalink to join Telegram can be found also on the right of every DC page: And... may I ask you introduce your ideas on Developer Community Telegram bot?Please share it below? Thank you in advance! Why do I have to join Telegram to see the data on Atelier?I thought joining the Community was enough? HI, Mike!You don't have to. DC Telegram Channel is introduced for those who loves Telegram mobile app as a way to communicate.It is yet another channel to deliver DC content which is already posted on DC or DC YouTube.But, we plan to introduce DC bot which can be interesting and unique for DC Telegram Channel.
Question
Evgeny Shvarov · Jun 20, 2017
Hi, Community!
How do you store the source files of your Caché project? What is the directories structure? What are the benefits?
I prefer the following structure:
/cls/package/subpackage/class.cls
/mac/package/routine.mac
/int/package/routine.int
/inc/macro.inc
/dfi/folder/sample.pivot.dfi
Example
Benefits:
folders are packages.easy to understand what type of sources are in the project.
What is your approach? Hi, Rubens!Thank you for the wide answer, very interesting.I agree with you on "no subfolders for routines" and separate folder for server-side code. May I wonder what are you using as IDE (Studio? Atelier? Something else?) and how do you import/export your code with Caché. I develop using a mix of Caché Studio with Visual Studio Code.I use Visual Studio Code for dealing with front-end code, while using Caché Studio for back-end.I don't use Caché Studio to edit static files. I'm actually doing experiments using my Port library for managing export/import operations. About how I keep the server code close to it's client counterpart is quite simple. By default Port exports project following the template /CacheProjects/{NAMESPACE}/{PROJECT}, so instead of depending on it, I overwrite that path to /my-repo/server.From this point exported files will follow:/my-repo/server/cls/My/Class.cls/my-repo/server/cls/Another/Deep/Package/Whatever.cls/my-repo/server/int/myroutine.int/my-repo/server/mac/myroutine.mac/my-repo/server/dfi/mydef.dfi/my-repo/server/int/myinclude.incAnd so on, for every recognized Caché file format.Now notice that I didn't said anything about static files. That's where a module bundler like Webpack is used to orchestrate the client-side workflow.Now Caché only needs to send readable data back to the SPA (preferably JSON using %CSP.REST).When the project repo reaches a milestone. I build a release to actually export the files to the path, like this: /my-repo/server/web/app/bundle-[chunkhash].js/my-repo/server/web/app/bundle-[chunkhash].cssSince [chunkhash] is unique per build, the consumer shouldn't have any issues with browser cache.Now there's an issue: the bundled files still aren't inside the CSP folder, so I need to import the project back to Studio using Port.Files are imported using UDL instead of XML. But Port always keep a project XML up-to-date along with the UDL code.As you can see I can work with Caché code AND Client-code, alternating between both editors, thus keeping their own development scope, even though their code remain inside the same repo. cls/My/Deep/Class.clsI don't think subdirectories should be applied for routines, originally routines aren't supposed to have submodules or subpackages and dots might be part of their name. Also if you need some complexity, you wouldn't prefer using routines but classes to keep things organized. I DO NOT recommend using src, unless you want to mix both back-end and front-end code. Or you want to keep the server code in a separated repository.Here is a scaffolding based on React for better understanding.my-app-project / package.json server cls mac int csp <- this is our build path, nothing should be added manually because everything is handle by the bundler. scripts / test.js build.js dev.js config / webpack.config.dev.js webpack.config.prod.js webpack.config.test.js src / components Header index.js Header.js HeaderSearchBar.js Footer index.js Footer.js FooterCopyright.js AppContainer index.js AppContainer.js containers App.js tests components Header Header.js HeaderSearchBar.js Footer Footer.js FooterCopyright.js AppContainer index.js AppContainer You can use folders to separate both client and server codes inside the same project. You can even structure your projectusing a monorepo approach if you want to keep multiple application modules together. Now since React will be using webpack's hot module reloading along with webpack-dev-middleware that builds everything within the memory, your Caché server should only work following SPA conventions and providing consumable data.There's a catch though, whenever the developer builds a new version (using webpack.config.prod), it's mandatory to delete the older bundle and import the project back to Caché to keep the source in sync on the server and the project. I think the most important part of source control file structure is mirroring package structure in Studio, since that is the view we spend the most time with. That said it looks something like this:
root/
Package1/
Class.cls
Class2.cls
Routine.mac
Include.inc
Package2/
Class.cls
Class2.cls
Routine.mac
Include.inc
Additionally:
Web app should be stored in a separate repository.If there's docs/dictionaries/etc, then all sources should be in a /src folder instead of repository root.All libs/modules/etc should be moved into their separate repositories each and plugged in as a submodules.Builds, if any should not be stored in a repo but rather meta-managed (releases).Commit messages and granular commit history is one of the most helpful things when analysing project history, enforce commit message style (title is the most important i.e. PART/SUBPART - thing done in a commit).
Article
Sergey Mikhailenko · Jun 2, 2020
When you first start working with InterSystems IRIS, it’s a common practice to install a system with only a minimum level of security. You have to enter passwords fewer times and this makes it easier to work with development services and web applications when you're first getting acquainted. And, sometimes, minimal security is more convenient for deploying a developed project or solution.
And yet there comes a moment when you need to move your project out of development, into an Internet environment that’s very likely hostile, and it needs to be tested with the maximum security settings (that is, completely locked down) before being deployed to production. And that’s what we’ll discuss in this article.
For more complete coverage of DBMS security issues in InterSystems Caché, Ensemble, and IRIS, you may want to read my other article, [Recommendations on installing the InterSystems Caché DBMS for a production environment.](https://community.intersystems.com/post/recommendations-installing-intersystems-cach%C3%A9-dbms-production-environment)
The security system in InterSystems IRIS is based on the concept of applying different security settings for different categories: users, roles, services, resources, privileges, and applications.

Users can be assigned roles. Users and roles can have privileges on resources — databases, services, and applications — with varying read, write, and use rights. Users and roles can also have SQL privileges on the SQL tables located in databases.
# How Security Levels Differ
When installing InterSystems IRIS, you can choose the security level: Minimal, Normal, or Locked Down. The levels differ in the degree of user engagement, the available roles and services, and in the configuration of authentication methods for services and applications. For more information, read the [Preparing for InterSystems Security](https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GCI_prepare_install#GCI_security) section of the Preparing to Install InterSystems IRIS guide.
In the documentation you’ll find the tables shown below, which show the security settings for each level. You can change the settings in the system management portal interface.
## Initial User Security Settings
|Security Setting | Minimal | Normal | Locked Down |
|--------------------------------------------|--------------|--------------|----------------------|
|Password Pattern |3.32ANP |3.32ANP |8.32ANP |
|Inactive Limit |0 |90 days |90 days |
|Enable _SYSTEM User |Yes |Yes |No |
|Roles assigned to UnknownUser |%All |None |None |
## Initial Service Properties
|Service Property |Minimal|Normal|Locked Down|
|-----------------------------------|-----------|----------|------------------|
|Use Permission is Public |Yes |Yes |No |
|Requires Authentication |No |Yes |Yes |
|Enabled Services |Most |Some |Fewest |
## Initial Enabled Settings for Services
|Service | Minimal | Normal | Locked Down |
|-----------------------------------|--------------|-------------|---------------------|
|%Service_Bindings | Enabled | Enabled | Disabled |
|*%Service_CSP | Enabled | Enabled | Enabled |
|%Service_CacheDirect | Enabled | Disabled | Disabled |
|%Service_CallIn | Enabled | Disabled | Disabled |
|%Service_ComPort | Disabled | Disabled | Disabled |
|%Service_Console | Enabled | Enabled | Enabled |
|%Service_ECP | Disabled | Disabled | Disabled |
|%Service_MSMActivate | Disabled | Disabled | Disabled |
|%Service_Monitor | Disabled | Disabled | Disabled |
|%Service_Shadow | Disabled | Disabled | Disabled |
|%Service_Telnet | Disabled | Disabled | Disabled |
|%Service_Terminal | Enabled | Enabled | Enabled |
|%Service_WebLink | Disabled | Disabled | Disabled |
*For InterSystems IRIS, %Service_CSP applies %Service_WebGateway.
The services used are slightly different for different operating systems.
# How You Can Improve Security
For each enabled service, you need to choose the appropriate authentication methods: unauthenticated, password, Kerberos, or delegated.
You also need to disable web applications that aren’t used in the system. And for web applications that are enabled, you need to select the correct authentication method: authenticated, password, Kerberos, delegated, login, or cookie.
Of course, the administrator chooses the security settings for each project and solution so the project can function according to the customer's requirements. And this is always a balance between keeping the system convenient enough that users can actually get their work done, while also secure enough to keep intruders at bay. As you know, the most secure system is a disabled system.
If you encounter a need to manually increase the security level of your system more than once, this is a sure sign you need to write a software module to solve these problems.
In fact, InterSystems Open Exchange has a lockdown program that can help you improve security. You’ll find the source code for the program in the repository on the InterSystems [isc-apptools-lockdown](https://openexchange.intersystems.com/package/isc-apptools-lockdown) page.
Here’s what the LockDown program does.
## First, it changes passwords for preinstalled users:
- Admin,
- CSPSystem,
- IAM,
- SuperUser,
- UnknownUser,
- _Ensemble,
- _SYSTEM.
## Second, it disables all services except:
- %%service_web gateway
- %service_console
- %service_login
- %service_terminal
## Next, it sets password protection for all web applications, including:
- /csp/ensdemo
- /csp/samples
- /csp/user
- /isc/studio/usertemplates
- /csp/docbook
- /csp/documatic
- /isc/studio/rules
- /isc/studio/templates
## Finally, it sets system-wide security parameters including:
- Password complexity "8.32 ANP"
- Limit on user inactivity of 90 days
- Audit and all security-relevant events
You can install the LockDown program on your system by downloading [LockDown.cls](https://github.com/SergeyMi37/isc-apptools-lockdown/blob/master/src/cls/App/Security/LockDown.cls) from GitHub. Then, in terminal mode, enter the following:
```
USER>zn “%SYS”
%SYS>do $system.OBJ.Load("/home/irisusr/LockDown.cls","ck")
```
Or you can install it using the ZPM batch manager from the public register with the following commands:
```
USER>zn “%SYS”
%SYS> zpm “install isc-apptools-lockdown”
```
# Performing a Lockdown
Before executing a lockdown, it’s strongly recommended that you perform a backup.
The LockDown program must be executed from the %SYS area. If you don't want to change the password for all preinstalled users, leave the first parameter empty.
If you want to keep the ability to edit programs and classes using IRIS Studio, Atelier, or VSCode, don’t disable the %Service_Bindings service. To ensure this works, the bindings argument must be set to 1. Here’s an example:
`do ##class(App.Security.LockDown).Apply("New Password 123",.msg,1)`
This module also contains a function that’s useful if the system password is compromised and you need a replacement for all preinstalled accounts without performing a lockdown. You can run it as follows:
`do ##class(App.Security.LockDown).Change Password("New Password 123", "Admin,CSPSystem,IAM,SuperUser,Unknown User, _Ensemble,_SYSTEM")`
Most likely, after performing the lockdown, your application or project will stop working. To fix it, you’ll need to restore some security settings to their original state. This can be done either via the management portal interface (security section) or programmatically.
# Changing Your Security Settings After Lockdown
After lockdown, if your web applications used authentication methods other than passwords, you’ll need to enable them.
I suggest running the software module [zpm-registry-test-deployment](https://github.com/intersystems-community/zpm-registry-test-deployment/blob/master/Installer.cls), which has an example of using LockDown for the ZPM-registry project.
The code that follows is applied at the end of the installation. The project was installed on IRIS with a minimal level of security. Here’s what the code had to do:
- Change passwords for all preinstalled users.
- Disable all services not used by this project.
- Enable password protection for all applications on the system, except web applications /registry (which allows unauthorized users to get a list of packages in the registry).
- Create a new user with privileges to publish new packages in the registry. This user must have write rights to the project tables in the IRISAPP database.
Create a new user:
```
set tSC= ##class(App.Security.LockDown).CreateUser(pUsername, "%DB_"_Namespace, pPassword, "ZMP registry user",Namespace)
If $$$ISERR(tSC) quit tSC
write !,"Create user "_pUsername
```
Add privileges for a new and unauthorized user:
```
set tSC=##class(App.Security.LockDown).addSQLPrivilege(Namespace, "1,ZPM.Package", "s", "UnknownUser")
set tSC=##class(App.Security.LockDown).addSQLPrivilege(Namespace, "1,ZPM.Package", "s", pUsername)
set tSC=##class(App.Security.LockDown).addSQLPrivilege(Namespace, "1,ZPM.Package_dependencies", "s", pUsername)
set tSC=##class(App.Security.LockDown).addSQLPrivilege(Namespace, "1,ZPM_Analytics.Event", "s", pUsername)
set tSC=##class(App.Security.LockDown).addSQLPrivilege(Namespace, "9,ZPM.Package_Extent", "e", pUsername)
set tSC=##class(App.Security.LockDown).addSQLPrivilege(Namespace, "9,ZPM_Analytics.Event_Extent", "e", pUsername)
If $$$ISERR(tSC) quit tSC
write !,"Add privileges "
```
Run the LockDown program:
```
set tSC= ##class(App.Security.LockDown).Apply(NewPassSys)
If $$$ISERR(tSC) quit tSC
Change the settings for the web app so that an unknown user can log in:
set prop("AutheEnabled")=96
set tSC=##class(Security.Applications).Modify("/registry",.prop)
If $$$ISERR(tSC) quit tSC
write !,"Modify /registry "
Change the settings for the %service_terminal service, changing the authorization method to Operating System, Password:
set name="%service_terminal"
set prop("Enabled")=1
set prop("AutheEnabled")=48 ; Operating System,Password
set tSC=##class(Security.Services).Modify(name,.prop)
If $$$ISERR(tSC) quit tSC
write !,"Modify service terminal"
```
# Wrapping Up
In this article, I discussed why you might want to increase the security level of your system and how you’d do this programmatically, and I showed an example using the InterSystems LockDown program.
We used a method in which we first closed down everything in the system (that is, we set the maximum security level). We then moderated the security by opening the services and applications necessary for the project to function, but only those. I'm sure there are other ways and best practices, and I’d love to hear about them as part of the discussion of this article by the community.
Have you thought about the OS security issues for the instance? For example: if you do a minimal security install on Linux, many more processes run as root than if you do any other install. The only safe way to fix that is via a re-install. I'm always nervous about the idea of converting a minimal install to a more secure one because of those kinds of issues and I don't want people to think their instances are more secure than they really are. Hi Katherine.I agree with you, and the problem of minimizing processes launched from root, my module will not solve
Announcement
Andreas Dieckow · Jan 5, 2018
InterSystems continuously monitors our systems for any evidence of attempts to exploit vulnerabilities such as the newly announced Meltdown and Spectre attack vectors. At this time we have seen no indications of attempts to target InterSystems systems or technology using these vulnerabilities. · InterSystems is aware of recently reported cybersecurity vulnerabilities known as Meltdown and Spectre that affect a wide range of computer processors (See US-CERT Alert TA 18-004A, Meltdown and Spectre Side-Channel Vulnerability Guidance, https://www.us-cert.gov/ncas/alerts/TA18-004A).· As is the case with other technology companies, InterSystems is examining our products to assess and understand the direct impact of the vulnerability and what appropriate actions to take to remediate any discovered risk.· Same as with many other companies, InterSystems’ corporate operations and infrastructure uses systems that are impacted by these vulnerabilities.· InterSystems is working to remediate these operational vulnerabilities as quickly as possible using the applicable patches and firmware updates as they are made available by our vendors.· InterSystems is also monitoring any performance impact caused by patches and firmware update to develop a plan of action to address if necessary.· InterSystems continues to monitor this issue and will provide updates as appropriate.
Announcement
Uwe Hering · May 19, 2018
Hi all,
Anyone who is planning to attend CEBIT 2018 in Hannover should make sure to join us on June 13 from 2pm to 5pm for a technical deep-dive into our new InterSystems IRIS Data Platform™ technology.
We will explore how InterSystems IRIS paves the way for innovation by supporting open analytics, sharding, docker and cloud deployments, to name but a few. Expect an interactive learning experience with insightful presentations and live demos.
To register, simply send an email to marie-laure.kinkel@intersystems.com. The event is free of charge, but has only a limited number of seats available, so make sure to sign up NOW! We will also provide you with a FREE CEBIT ticket upon registration.
What’s more, you will also get the chance to delve into InterSystems IRIS yourself: Sit down in our Sandbox area at stand C49 in hall 13 and take InterSystems IRIS to the test.
See and discuss the agenda below.
Session I – Data-driven Business Models
Session II – InterSystems IRIS Technical Deep-dive
View the original agenda of the event in German here.
We look forward to welcoming you in Hannover!
Sincerely,InterSystems CEBIT Team
Article
Gevorg Arutiunian · Jul 6, 2018

[GraphQL](http://graphql.org/) is a standard for declaring data structures and methods of data access that serves as a middleware layer between the client and the server. If you’ve never heard about GraphQL, here is a couple of useful online resources: [here](https://medium.freecodecamp.org/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf), [here](https://blog.apollographql.com/graphql-vs-rest-5d425123e34b) and [here](https://blog.apollographql.com/the-anatomy-of-a-graphql-query-6dffa9e9e747).
In this article, I will tell you how you can use GraphQL in your projects based on InterSystems technologies.
InterSystems platforms currently support several methods of creating client/server applications:
- REST
- WebSocket
- SOAP
So what’s the advantage of GraphQL? What benefits does it provide compared with REST, for example?
GraphQL has several types of requests:
- **query** - server requests for obtaining data, similar to GET requests recommended for fetching data using REST.
- **mutation** - this type is responsible for server-side data changes, similar to POST (PUT, DELETE) requests in REST.
Both mutation and query can return data – this comes in handy if you want to request updated data from the server immediately after performing a mutation.
- **subscriptions** - the same query type that will output data. The only difference is that a query is launched by a page rendered on the client side while subscriptions are activated by mutations.
## Key features and advantages of GraphQL
### It’s up to the client to decide what data should be returned
One of the key features of GraphQL is that the structure and volume of returned data are defined by the client application. The client application specifies what data it wants to receive using a declarative, graph-like structure that closely resembles the JSON format. The response structure corresponds to that of the query.
Here is how a simple GraphQL query looks:
```json
{
Sample_Company {
Name
}
}
```
A response in the JSON format:
```json
{
"data": {
"Sample_Company": [
{
"Name": "CompuSoft Associates"
},
{
"Name": "SynerTel Associates"
},
{
"Name": "RoboGlomerate Media Inc."
},
{
"Name": "QuantaTron Partners"
}
]
}
}
```
### Single endpoint
When using GraphQL to work with data, we always connect to a single **endpoint**, GQL server, and get different data by changing the structure, fields, and parameters of our queries. REST, in contrast, uses multiple endpoints.
Let’s compare REST with GraphQL using a simple example:

Let’s assume that we need to load a user’s content. If we are using REST, we need to send three queries to the server:
1. Get the user’s data by their id
2. Use their id to load their posts
3. Use their id to get a list of their followers/subscribers
Below is a REST map corresponding to these queries:
```
```
In order to get a new data set, we will need to update this REST map with a new endpoint.
GraphQL handles this with a single query. To do that, just specify the following in the request body:
```
{
operationName: null, //a query can have a name ( query TestName(...){...} )
query: "query {
User(id: "ertg439frjw") {
name
posts {
title
}
followers(last: 3) {
name
}
}
}",
variables: null // initialization of the variables used in the query
}
```
A REST map corresponding to this query:
```
```
Note that this is the only endpoint on the server.
## Installing GraphQL and GraphiQL
In order to start using GraphQL, you need to complete a few steps:
1. Download the [latest release](https://github.com/intersystems-ru/GraphQL/releases) from GitHub and import it to the necessary namespace
2. Go to the system management portal and create a new web application based on your InterSystems Data Platform product (Caché, Ensemble or IRIS):
- Name - **/**
- Namespace - **for example, SAMPLES**
- Handler class - **GraphQL.REST.Main**
3. GraphiQL — a shell for testing GraphQL queries. Download the [latest build](https://github.com/intersystems-ru/GraphQL/releases) or [build](https://github.com/graphql/graphiql) from the source on your own.
4. Create a new web application:
- Name - **/graphiql**
- Namespace - **for example, SAMPLES**
- Physical path to CSP files - **C:\InterSystems\GraphiQL\**
## Let’s take a look at the result
Go to the following link in your browser **http://localhost:57772/graphiql/index.html** (localhost — server, 57772 — port)

I hope everything is clear with the **Query** and **Response** namespaces. A **Schema** is a document that is generated for all stored classes in a namespace.
The schema contains:
- Classes
- Properties, arguments, and their types
- Descriptions of all of the above generated from comments
Let’s take a closer look at a schema for the **Sample_Company** class:

GraphiQL also supports automatic code completion that can be activated by pressing the **Ctrl + Space** key combination:

## Queries
Queries can be simple and complex for several sets of data. Below is a sample query for data from to different classes, **Sample_Person** and **Sample_Company**:

## Filtering
At the moment, only strict equality is supported:

## Pagination
Pagination is supported through 4 functions that can be combined to achieve the necessary result:
- **after: n** – all records with id greater than n
- **before: n** – all records with id smaller than n
- **first: n** – first n records
- **last: n** – last n records

## Visibility areas
In most situations, the business logic of an application dictates that particular clients only have access to particular namespace classes (role-based permissions). Based on that, you may need to limit class visibility for a client:
- All classes in the namespace (**GraphQL.Scope.All**)
- Classes inherited from a superclass (**GraphQL.Scope.Superclass**)
- Classes belonging to a particular package (**GraphQL.Scope.Package**)
In order to change the method of visibility restriction, open the studio, switch to the necessary namespace, and open the **GraphQL.Settings** class. It has a **SCOPECLASS** parameter with the default value of **GraphQL.Scope.All** — this is the class containing the description of the class visibility interface in the namespace:

To change class visibility restrictions, you need to set one of the values provided above: **GraphQL.Scope.Package** or **GraphQL.Scope.Superclass**.
If you picked **GraphQL.Scope.Package**, you will also need to go to that class and change the value of the **Package** parameter to the name of the necessary package – for instance, **Sample**. This will make all the stored classes from this package fully available:

If you picked **GraphQL.Scope.Superclass**, simply inherit from this class once again in the necessary classes::

## Currently supported
Queries:
- Basic
- Embedded objects
- Only many to one relation
- List of simple types
- List of objects
## Currently under development
Queries:
- Embedded objects
- Support of relations of all types
- Filtering
- Support of inequalities
## Plans
- Mutaions
- [Aliases](https://graphql.github.io/learn/queries/#aliases)
- [Directives](https://graphql.github.io/learn/queries/#directives)
- [Fragments ](https://graphql.github.io/learn/queries/#fragments)
→ [Link ](https://github.com/intersystems-community/GraphQL) to the project repository
→ [Link ](http://37.139.6.217:57773/graphiql/index.html) to the demo server
Issues Pull Requests are very welcome.
Keep an eye on our project updates!
Just for the record, GraphQL access to Cache has been supported in EWD.js and EWD 3 (the fore-runners to QEWD.js) since 2015:https://groups.google.com/forum/#!searchin/enterprise-web-developer-community/graphql%7Csort:date/enterprise-web-developer-community/okC6T2W-Sfk/UomKqSrwBQAJhttps://groups.google.com/forum/#!searchin/enterprise-web-developer-community/graphql%7Csort:date/enterprise-web-developer-community/aO1-9mE1FOE/ebdUS8ZbBAAJ And, any stats, Rob? Is it the most popular API in EWD and EWD3? And why it is not supported in QEWD? As I release my code as Open Source, I've no idea of usage stats. There's growing interest in the use of GraphQL in the community I work within these days, for all sorts of reasons.QEWD is a re-badging of EWD 3, so yes, it is supported in QEWD - which of course is straightforward since QEWD is JavaScript/Node.js and can just use the Facebook JavaScript GraphQL module.Just making the point that GraphQL and support for it in Cache isn't something new, as those who follow our work at M/Gateway will know :-)Rob Actually I'm impressed how quickly you guys introduce in QEWD new trendy approaches for development. Though there is a difference here: what @Arutunyan.Gevorg published supports Caché Objects and I doubt if QEWD does. Is there any Caché Objects support/mapping in QEWD? QEWD supports Cache Objects for those who wish to use them via the cache.node APIs for Cache Objects.:https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=BXJS_objectsYour handler logic (which runs in a QEWD Worker process) has access to these APIs via the "this.db" object, eg this.db.invoke_classmethod()The following post is a bit old and refers to how you used these APIs in EWD.js. However, change the invocation to this.db.xxx() and the examples should work in QEWD:https://groups.google.com/forum/#!searchin/enterprise-web-developer-community/invoke_classmethod%7Csort:date/enterprise-web-developer-community/iVR-z_Lxs9I/PPS26Lp5RskJPersonally I prefer to use the Cache database as a persistent JSON database / Document Database, via the ewd-document-store abstraction that is used by QEWD, and integrate that storage into JavaScript Objects. But Cache Objects will work with QEWD and GraphQL just fineRob Hi Rob,I have searched and read through all training materials only for this answer. Probably, it is a good idea to have a separate slide which shows how QEWD can make use of cache object scripts from the handler methods with examples.This may be useful for:1. Applications written in Cache object scripts over the years with business logic that is not easy to change in few years of development.2. Applications using a middle layer and they want to replace it with QEWD to make use of micro-service architecture.3. New development mainly focusing on back-end logic in Cache database with object oriented programming.4. And of course, to make use of QEWD while enjoying the Cache object oriented programming style rather than using it as a document store (I think Cache is not mainly used for document store, but because of its value added features and strengths). Also, to adopt QEWD in Cache based ERP applications, integration of QEWD with Cahce object script is vital.Any training materials, slides or GitHub source with working examples to use QEWD and cache object scripts is highly recommended.Thanks,Jose After import an error occurred as below.---------------------------Studio---------------------------ERROR #6301: SAX XML Parser Error: invalid XML encoding declaration '' while processing Anonymous Stream at line 1 offset 32 > ERROR #5490: Error running generator for method 'DispatchMap:GraphQL.REST.AbstractREST'ERROR: %CSP.REST.cls(DispatchMap) of generated code compiling subclass 'GraphQL.REST.AbstractREST' > ERROR #5030: An error occurred while compiling class 'GraphQL.REST.AbstractREST'---------------------------OK ---------------------------I am using Cache 2017.2.2.Any pointers will be a great help.Thanks, Strange, as that should not be hit for AbstractREST at all.Does you class looks the same as in repo?Just compiled successfully on:
Cache for Windows (x86-64) 2017.2 (Build 744U) Fri Sep 29 2017 10:58:27 EDT
Yes, same version. Just downloaded from repo and imported GraphQL.xml.Version: Cache for Windows (x86-64) 2017.2.2 (Build 865) Mon Jun 25 2018 10:45:31 EDTAlso in Cache for Windows (x86-64) 2017.2 (Build 744) Fri Sep 29 2017 11:10:05 EDTand getting the same error when import and compile GraphQL.xml. You use 8bit Caché. Maybe you need to convert GraphQL.xml into your local encoding.Or use Unicode Caché. Thanks Eduard, now it is working in two different versions.1. Cache for Windows (x86-64) 2017.2.2 (Build 865U_SU) Mon Jul 9 2018 14:31:14 EDT USER>Write $system.Version.IsUnicode() 12. Cache for Windows (x86-64) 2018.1 (Build 179) Tue Sep 4 2018 00:04:51 EDT USER>Write $system.Version.IsUnicode() 0 Really interesting stuff that I would like to introduce but there seem to be no new developments for a long time now. Has this development fizzled out? What features are you most interested in? Unless its not documented, I think he meant features like mutations and subscriptions.Specially mutations, anything else have a workaround. Mutations, mainly.
Is GraphQL support, or will it become, an official part of the product? I have not heard about such plans, maybe when this technology becomes more stable and widely adopted. Extremely uneducated question:
If we have a global with its nice tree structure (like for example that Persons tree built in Globals Introduction by InterSystems Learning Services) without specific schema (e.g. class definition), would graphql be able to be used to make specific condition/wild-card based queries? Current implementation resolves GraphQL query into SQL, so classes/tables are required.
This is our advantage as we don't need to write resolvers manually.
That said, if you want to provide custom schema - you can, as our GraphQL implementation includes GraphQL parser so you can use parsed AST to write your own resolver. This looks very promising. I've got the testing shell up and running returning data from the Sample namespace but how do i "generate a schema for all classes in the namespace" as mentioned in your instructions? My Documentation Explorer just reports "NO SCHEMA AVAILABLE" What does running this code
write ##class(GraphQL.Utils.Schema).GetSchema().%ToJSON()
return for you? It generates tons of JSON looking data. Is there a trick to getting the GraphiQL to get to the schema? Any settings or such? This is the schema.
Do you uses GraphiQL packaged with the repo? yes, I did No worries, I got it working after a fresh reinstall. Probably did something wrong the first time around
Article
Evgeny Shvarov · Apr 22, 2017
Hi!
If you see this page you are in the InterSystems Developer Community!
You are very welcome!
This is the place where you can read about and discuss InterSystems products and technologies: InterSystems IRIS, Caché, Ensemble, HealthShare, DeepSee, and iKnow.
What type of content can I find here?
We have three types of content on Developer Community(DC): articles, questions, announcements. And answers to questions. And videos.
The articles are about the best practices and experience with InterSystems technology and products. Both InterSystems employees and community members post articles. You can find release notes and new features descriptions and the articles regarding experiences and InterSystems technology examples.
And of course, its a place where you can ask your question and get the answer from the most experienced engineers in InterSystems technology from all over the world.
Why register?
Register on DC to post and comment articles, ask questions and give answers regarding InterSystems Data Platforms, solutions built with InterSystems Data Platforms and tools, technologies and approaches which help to build, deploy and maintain solutions on InterSystems Data Platforms. Here are the guidelines on how to post.
Note! Moderators may remove posts that are not related to InterSystems products and technologies.
InterSystems Developers community code of conduct.
Registered members can vote. Vote if you like an article, a question or an answer.
When should I vote down?
Use your downvotes whenever you encounter an egregiously sloppy, no-effort-expended post, or an answer that is clearly and perhaps dangerously incorrect.
If you downvote, please consider adding a comment if you think the post can be improved.
See more about votes.
How does the site work?
Posts are categorized by Tags. There are mandatory tags, which called Groups in editiing. Mandatory tags are related either to InterSystems Products, or InterSystems Services. You need to supply at least one of these tags. Tags are tags, the things which help to categorize posts. You can subscribe for tags to get notifications via email or RSS.
Also, you can follow the member you like - it's a subscription to member's posts and comments.
On the main page, you can see the feed of posts where the topmost is the either latest posted or the latest commented or answered.
You can use feed filters to see only the tags you subscribed, the most voted and new postings as well.
Also, we have DC analytics site to check some figures about DC members, posts, answers, etc.
For all the rest see the Developer Community FAQ.
Subscriptions and notifications
Registered members can receive email notifications regarding different actions on the Developers Community. Please see this article how to deal with that.
Also, everyone can subscribe to RSS: for everything and for specific tags.
InterSystems Global Masters!
It's our InterSystems Advocacy Hub. If think you are an advocate of InterSystems Technology please join the team of hundreds of InterSystems advocates all over the world. We'll provide you challenges, badges, and rewards of course. See the details.
InterSystems Open Exchange!
Find tools, frameworks, solutions, technology examples on InterSystems Open Exchange! Learn more.
What else?
If you have any questions about the site, ask in this group or see the FAQ.
We have Twitter to tweet about all what is valuable in Developer Community and Facebook page if you like it more.
Here is InterSystems Developers LinkedIn information channel and InterSystems Developers LinkedIn Group.
And we have DC Telegram channel for the same purpose if you like Telegram.
And we started the InterSystems Developers YouTube Channel
And also we have Developer Community Subreddit for all the most interesting announcements.
Welcome to InterSystems Developer Community!
This is nice documentation.I am still confused between GROUPS and TAGS, they seem like the same thing.Also, it would have been nice to have this information and much, much more at the beginning.I did ask for documentation when DC was just starting but was told it should be intuitive, but it was never that to me.(at least that was in my memory).Anyway, the documentation is nice, but should be expanded and available through a shortcut, or is that a tag or group?You say if I have any more questions, ask in this Group, how do I know what Group I am in? And how do I ask in a Group?Thank you Hi, Mike!Thanks for the feedback!I am still confused between GROUPS and TAGS, they seem like the same thing.Groups and tags are both tags. But the group is the way for us to be sure, that every post relates to something very significant to what our Company does. It's either InterSystems product, technology or service. Anyway, the documentation is nice, but should be expanded and available through a shortcutThere is a shortcut on the Links widgetand in Community menu - "About the site" You say if I have any more questions, ask in this Group, how do I know what Group I am in? And how do I ask in a Group?Sorry, Mike! I just forgot to put the link to the group. But of course, you can ask here in this post too.And yes, this post would be updated once new features and new better ideas to describe the Community will appear. Hi Evgeny,I couldn't help notice that this post has a -1 rating.I can't see anything wrong with the post so curious what the reason for a down vote would be.On stack overflow they explain the use of down voting as...When should I vote down?Use your downvotes whenever you encounter an egregiously sloppy, no-effort-expended post, or an answer that is clearly and perhaps dangerously incorrect.You have a limited number of votes per day, and answer down-votes cost you a tiny bit of reputation on top of that; use them wisely.This post has an interesting conversation around down votes...https://meta.stackexchange.com/questions/135/encouraging-people-to-explain-downvotesAs the original poster explains...Where the down-vote has been explained I've found it useful & it has improved my answer, or forced me to delete the answer if it was totally wrongThis initiated a change that prompts down voters with the message, "Please consider adding a comment if you think the post can be improved".We all make mistakes so its good to get this type of feedback. It also helps anyone landing on the answer months or years down the line and not realising the answer they are trying to implement has a mistake. Perhaps the DC site could do with something similar?Sean. Sean,I was the one who put the downvote in, and I explained myself in the reply.Maybe you are not the person to ask, but you brought in the comment:"You have a limited number of votes per day, and answer down-votes cost you a tiny bit of reputation on top of that; use them wisely."I don't understand how using down-votes cost someone "a tiny bit of reputation"Seems to me when a down-vote is used, it should enhance ones reputation as you are increasing the quality of a post.Also, if the down-vote is used when:"Use your downvotes whenever you encounter an egregiously sloppy, no-effort-expended post, or an answer that is clearly and perhaps dangerously incorrect."If that is the criteria for downvotes, they will never be used, so why even have them? Hi, Sean!Thanks for the feedback, this is very useful and fair input. So I've introduced the statement about downvotes to the description.We'll add a hint about commenting triggering by downvote. Thanks! In relation to stackoverflow I think the intention was to stop people abusing the implementation of the down vote.I'm not sure that's relevant here, unless the main DC site started displaying some kind of reputation score in the same way as stackoverflow.> Then downvotes will never be used, they why even have them?I think dangerously incorrect is a poor description and perhaps needs down voting :)It should just say "contains incorrect information".Despite that, there are 1,000,000+ users on stackoverflow regularly using the down vote so it must be working. We have a nice welcome video now. Check it out! Recently we got yet another "spam" post. It was hidden.
So this post was updated with the statement:
Note! Moderators may remove posts that are not related to InterSystems products and technologies.
Hi, Community!You can apply your enhancement requests to DC in this repository.And you can monitor the progress in this kanban projects. E.g. here is the June 2018 project. How to solve this error local host:5772 says Internal server error Hi Masilu! Could you please submit a new question with the description of the problem? In DC ANALYTICS / Authors what do these column headers stand for?
Comment Rating
Post Rating
VPP Context
VPP Absolute
For Rating I'd expect Votes ? But VPP ? VPP=Votes per post Thanks!
Question
Kishan Ravindran · May 10, 2017
Is there any simple code in Cache using FHIR to understand the relationship between them? If so can anyone provide some example. Hi KishanI think it would help to have a little bit more information on your particular use case for FHIR. FHIR is the latest standard to be developed under the HL7 organization. Pronounced 'Fire' , FHIR stands for Fast Healthcare Interoperability Resources. FHIR is a standard for exchanging healthcare information electronically. The FHIR standard is just that, a standard, and as is the case for all standards, requires implementation. Complete details about the FHIR standard are publically available on the internet at https://www.hl7.org/fhir/There is no specific functionality built into the InterSystems Cache product to support the FHIR standard, although InterSystems Cache could be used to develop an implementation of the FHIR standard. Such an implementation, done with Cache, would require a significant amount of developmentOn the other hand InterSystems HealthShare does have specific libraries included that can make working with the FHIR standard much easier, but this obviously would depend upon what your exact use-case for FHIR was. If you could provide additional information as to what you are wanting to do with FHIR it would make answering your question much easier.