#新手

0 关注者 · 74 帖子

初学者标签汇集了面向 InterSystems 数据平台初学者的文章和问题

文章 Michael Lei · 六月 20, 2023 5m read

这是在 Ensemble 中实现“微服务”设计的初学者指南。 “微服务”是当今流行的一个词,具有广泛的解释。我的解释是:“微服务”是一种“NoSQL 服务”。一个什么?答案在文章中。

我们了解了 SQL 和 NoSQL 数据库之间的区别。对我来说,SOA Web 服务和“微服务”之间的区别几乎相同。我将通过一个例子来解释它。

请注意,虽然这是一本初学者指南,但我假定我对数据建模、RESTful 服务和 Ensemble 有深入的技术知识。

航班预订——示例

我的例子很简单。我想为我的家人订一张机票。我使用www.skyscanner.hu ,但它可以是任何预订网站。那我该怎么办?在着陆页上,我输入了航班信息:我需要从布达佩斯到布拉格并返回的机票,10 月29日起飞,11 月 1返回,直飞航班,经济舱四人。提交搜索表单后,我会返回可用选项。我选择一个并输入乘客详细信息、折扣计划,最后通过 PayPal 付款。直截了当。

在更详细的版本中:后台发生了什么。

n 开始预订

n 输入选择条件

n 生成匹配航班列表

n 选择航班

n 临时封号

n 输入乘客详细信息

n 根据标价应用一些折扣程序计算机票

n 切换到 PayPal 支付

n 完成预订,释放临时块

当任务是使用 SOAP Web 服务开发后端时,最常见的架构如下:

n 将有支持预订的 SOAP 服务。假设它称为 FlightBookingService。

0
0 162
文章 Hao Ma · 五月 24, 2023 4m read

Manifest也许应该被翻译成“清单”, 字典上是这么解释的: 提供船舶及其货物和其他物品、乘客和船员的全面细节的文件,供海关官员使用,比如:飞机上的乘客或货物清单; 一辆货运列车的车厢清单。

在计算机语言中, Manifest可以是各种格式,用的最多的是xml和json,在IRIS中,manifest是xml格式的, 放在objectscript类的XDATA块里。

编写mainfest

IRIS用manifest来做配置。内部工具*%install*, 会读取manifest, 生成真正的objectscript代码来配置IRIS。我们来看个基本的例子。

基本用法

下面的User.Manifest.cls` ,它配置了IRIS的global buff, bbsize等等, 然后还创建了一个命名空间。

Include %occInclude
Class User.Manifest
{

ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]
{      
   Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "MyInstall")
}

XData MyInstall [ XMLNamespace = INSTALLER ]{
<Manifest>
	<SystemSetting Name="Config.config.gmheap" Value="50000"/>
   <SystemSetting Name="Config.config.locksiz" Value="5000000"/>
   <SystemSetting Name="Config.config.routines" Value="256"/>
   <SystemSetting Name="Config.config.globals8kb" Value="600"/>
   <SystemSetting Name="Config.config.wijdir" Value="/cache/wij"/>
   <SystemSetting Name="Config.Journal.CurrentDirectory" Value="/journal1"/>
   <SystemSetting Name="Config.Journal.AlternateDirectory" Value="/journal2"/>
   <SystemSetting Name="Config.Miscellaneous.EnableLongStrings" Value="1"/>
   <Namespace Name="TUOTANTO" Create="yes" Code="TUOTANTO-R" Data="TUOTANTO-D">
   	<Configuration>
    		<Database Name="TUOTANTO-R" Create="yes" Dir="/cache/database/TUOTANTO-R"/>
    		<Database Name="TUOTANTO-D" Create="yes" Dir="/cache/database/TUOTANTO-D"/>
    	</Configuration> 
    </Namespace>   
</Manifest>
}
}


稍微解释一下代码:

  • Include %occInclude是必须的

  • setup()用来读取manifest的内容,完成配置工作。用户基本不用修改这个method。

  • mainifest本身的逻辑层次很清楚,要配置什么内容查查文档都可以。上面的manifest只是个示意,真正用起来可以需要非常多的配置项,比如namespace, database的配置,有很多的标签可选。

传参数给manifest

调用manifest的method, 也就是例子里的setup(), 注意第一个参数是ByRef pVars。这是objectscript里常用的By referrence的传参方式。请看下面的例子:

Include %occInclude
Class User.Manifest
{

ClassMethod main(){
   Set pVars("Namespace")="MYNAMESPACE"
   Set pVars("AnotherKey")= "AnotherValue"
   $$$ThrowOnError(..CreateNamespace(.pVars))
}

ClassMethod CreateNamespace(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]{      
   Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "CreateNamespace")
}

XData CreateNamespace [ XMLNamespace = INSTALLER ]{
<Manifest>
	<Log Text="This is the content of ${AnotherKey}" Level="0" />
   <Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Data="${Namespace}" Ensemble="1">
		<Configuration>
			<Database Name="${Namespace}" Create="yes" Dir="${MGRDIR}/${Namespace}" Resource="%DB_${Namespace}" PublicPermissions="RW" MountAtStartup="true" />
		</Configuration>	
	</Namespace>
</Manifest>
}
}

上面code在main()里定义了一个pVars, 放了两个key-value, 用来调用CreateName()。 定义的namespace在manifest用到了, Anotherkey被用在了log里, 只是一个示意。

注意这个定义: Dir="${MGRDIR}/${Namespace}"。 其中的MGRDIR不需要自己定义。Manifest有一堆自己定义的Variable, 用的最多的是 CFGDIR, CSPDIR, INSTALLDIR, MGRDIR, PORT等等。具体列表见文档。

更多的用法

下面这个例子包括了import文件和copy文件, SourceDirNamespace是传入的参数。导入文件要在一个namespace的定义里面, 拷贝文件和命名空间无关。

<Manifest>	
   <Namespace Name="${Namespace}">
		<Import File="${SourceDir}/code.xml" Flags="ck" Recurse="1"/>
	</Namespace>
   <CopyDir Src="${SourceDir}/xslfiles" Target="${CSPDIR}/xslt" IgnoreErrors="0"/>
   <CopyFile Src="${SourceDir}/a.html" Target="${CSPDIR}/hcc" IgnoreErrors="0"/>
</Manifest>

CSPApplication

在manifest里定义cspapplication不难,麻烦的是不同的版本使用的标签上会有修改。下面给了一个例子。

<Manifest>
	<Namespace Name="flagger">
      <CSPApplication CSPZENEnabled="1" LoginClass="/csp/flagger/Flagger.LoginAuth.cls" CustomErrorPage="/csperror.csp" ChangePasswordPage="/csp/flagger/ChangePassword.cls" AutoCompile="1" Url="/csp/flagger" IsNamespaceDefault="1" InboundWebServicesEnabled="1" Recurse="1" AuthenticationMethods="64" DefaultTimeout="900" Directory="${CSPDIR}flagger" UseSessionCookie="2" CookiePath="/csp/flagger/" ServeFiles="1" ServeFilesTimeout="3600"/>
   </Namespace>
</Manifest>

调用代码的例子

<Manifest>
	<Role Name="${PMGNAMESPACE}" Description="Works User Role for ${PMGNAMESPACE} Namespace" Resources='"_tInstaller.Evaluate("${PMGDbResource}:RW,PMG:RWU")_"' RolesGranted="" />
	<!-- set locale -->
	<Namespace Name="%SYS" Create="no">
		<Log Text="Changing the Locale" Level="0" />
		<Invoke Class="Config.NLS.Locales" Method="Install" CheckStatus="true">
			<Arg Value="chew" />		
		</Invoke>
    </Namespace>
   <Namespace Name="flagger">
   	<Invoke Class="IRISConfig.Installer" Method="LoadTransactionalData" CheckStatus="true">
			<Arg name="pNamespace" Value="${Namespace}"/>
		</Invoke>
   </Namespace>
</Manifest>

创建User, Role

<Manifest>
	<User Username="ISC" PasswordVar="PASSWORD" Roles="%All" Fullname="ISC" Comment=""/>
   <Role Name="${PMGNAMESPACE}" Description="Works User Role for ${PMGNAMESPACE} Namespace" Resources='"_tInstaller.Evaluate("${PMGDbResource}:RW,PMG:RWU")_"' RolesGranted="" />
</Manifest>

Nampespace Mapping

<Manifest>
    <Namespace Name="FHIRNS">
		<Configuration>
			<Database Name="FHIRNS"/>
            <GlobalMapping Global="%SYS" From="IRISSYS"/> 
            <GlobalMapping Global="OAuth2.*" From="HSSYS"/> 
            <GlobalMapping Global="SchemaMap.*" From="HSLIB"/> 
            <ClassMapping Package="HS" From="HSLIB"/>
            <ClassMapping Package="HS.Local" From="HSCUSTOM"/>
            <ClassMapping Package="HSMOD" From="HSLIB"/>
            <ClassMapping Package="SchemaMap" From="HSLIB"/>
            <RoutineMapping Routines="HS.*" From="HSLIB"/>
            <RoutineMapping Routines="HSMOD.*" Type="INC" From="HSLIB"/>
            <RoutineMapping Routines="HSMOD.*" From="HSLIB"/>
            <RoutineMapping Routines="SchemaMap.*" From="HSLIB"/>
		</Configuration>
	</Namespace>
</Manifest>

其他还有很多的用法。想了解更多,可以看看文档说明里的Tag列表, 和template

怎么执行cls文件

Using the Manifest

在Terminal里执行

%SYS>do ##class(MyPackage.MyInstaller).setup()

或者, 带上参数

%SYS>set vars("SourceDir")="c:\myinstaller"
%SYS>set vars("Updated")="Yes"
%SYS>do ##class(MyPackage.MyInstaller).setup(.vars,3)

During IRIS安装

Export the manifest class as DefaultInstallerClass.xml to the same directory where the InterSystems IRIS install (either .msi, setup_irisdb.exe, or irisinstall) is run. It is imported into %SYS and compiled, and the setup() method is executed.

那么是irisinstall里面的什么语句在执行manifest呢?

# script, 用ISC_INSTALLER_MANIFEST, installer-manifest-example.xml

[root@silent jhvinstall]# cat cache_install.sh
#!/bin/bash
echo -n "Installing Cache..."
ISC_INSTALLER_MANIFEST=$3 ISC_PACKAGE_INSTANCENAME=$1 ISC_PACKAGE_INSTALLDIR=$2 ISC_PACKAGE_UNICODE="Y" ISC_PACKAGE_INITIAL_SECURITY="Minimal" ISC_PACKAGE_MGRUSER="cacheusr" ISC_PACKAGE_MGRGROUP="cacheusr" 
ISC_PACKAGE_USER_PASSWORD="sys" ./cinstall_silent

[root@silent jhvinstall]# ./cache_install.sh CACHE6 "/cache/tmpcache6" "/tmp/installer-manifest-example.xml"
Installing Cache...

写一个脚本执行

这里给一个脚本的例子,简短,但内容很丰富。

#!/bin/bash
# Usage install.sh [instanceName] [password]
instanceName=$1
password=$2
DIR=$(pwd)
ClassImportDir=$DIR/install
NameSpace="ENSDEMO"
CspPath="/csp/ensdemo"
SrcDir=$DIR/src/CLS
DirFront=$DIR/src/CSP/csp/demo

irissession $instanceName -U USER <<EOF 
SuperUser
$password
do \$system.OBJ.ImportDir("$ClassImportDir","*.cls","cubk",.errors,1)
write "installer导入成功"
Set pVars("DirBin")="$DIR/ENSDEMO"
Set pVars("DirFront")="$DirFront"
Set pVars("NAMESPACE")="$NameSpace"
Do ##class(App.Installer).setup(.pVars)
zn "%SYS"
set props("DeepSeeEnabled")=1
set sc=##class(Security.Applications).Modify("$CspPath", .props)
zn "$NameSpace"
do \$system.OBJ.ImportDir("$SrcDir","*.cls","cubk",.errors,1)
halt
EOF
1
0 197
文章 Hao Ma · 五月 4, 2023 6m read

当系统发生严重危机,一般错误,以及其他需要管理员关注的其他事件发生时, 管理员必须及时的收到系统发出的警告信息。

上篇文章中介绍了控制台日志。这是个文本文件,包含几乎所有的系统级别的错误信息,并且有严重级别的标识,那么使用工具来监控控制台日志文件,并给管理员发送通知是可行的方案吗?

当然。实际上,有些用户正是这样来管理Caceh'/IRIS的。他们有自己熟悉的监控工具,实时读取控制台日志,分析内容,并完成警告通知的发送。

这篇文章我来介绍的是Cache'/IRIS内置的处理警告的机制和配置方法。 通过把严重的错误和事件写入另一个文本文件alert.log,并配置邮件,SNMP, API接口发送通知,可以基本的实现caceh'/IRIS系统的警告通知工作。

Alerts.log

控制台日志中最严重的两个级别(级别2和3), 的记录会被写入另一个文本文件,名字是Alert.log。 默认存储于\installDir\mgr\路径。

在操作门户中“系统>系统日志>控制台日志” ,你会发现 Alerts.log的内容会以红色的字体显示在最上方。比如下图中有2个严重级别的Alert。

另外, 告警的条目数量会显示在系统仪表板的“错误和告警”模块中的‘严重告警’(Serious Alerts)栏。

注意,这里的数值只显示30分钟内非启动过程中的Alert条目数。比如上面例子中产生了一条“Failed to allocate…”的告警,因为是启动过程中的记录,因此仪表板中的严重告警数值为1。而如果30分钟内不再发生 “Winter is coming”的告警,此数值会减为0.

关于alerts.log, 您还需要知道:

  • 每次系统重启该文件也会清除重置。
  • 对alerts.log的内容,用户可以使用系统工具^MONMGR配置发送告警邮件
  • 除了来自控制台日志,Alerts.log的记录还可以是来自其他来源

是的。底层的系统内核以及开发工具可以直接写告警信息到Alert.log, 而不通过控制台日志,应用监视器%Monitor.Adaptor就是这么一个开发工具,有些开发者使用它来向alert.log直接写入记录。

细心的读者可能注意到上面图中有个告警内容是*“Winter is coming”*,它是为了测试用以下命令产生的。

do ##class(%SYS.System).WriteToConsoleLog("winter is coming",,2)

这也是为什么要单独保留一个Alert日志文件,在设计者的想法里, alert.log不是只从控制台日志拿记录,它还可以有多个可能的来源。

可以把控制台日志中的“警示性错误(Warning)”写入Alert.log吗?

可以,但管理员必须清楚的知道这样会收到很多不严重的警示信息。通常这样做的理由是用户有自己的监控手段监控Alert.log这个文件,那么先把Warning写入Alert.log,随后用自己的方式去过滤,这是个合理的解决方案。

读取控制台日志到Alert.log的工具在早期版本中被称为Caché Monitor,这是个非常恼人的名字,好在新版本里改称为“Log Monitor”。默认的配置中,Log Monitor每10秒扫描一下控制台日志,将级别2,3的记录写入Alert.log。配置和修改log monitor使用终端工具^MONMGR,它可以修改写入错误的级别选择和采样的间隔(Monitor Interval)。

%SYS>do ^MONMGR

1) Start/Stop/Update MONITOR
2) Manage MONITOR Options
3) Exit

Option? 2 

1) Set Monitor Interval
2) Set Alert Level
3) Manage Email Options
4) Exit

Option? 2
Alert on Severity (1=warning,2=severe,3=fatal)? 2 => 

1) Set Monitor Interval
2) Set Alert Level
3) Manage Email Options
4) Exit

Option? 4

Alert.log内容的发送

系统内嵌的发送通知的方式有以下几种:

发送告警邮件

这是系统默认的Alert的通知方式。使用^MONMGR配置配置您的邮件地址和服务器。

SYS>do ^MONMGR

1) Start/Stop/Update MONITOR
2) Manage MONITOR Options
3) Exit

Option? 2

1) Set Monitor Interval
2) Set Alert Level
3) Manage Email Options
4) Exit

Option? 3

1) Enable/Disable Email
2) Set Sender
3) Set Server
4) Manage Recipients
5) Set Authentication
6) Test Email
7) Exit

Option?

SNMP Trap

通过SNMP Trap发送通知/警告也是非常常用的方案。无论是Cache'还是IRIS, 您都可以在SNMP客户端使用SNMP收集采样指标,接收alert消息。具体的操作内容,我会在单独的文章介绍。这里只是简单的描述下步骤:

  • 确认操作系统的SNMP服务已启动
  • 在Cache'/IRIS管理门户“System>Security Management >Services”启动%Service_Monitor服务.
  • 到“Monitor Setting"页面确认“the monitor service is Enabled"
  • 重启实例。

以下是使用snmptrapd命令接收的alert的例子:

Received 113 byte packet from UDP: [172.16.58.200]:60620->[0.0.0.0]:0
0000: 30 6F 02 01  00 04 06 70  75 62 6C 69  63 A4 62 06    0o.....public�b.
0016: 0A 2B 06 01  04 01 81 81  33 01 02 40  04 AC 10 3A    .+......3..@.�.:
0032: C8 02 01 06  02 01 0F 43  02 5D 33 30  44 30 1A 06    �......C.]30D0..
0048: 12 2B 06 01  04 01 81 81  33 01 01 01  01 01 04 48    .+......3......H
0064: 53 41 50 04  04 48 53 41  50 30 26 06  12 2B 06 01    SAP..HSAP0&..+..
0080: 04 01 81 81  33 01 01 01  01 08 04 48  53 41 50 04    ....3......HSAP.
0096: 10 77 69 6E  74 65 72 20  69 73 20 63  6F 6D 69 6E    .winter is comin
0112: 67

注意: snmp trap的发送发生在alerts.log的写入时。重复消息写入Alert的时限是30分钟。切换执行的进程,比如重新打开另一个terminal进程会重新计数。

REST API

通过REST接口查看alert内容是IRIS的新特性。下面的查看结果中有4个alert记录。原始输出的json是给机器读的,堆在一起很难看,我做了格式化,更方便人读。

注意的一点: 通过REST读取alert的内容每次只能读到新的alerts。也就是说,当再次GET的时候, 如果和上次查看的间隔中没有新alert记录出现,GET的结果是空,虽然这时候alert.log的文件里还是有很多记录。

hma@CNMBPHMA ~ % curl http://localhost:52773/api/monitor/alerts
[
    {
        "time": "2023-05-04T02:12:05.647Z",
        "severity": "2",
        "message": "Preserving journal files /usr/irissys/mgr/journal/20230421.002 and later for journal recovery and transaction rollback"
    },
    {
        "time": "2023-05-04T02:13:35.671Z",
        "severity": "2",
        "message": "[SYSTEM MONITOR] DiskPercentFull(/external/demo/) Alert: DiskPercentFull = 91.34, 91.34, 91.34 (Max value is 90)."
    },
    {
        "time": "2023-05-04T02:13:35.671Z",
        "severity": "2",
        "message": "[SYSTEM MONITOR] DiskPercentFull(/external/oeesp/) Alert: DiskPercentFull = 91.34, 91.34, 91.34 (Max value is 90)."
    },
    {
        "time": "2023-05-04T02:13:35.672Z",
        "severity": "2",
        "message": "[SYSTEM MONITOR] DiskPercentFull(/external/smart/) Alert: DiskPercentFull = 91.34, 91.34, 91.34 (Max value is 90)."
    }
]

Monitoring Web Service

Caché Monitoring Web Service是一个提供系统采样值的Web服务,简单的说,您在用户界面上看到的所有指标,都可以从这个Web服务得到。

它的其中一个服务是EventSubscribe,用户调用这个服务,订阅Caché Event, 提供用户自己的Web服务调用地址,服务规范拷贝Monitoring Web Service中的EventSink服务,这是服务就是专门提供给客户的一个WSDL模板。当Caché产生Warning或者Alert时,Caché会调用用户的Web服务发送通知。这是一个不太常用的方案,感兴趣的用户可以查看产品手册中“Monitoing Caché Using Web Services”部分。

0
0 477
文章 Michael Lei · 四月 3, 2023 2m read

如果您使用过 Caché Objects,你已经知道所有关于关系(一对多,父子孙继承等)......
但是您不会在文档中找到关于多对多关系的地方。

但我经常遇到 Caché 对象的新用户提出的问题:
“是否可以实现多对多关系?”答案是——当然!

如何实现取决于相关的任务:有一个比较重的和一个轻量级的解决方案。
两者的共同点是它们不能开箱即用需要添加一些代码来管理它。

让我们举一个基于 SAMPLES 命名空间的例子:

我们有 N:1 关系的情况

但是,您如何处理超过 1 个公司的员工?

重的解决方案:
您添加一个额外的持久类,与双方都有一个:多的关系。

优点:您可以添加管理信息作为有效性、各种时间戳……
以及与此“链接”相关的其他内容。
但它是一个额外的持久类,具有所有优点和缺点。所以我觉得这个很重。
该类可能如下所示:

0
0 172
文章 Kelly Huang · 三月 28, 2023 1m read

嗨大家好!

最近我需要使用 IRIS For Health 设置本地 FHIR 服务器,我认为我找到了有史以来最简单的方法!

只需在终端中运行以下两行:

docker run --rm --name my-iris -d --publish 9091:1972 --publish 9092:52773 intersystemsdc/irishealth-community

docker exec -it my-iris iris session iris -U "USER" '##class(%ZPM.PackageManager).Shell("install fhir-server")'

您将在 http://localhost:9092/fhir/r4 本地运行 FHIR 服务器。

就是这么简单!

FHIR 服务器将使用最新版本的 InterSystems IRIS for Health Community Edition,并将通过 FHIRSERVER 命名空间中的 IPM 包从该应用程序部署 FHIR 服务器

这是针对 Mac OS的,所以请在评论中添加它在 Windows 中的工作方式。

这是一篇非常短的文章,因为使用 InterSystems IRIS for Health 和IPM Package Manager 设置本地 FHIR 服务器真的很容易。

0
0 255
文章 Michael Lei · 三月 2, 2023 4m read

正式名称为Class Query 的意思可以追溯到 Caché 的早期。
使用CLASS是因为它嵌入在 COS 类中。
尽管官方文档中有精确的描述,但它仍然相当抽象。
我的教程应该通过 COS 中的一个简单示例逐步指导您,使您有直观的体会

0
0 127
文章 Lilian Huang · 二月 28, 2023 3m read

嗨,InterSystems 开发人员!

最近我更新了FHIR 开发模板,它发布了一个 IPM 包fhir-server ,使 InterSystems FHIR 服务器的设置成为一个微不足道的手动或自动或编程的程序,只需一条命令。

请参阅下文,了解如何从中受益。

TLDR

USER>zpm "install fhir-server"

以下所有详细信息。

0
0 149
文章 Hao Ma · 十一月 20, 2022 7m read

发布您自己的软件

首先:要发布您的软件,您要支持这个”命名规范。其中和zmp最相关的是包名和l类名的设计,你要定义成这样:

company.project.subpackage.TheClass.cls

如果您的Package Name定义是: Company.Project, 有大写字母,对不起,是无法用zpm打包的。

这个链接给了最简单的例子,但还不详细,我来总结一下:

发布您的软件前,有几件事情要了解:

  1. zpm的注册中心并不存代码,存的只是一个到您代码的链接。因此,您得找地方放您的代码。当前最常用的是github。

  2. 文件目录的结构

    举例:有一个class定义是 com.tony.Test1.cls, 你的目录应该这么组织,假设您要放在 /myDemo, 那么class应该在/myDemo/src/com/tony/Test1.cls。这是使用VSCode组织代码的默认方式,只有保证这样的目录结构,您才可能用zpm加载代码到iris.

让我来做个简单的例子。

首先,有这样的class:

Class com.tony.Test1
{	Property p1;
}

我的文件目录设置

$ ls -l /external/myDemo/src
total 4
-rw-r--r-- 1 irisowner irisowner 40 Nov 12 10:00 Test1.cls
$

这时候我来使用zpm打包测试

module.xml的生成和加载

第一步,生成module.xml

我们看看最简单的用zpm generate命令生成module的例子:

zpm:USER>generate /external/myDemo/project1

Enter module name: project1
Enter module version: 1.0.0 =>
Enter module description:
Enter module keywords:
Enter module source folder: src =>

Existing Web Applications:
    /csp/user
    /terminal
    /terminalsocket
    Enter a comma separated list of web applications or * for all:
Dependencies:
    Enter module:version or empty string to continue:
zpm:USER>

zpm generate会把/external/myDemo/project1目录下的文件打包,在这个目录下创建一个module.xml文件, 是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
  <Document name="project1.ZPM">
    <Module>
      <Name>project1</Name>
      <Version>1.0.0</Version>
      <Packaging>module</Packaging>
      <Resource Name="com.PKG" />
      <SourcesRoot>src</SourcesRoot>
    </Module>
  </Document>
</Export>

先等等解释这个xml, 让我们先执行第2步。

第2步: 把文件load到iris

zpm:USER>load /external/myDemo/
[USER|firstdemo]	Reload START (/external/myDemo/)
[USER|firstdemo]	Reload SUCCESS
[firstdemo]	Module object refreshed.
[USER|firstdemo]	Validate START
[USER|firstdemo]	Validate SUCCESS
[USER|firstdemo]	Compile START
[USER|firstdemo]	Compile SUCCESS
[USER|firstdemo]	Activate START
[USER|firstdemo]	Configure START
[USER|firstdemo]	Configure SUCCESS
[USER|firstdemo]	Activate SUCCESS
zpm:USER>

您去iris里看看, 确认class已经被loaded

第3步: 删除(optional, 但你可能会用到这个命令)

zpm:USER>uninstall firstdemo

[USER|firstdemo]	Clean START
[USER|firstdemo]	Unconfigure START
[USER|firstdemo]	Unconfigure SUCCESS
Deleting class com.tony.Test1
[USER|firstdemo]	Clean SUCCESS
zpm:USER>

这时候您应该可以发现com.tong.Test1类已经从Iris删除了。

对上面的例子总结一下:

  1. 打包是对一个文件夹打包

  2. 使用zpm把软件包加载进iris是先找包里面的module.xml文件。通过module.xml里定义的信息来知道包的名字,版本,打包的内容等等。 这个module.xml是在打包的时候用zpm generate创建的, 但您也可以自己手工创建,比如copy其他包的module.xml改改, 有时候会更快捷,尤其是您对zpm命令不是很熟悉的时候, 对很多打包的需求,比如后面会提到的定义依赖等等,直接改module.xml比zpm generate容易多了。

  3. 让我来说说可能的问题:

    module.xml中<Resource Name="com.PKG"/>定义了包名com.PKG, 加载数据包到iris很成功。但是,如果您还记得,刚刚例子里打包的是class是com.tony.Test1,那么如果你再定义一个新的类,叫com.tiedan.Test1, 用zpm generate一个新module, 名字叫project2(注意第一个打包的module名字是project1), project2的"Resource Name"也还是"com.PKG, 它能正确加载吗?

    不会, 你会被告知:"ERROR! Resource 'com.PKG' is already defined as part of module 'project1'; cannot also be listed in module 'project2'"

​ 解决方法:手工将module.xml里面的Resource Name改成“com.tony.PKG"和"com.tiedan.PKG", 这样两个包都能成功加载了。

还有个小问题,Mac用户可能会看到这样的提示:

zpm:USER>load /external/myDemo/project1

[USER|project1] Reload START (/external/myDemo/project1/) [project1] Reload FAILURE ERROR! Unable to import file '/external/myDemo/project1/src/com/.DS_Store' as this is not a supported type. zpm:USER>

这是说打包的文件夹下面有.DS_Store文件,而zpm不认识。zpm会把里面认识的文件, 比如.cls文件成功加载, 然后告诉你"Roload FAILURE"

好吧, 到这里我们知道怎么打包和把包加载到iris里, 接着看看什么文件可以被打包。

Package可以包含的文件类型

这时候要好好了解module.xml的内容的细节了, 请阅读技术文档的module.xml部分

其中的resource部分,阐明了您可以打包的内容:

第一部分:可以被加载到iris的文件类型。

Use the following suffixes for different types of resources:

.PKG - Package .CLS - Class .INC - Include .MAC - Routine .LOC - LocalizedErrorMessages .GBL - Global .DFI - DeepSee Item

第二部分:jar包

<FileCopy Name="lib/" Target="${libdir}my-lib/"/>               Copies content of lib folder to Target
<FileCopy Name="somefile.jar" Target="${libdir}my-lib/"/>       Copies just desired file to Target

第三部分:UnitTest

module.xml的例子里给出的UnitTest部分是这个样子

<UnitTest Name="/tests/unit_tests/" Package="Test.Unit" Phase="test"/>

说实话,我还没研究怎么使用zpm generate可以做到这一点,能想到的就是手工去修改module.xml文件。

第四部分:Web Application

执行zpm generate的时候, 会列出当前命名空间可以使用的Web Application列表。让我重新执行一下打包的第一步,看看结果是什么样子

zpm:USER>generate /external/myDemo/project1

Enter module name: project11
Enter module version: 1.0.0 =>
Enter module description:
Enter module keywords:
Enter module source folder: src =>

Existing Web Applications:
    /csp/user
    /terminal
    /terminalsocket
    Enter a comma separated list of web applications or * for all: /csp/user
    Enter path to csp files for /csp/user: 
Dependencies:
    Enter module:version or empty string to continue:
zpm:USER>

得出的module.xml里多了如下内容:

<CSPApplication CookiePath="/csp/user/" DefaultTimeout="900" DeployPath="${cspdir}user/" Description="User Namespace applications" GroupById="%ISCMgtPortal" MatchRoles=":{$dbrole}" PasswordAuthEnabled="1" Recurse="1" ServeFiles="2" ServeFilesTimeout="3600" UnauthenticatedEnabled="1" Url="/csp/user" UseSessionCookie="2"/>
      <SourcesRoot>src</SourcesRoot>

其中,打包时提问`Enter path to csp files for /csp/user:。 这里,您需要填入的是当前要load的csp文件。比如:您有一个tony.csp要加载,那么您可以在要打包的目录下创建一个子目录“cspfiles", 把tony.csp放在cspfiles目录里, 回答提问的使用这样

Enter path to csp files for /csp/user:/cspfiles

这里用的是相对路径,但格式是绝对路径的格式,我把它看成一个bug。

module.xml中还有其他很多配置的内容,我在后面会介绍包的依赖的部分。

软件包的Package

用package命令,在iris里将软件打包。打包的结果是得倒一个project1-1.0.0.tgz的文件。 package -v显示verbose信息,您可以清楚的看到project1-1.0.0.tgz和module.xml的存放位置。

zpm:USER>project1 package -v

[USER|project1]	Reload START (/external/myDemo/project1/)
Skipping preload - directory does not exist.
Load of directory started on 11/20/2022 13:15:17 '*'

Loading file /external/myDemo/project1/src/com/tony/Test1.cls as udl
Load finished successfully.

[USER|project1]	Reload SUCCESS
[project1]	Module object refreshed.
[USER|project1]	Validate START
[USER|project1]	Validate SUCCESS
[USER|project1]	Compile START
Compilation started on 11/20/2022 13:15:17 with qualifiers 'd-lck'
Compiling class com.tony.Test1
Compiling routine com.tony.Test1.1
Compilation finished successfully in 0.008s.

[USER|project1]	Compile SUCCESS
[USER|project1]	Activate START
[USER|project1]	Configure START
[USER|project1]	Configure SUCCESS
Studio project created/updated: project1.PRJ
[USER|project1]	Activate SUCCESS
[USER|project1]	Package START
Exporting 'com.tony.Test1.cls' to '/usr/irissys/mgr/Temp/dirKBwoaM/project1-1.0.0/src/com/tony/Test1.cls'
Exported to /usr/irissys/mgr/Temp/dirKBwoaM/project1-1.0.0/module.xml
Module exported to:
	/usr/irissys/mgr/Temp/dirKBwoaM/project1-1.0.0/

Module package generated:
	/usr/irissys/mgr/Temp/dirKBwoaM/project1-1.0.0.tgz
[USER|project1]	Package SUCCESS
zpm:USER>

软件包的Publish

我们并没有权限把软件包直接发布到官方的registry去。您需要去InterSystems的OpenExchange页面,提交您的软件包。如下图填入软件包的信息,Github URL, 注意勾选右下角的"Publish in Package Manager" 。

image

后面, 我会介绍怎么创建自己team的私服, 用zpm publish可以简单的把iris的软件包发布到私服上去,这对一个开发团队共享软件包并方便部署应该是更有吸引力些。

2
0 281
文章 Hao Ma · 十一月 26, 2022 4m read

建立私服(Porxy-Registry)

这张图解释了您的私服是怎么工作的, 整篇文章在这里: Proxy-Registry

搭建私服

您需要有一台自己的的服务器, 在上面安装IRIS, zpm, 然后用zpm去下载另一个软件包“zpm-registry"。象这样

zpm:DEMO>search -r zpm-registry
registry https://pm.community.intersystems.com:
zpm-registry 1.1.11Repository: https://github.com/intersystems-community/zpm-registry/

zpm:DEMO>install zpm-registry
[DEMO|zpm-registry]	Reload START (/usr/irissys/mgr/.modules/DEMO/zpm-registry/1.1.11/)
[DEMO|zpm-registry]	Reload SUCCESS
[zpm-registry]	Module object refreshed.
[DEMO|zpm-registry]	Validate START
[DEMO|zpm-registry]	Validate SUCCESS
[DEMO|zpm-registry]	Compile START
[DEMO|zpm-registry]	Compile SUCCESS
[DEMO|zpm-registry]	Activate START
[DEMO|zpm-registry]	Configure START
[DEMO|zpm-registry]	Configure SUCCESS
[DEMO|zpm-registry]	Activate SUCCESS
zpm:DEMO>

到github页面, https://github.com/intersystems-community/zpm-registry/, 你可以得到更详细的软件信息。

配置私服连接公服, 需要在私服的IRIS的安装目录添加一个yaml文件, 定义uplink:

uplinks:
  pm:
    url: https://pm.community.intersystems.com/
    allow_packages: dsw,zpm*,?u*

几点说明:

  • uplinks的项目可以有多个,pm是intersystems的默认公共registry

  • allow_packages: - a comma-separated list of allowed packages, you can use the exact package name or mask: * - any sequence of characters, ? - any charac

  • registry 提供的rest 接口描述: https://pm.community.intersystems.com/_spec

设置zpm client连接私服

通过repo命令将您的zpm client切换到刚刚配置的私服。repo -n registry里面的 - user, - pass是你搭建的私服的账号密码。您也可以在私服上修改/registryWeb应用不做用户验证。

zpm:DEMO>repo -list
registry
	Source: 		https://pm.community.intersystems.com
	Enabled?		Yes
	Available?		Yes
	Use for Snapshots?	Yes
	Use for Prereleases?	Yes
	Is Read-Only?		No
	Deployment Enabled? 	No

zpm:DEMO>repo -n registry -r -url http://localhost:52773/registry/ -user superuser -pass demo

registry
	Source: 		http://localhost:52773/registry/
	Enabled?		Yes
	Available?		Yes
	Use for Snapshots?	Yes
	Use for Prereleases?	Yes
	Is Read-Only?		No
	Deployment Enabled? 	No
	Username: 		superuser
	Password: 		<set>
zpm:DEMO>

这时的私服时没有连接公服。

发布软件包到私服

发布一个 GitHub 的包

先把软件存在github, 然后用curl命令把包发布在私服的地址。

$ curl -i -X POST -H "Content-Type:application/json" -u superuser:1104 -d '{"repository":"https://github.com/psteiwer/ObjectScript-Math"}' 'http://localhost:52773/registry/package’

使用zpm 客户端先在本地load,然后使用publish 命令

大概像这个样子:

zpm:USER>help load
...
  ■ Examples
    ∙ load C:\module\root\path\
load C:\module\root\path\module-0.0.1.tgz
      Loads the module described in C:\module\root\path\module.xml
    ∙ load -dev -verbose C:\module\root\path\
load -dev -verbose C:\module\root\path\module-0.0.1.tgz
      Loads the module described in C:\module\root\path\module.xml in developer mode and with verbose output.
    ∙ load https://github.com/user/repository.git
load https://github.com/user/repository.git -b branch-name
      Loads the module described in C:\module\root\path\module.xml in developer mode and with verbose output.
zpm:USER> load https://github.com/user/repository.git
zpm: USER> publish <package name>

其他的Feature

在使用中您还会有各种各样的需求, 但我相信看到现在您应该对怎么寻找答案非常清楚了。这里简单的说两个feautre

1. 发布为Delopyed模式

如果您要隐藏自己的代码,只发布编译后的软件, 可以简单的修改Module.xml, 设置“<Resource Name="Sample.Demo.PKG" Deploy="true"/>“, zpm会自动完成。

2. 包的依赖

因为有朋友问,所以说一些包依赖的功能。是的, zpm是设计了包依赖的功能的,在module.xml里添加Dependencies节点, 可以定被依赖的包的列表。 具体的写法请参见这个例子:module.xml example

虽然但是,对ObjectScript程序来说,定义包依赖的机会并不多。我能想到的应用场景就是, 当您的软件中想用社区其他包,比如上面的bitmap-adoption的包的话,您可以包"bitmap-adoption"打包到module.xml里面。

我对当前发布的200多软件包随便挑了一些,还没有发现有哪个使用了包依赖, 象这样:

zpm:USER>list-dependents yaml-utils
zpm:USER>list-dependents terminal-multiline-editor
zpm:USER>list-dependents bitmap-adoption
zpm:USER>list-dependents global-dump-sql
...
0
0 234
文章 Chang Liu · 九月 22, 2022 2m read

1,准备

    本次安装环境:Kylin-Server-10-SP2-Release-Build09-20210524-x86_64.iso

    安装系统适配的对应版本:HealthConnect-2021.1.2.338.0-lnxubuntux64.tar.gz;ISCAgent-2021.1.2.338.0-lnxubuntux64.tar.gz

     系统语言选择:English(必要)

2,安装HealthConnect+webgateway

  2.1  新建所需用户组

  groupadd iscagent

 2.2  解压文件

2.3 安装

  本次安装,使用root用户及root用户组安装,超级端口改为51773

3,安装ISCAgent

  3.1安装说明

  ISCAgent是healthconnect的镜像服务,若是单机使用,则不需要安装。

  3.2  解压文件

    

 3.3  安装

 

3.3  加入服务

3.3.1   新建文件

  /etc/systemd/system 下创建文件,ISCAgent.service,内容如下:

 [Unit]

Description=InterSystems Agent

After=syslog.target network-online.target

[Service]

8
0 421
文章 Claire Zheng · 十月 18, 2022 4m read

各位开发者社区的同学们,大家好!

您想更好地获得帮助、讨论有趣的功能、发布公告或分享您的知识吗?在这篇文章中,我们将告诉你如何做到这一切。

我们将通过以下几部分来分享“如何做”:

一般发帖步骤

首先,你需要点击开发者社区网站顶部菜单中的“发布新帖”按钮:

之后,您将看到编辑器中显示创建一个问题、一则公告、一篇文章或一个讨论。不同类型的帖子有自己的一组必填字段和可选字段。

0
0 153
文章 王喆 👀 · 九月 24, 2022 2m read

在医院但凡接触“数据”和“指标”的人,对以下场景应该是深有感触。同样的指标、同样的时间,有可能是同一个部门出的,最后“数据不一致”。除了“匪夷所思”,更有“深恶痛绝”。那么,如何解决这个问题?我的答案是商业智能(BI)。随着技术和市场的发展,有很多公司开始研发直接面向业务用户的敏捷BI工具,FineBI就是这样的一款BI工具。这个也是我接触的第一款国产BI。

项目的前提条件和设置

  1. 操作系统:Windows 64
  2. IRIS产品:HealthConnect 2020
  3. BI工具:FineBI
  4. JDK: JDK1.8

FineBI、JDK、HealthConnect、FineBI的相关安装步骤网上有很多,在此就暂时略过。要在FineBI上创建仪表板,我们需要一点数据,在此我使用的是开发过程中的一些测试数据,相关测试数据和互联互通的69个交互服务息息相关,有需要可以自己模拟的造。

将FineBI和IRIS连接

       我们首先找到HealthConnect的安装文件,我们需要找到intersystems-jdbc-3.2.0.jar这样一个文件。大概在【安装目录】\InterSystems\HealthConnect\dev\java\lib\JDK18,如图所示:

       将文件复制到FineBI的安装目录\webapps\webroot\WEB-INF\lib,如图所示:

0
0 331
文章 Michael Lei · 九月 15, 2022 4m read

关于微服务架构(MSA)的IRIS定位的初学者指南。MSA在企业级Java世界中的能见度越来越高,因此,了解这股热潮背后的内容是至关重要的。我尝试着写下我的观点并与大家分享。

背景

首先,我必须承认。今年初夏,我的同事要求我收集一些关于匈牙利开发的医疗产品的信息。当我从相关公司得到反馈时,发现该产品是一个模块化系统,基于微服务架构(MSA)。好的。什么是MSA?在网上做了简短的研究,阅读了一些WIKI网页后,我得出结论:啊哈,又是一个 "架构"。我们可以用IRIS在 "架构层面 "遵守 "任何架构"--至少 "在某种程度上"。但也有一些恼人的地方。这让我对MSA有了更多的了解。到目前为止还不错,但是REST不是这篇文章的主要话题吗?MSA和REST之间的关系是什么?我访问的几乎每个网站都在例子中使用了RESTful网络服务。这让我有点怀疑。但总的来说,我赞同对MSA的一般总结:它是SOAP但做得很好。特别是因为有一些关于 "内聚 "和 "耦合 "的句子,我完全不明白。那么,如果MSA只是 "SOAP做得好",为什么我没有看到SOAP的例子?为什么这些例子(几乎)都是RESTful?

0
0 339
文章 Michael Lei · 八月 9, 2022 1m read

在测试你的代码时,你经常会遇到需要检查对象的实际内容。无论是使用 ZWRITE 还是 $system.OBJ.Dump()

你会得到一个简单的属性图片,"--- 属性值---"

而 "--- swizzled references ---" 更容易让人混淆 

用“--- calculated references ---" 你只是被留在了后面。

0
0 391
文章 Weiwei Gu · 六月 27, 2022 6m read

Globals,这些存储数据的魔剑,已经存在了一段时间,但是没有多少人能够有效地使用它们,也没有多少人知道这个超级武器。

如果你把Globals的东西用在它们真正能发挥作用的地方,其结果可能是惊人的,要么是性能的提高,要么是整体解决方案的大幅简化 (1, 2).

Globals提供了一种特殊的存储和处理数据的方式,它与SQL表完全不同。它们在1966年首次出现在 M(UMPS)编程语言中, 该语言最初用于医学数据库。现在它仍然以同样的方式被使用,但也被其他一些以可靠性和高性能为首要任务的行业所采用:金融、交易等。

后来M(UMPS)演变为 Caché ObjectScript (COS). COS是由InterSystems公司开发的,作为M的一个超集. 其原始语言仍然被开发者社区所接受,并在一些实现中保持活力。在网络上有几个活跃的网址,比如:MUMPS Google group, Mumps User's group), effective ISO Standard等等

现代基于Globals的数据库支持交易、日志、复制、分区等。这意味着它们可以被用来构建现代的、可靠的、快速的分布式系统。

Gloabls并不将你限制于关系模型的范围内。它们让你可以自由地创建为特定任务优化的数据结构。对于许多应用来说,合理地使用好的Globals就如一颗真正的银子弹头,它所提供的速度是传统关系型应用的开发者所梦寐以求的。

作为一种存储数据的方法,globals可以在许多现代编程语言中使用,包括高级和低级语言。因此,本文将特别关注Globals本身,而不是它们曾经来自的语言。

1
1 323
文章 Hao Ma · 一月 30, 2021 4m read

IIS在Windows Server里是默认安装,在Windows7和Windows10里面需要用户到"控制面板>程序"里面找到"Turn Windows features on or off"的设置来启动。 本文假设IIS已经在用户的服务器上启动,并且正常工作。

通常情况下,当IRIS安装在Windows系统时,用户会在同一台机器上使用IIS,很少有单独安装一台IIS服务器给远程IRIS提供Web服务器的,当然这样也绝无问题。

有两个软件包可以安装CSP Gateway。一个是IRIS的安装包。在IRIS的安装过程中, 如果有IIS正在工作, 那么安装程序会自动的安装CSP Gateway。 2018年以前的Ensemble或者Cache'的版本的安装过程中会跳出一个询问框,让用户选择是否"安装CSP网关。。。”。而后来的版本大多不做询问而自动为用户做了选择。 如果需要强制安装或者不安装CSP Gateway,那么需要在安装中选"Customer Component"设置。

另一个软件包是单独的CSP Gateway安装包, 可以在InterSystems的WRC或者工程师处得到。这是一个只有10多兆的很小的安装包,它只安装CSP Gateway, 并不安装IRIS实例,适合在单独的IIS硬件服务器上安装CSP Gateway; 或者, 当一个服务器上已有了IRIS, 但后来想添加IIS服务和CSP Gateway,用这个单独的安装包也很方便。

单独的CSP Gateway的安装会在IIS的工作目录“C:\Inetpub"下添加子目录CSPGateway,或者WebGateway, 然后在IIS的default Website上添加CSP Gateway的配置。整个配置相当简单。下面的步骤是在Windows10上单独安装Web Gateway安装包2020.1连接同一台服务器上的IRIS的的过程。

其中后面配置CSP Gateway访问IRIS应用的部分可以参考Apache上配置CSP Gateway的文档。

CSP Gateway安装

  1. 使用浏览器访问 http://localhost, 显示IIS的欢迎主页, 确认IIS已工作。
  2. 打开WebGateway-20201.1.xxxx-win_x64应用程序开始安装。安装时会提示用户输入连接的IRIS Server的IP地址和端口。默认的Application Name用CSP,IP地址端口使用localhost, 51773。安装过程会重启IIS服务,安装结束后用户不用手工重启。
  1. 安装后的检查IIS
  • 检查Web Gateway安装后的文件。 确认在IIS的安装目录(默认为C:\inetput)下安装了CSPGateway子目录, 其中包含若干dll文件。它们是IIS中用到的CSP Gateway的模块,在不同的CSP Gateway版本中这些Dll文件的数量和名字稍有不同。
  • 创建了c:/intersystems/WebGateway的文件夹,早些的版本中并不创建这个目录。
  • 打开IIS配置界面, 确认在Default Site下安装了CSP application. 在某些版本的Web Gateway安装后, /csp被安装为Virtual Directory, 关于IIS中application和virtual diectory的区别请自行查询, 无论安装成那种类型, 对csp的使用和配置没有区别。使用HealthConnect 2018以前版本的安装包安装的CSP Gateway生成CSP和ensemble两个Application。
  1. 查看CSP Gateway登录页面。

登录http://localhost/csp/bin/Systems/Module.cxw。 在主页上会显示Web Gateway的版本, Web Server Type是"Microseof-IIS"。配置文件和日志文件在c:\Inetpub\CSPGateway目录下。 (如果是打开时出现HTTP错误500.19, 你需要重启IIS)

  1. 查看连接的IRIS Server。

从左边菜单栏进入Server Access配置界面。其中csp是默认安装的IRIS连接。2018以前的版本可能用的是LOCAL。不管怎么说,使用"Edit Server"打开,可以看到连接的IRIS的端口和设置。

配置UserName"CSPSystem"和Password "SYS",并保存。

在左边菜单栏,使用"Test Server Connection"测试到“csp"的连接,测试成功会显示IRIS的版本。

Test Server Connection
Server connection test was successful: csp (localhost:51773)
$ZVersion: IRIS for Windows (x86-64) 2020.2 (Build 199U) Tue Apr 28 2020 17:17:56 EDT
  1. 访问IRIS维护主页 (可选)

从链接 http://WebServer/csp/sys/Utilhome.csp 访问IRIS维护主页System Management Portal应该可以成功了,但您会发现有部分网页内容(element)无法加载。这是因为在默认的安装中,只将"csp cls zen cxw"这4种类型的请求发送给CSP Gateway, 而被称为Static file的文件,比如.js, .css, .png等等类型的文件并没有被发送给CSP Gateway. 这是另外的一个安全机制,强制客户人工的配置是否需要从Web服务器访问IRIS维护主页。如果答案是NO, 那么访问IRIS维护页面就只能通过PWS,用IRIS服务器的52773的接口。 如果用户认为从Web服务器访问IRIS维护页面是必要的, 需要修改CSPFileTypes配置,把任意类型的请求发送给IRIS。

  1. 访问IRIS上的其他Web Application

IRIS上其他的Web Application, 比如”/api", ”/test"等等,通常情况下当Web Application被添加后,配置会自动同步到Web Gateway, 用户不用去Web Gateway的页面配置路由。但IIS上必须填写响应的配置,才能把请求从IIS发送到CSP Gateway. 这样操作:

  • 添加applications。如下图所示, 在IIS的default site下添加了两个新application, test和api.
  • 为每个applcation配置"Handler Mappings"。使用右边动作栏中的”Add Module Mapping",而不是另3种动作。 还要注意不要勾选"Request Restrictions"的"invoke handler only if request is mapped to"选择框,这样在"Handler Mappings"页面看到的Path Type一栏中显示的是"Unspecified", 否则会显示"File"或者其他内容。
  • 测试访问一些应用, 比如

http://172.16.58.200/api/mgmnt/v2/
http://172.16.58.200/test/test.webservice1.cls

一般情况下,到目前为止IIS已经能够正常工作,将需要的请求发送给IRIS。如果出现故障或者需要调整CSP gateway的配置,请参考[WebGateway系列_配置Apache连接IRIS]

3
0 484
文章 Michael Lei · 五月 17, 2022 3m read

在这篇文章中,我们将使用docker和 参数配置文件模版 这一新特性来运行IRIS集群且轻松配置好。

在 UNIX® 和 Linux 上,您可以使用声明式参数配置合并文件来修改默认的 iris.cpf。合并文件是一个部分 CPF,在实例启动时为任何数量的参数设置所需的值。CPF 合并操作对每个实例只起一次作用。

我们的集群架构非常简单,它将由一个主节点(Node1)和两个数据节点(检查所有可用角色)组成。不幸的是,docker-compose不能部署到几个服务器上(尽管它可以部署到远程主机上),所以这对本地开发分片的数据模型、测试等很有用。如果是生产的InterSystems IRIS集群部署,你应该使用ICM云管理器IKO K8S调度器

0
0 137
文章 Hao Ma · 四月 19, 2022 26m read

本文档只是给您一个大致的概念,方便您了解IRIS安装的方方面面。并非官方安装手册或者安装建议。生产环境的安装请仔细研究并参照IRIS官方的安装文档

操作系统的选择

IRIS支持多种Linux系统。详细的列表请参见各个版本的支持列表,比如这个是最新的2021IRIS的支持列表。需要注意的是, CentOS只支持作为测试系统, 并不支持生产系统的安装。

官方文档是以Redhat为主介绍的IRIS安装, 这是IRIS在生产环境中最常用的Linux系统之一。另一个Ubantu, InterSystems提供的docker版本是安装在Ubantu上的。

我自己测试的时候喜欢使用CentOS, 所以后面有具体安装步骤中,使用的CentOS上的记录。

服务器的配置

对于生产系统,安装前需要一个硬件配置方案,这个方案通常是您的项目的实施部门根据用户需求提供的。

对于测试系统,只有一个最小的磁盘的要求:1.5G。无论是实体服务器, 虚拟服务器,或者docker container,根据您要测试的内容, 一切以方便为准。如果不做性能测试,我个人经常使用的CentOS虚拟机是2核CPU, 2G或4G内存,没有运行不流畅的问题。

磁盘分区

标准的Linux磁盘分区并不适合IRIS的生产运行。哪怕要创建一个尽量接近生产的测试环境,建议您安装软件前要有一个完整的磁盘分区规划。在官方文档中,创建IRIS服务器分区有以下原则:

0
1 1024
文章 Weiwei Gu · 三月 14, 2022 3m read

大家好!

InterSystems IRIS有一个叫做互操作性Interoperability的菜单。

它提供了轻松创建系统集成的机制(适配器、记录图、BPM、数据转换等),因此不同的系统可以轻松地连接起来。

在数据中继过程中可以包括各种操作,比如:为了连接那些通常不连接的系统,可以根据目的系统的规格要求来接收(或发送)数据。另外,在发送数据之前,可以从另一个系统获取和添加信息。以及,信息可以从数据库(IRIS或其他)获取和更新。

为此,我们会撰写一系列的文章,将讨论以下主题,同时看一下示例代码,以帮助你了解它是如何工作的,以及在用互操作性整合系统时需要什么样的开发。

* How it works 它是如何工作的
* What a Production is 什么是Production ?
* Message 消息
* Component Creation 组件的创建

* 1)Business Operations  业务操作

*2)Business Processes 业务流程
*3) Business Services 业务服务


  首先,介绍一下我们在这个系列中要使用的案例。

 一家经营着一个购物网站的公司,目前正在改变其产品信息的显示顺序,以配合季节的变化。 然而,有些商品无论在什么季节都能卖得很好,而有些商品却在意想不到的时候卖得很好,这与目前改变顺序的显示规则不相符。 因此,我们研究了以当天的温度,而不是按季节来改变产品展示顺序的这种可能性。这就需要调查当时购买产品时的天气温度。 由于外部网络API可用于检查天气信息,我们计划在购买时收集这些天气信息,并在后来的审查数据库中登记。 这很简单,但你需要使用 "外部Web API "来收集信息,并且需要将获得的信息和购买信息结合起来,再在数据库中登记。 具体说明将在以后的相关文章中讨论(不包括创建网站)。也请大家持续关注查看! 至于我们这次使用的 "外部网络API",我们使用的是( OpenWeather当前天气数据.)

(如果你想尝试一下,你需要注册一个账户并获得一个API ID)。

下面是一个REST客户端的GET请求的结果(我们将在所应用的互操作性机制中去运行这个请求)。

The JSON of the HTTP response is as follows:

{
    "coord": {
        "lon": 135.5022,
        "lat": 34.6937
    },
    "weather": [
        {
            "id": 803,
            "main": "Clouds",
            "description": "broken clouds",
            "icon": "04d"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 17.05,
        "feels_like": 13.33,
        "temp_min": 16,
        "temp_max": 18,
        "pressure": 1017,
        "humidity": 55
    },
    "visibility": 10000,
    "wind": {
        "speed": 4.63,
        "deg": 70
    },
    "clouds": {
        "all": 75
    },
    "dt": 1611635756,
    "sys": {
        "type": 1,
        "id": 8032,
        "country": "JP",
        "sunrise": 1611612020,
        "sunset": 1611649221
    },
    "timezone": 32400,
    "id": 1853909,
    "name": "Osaka",
    "cod": 200
}

下篇文章中,我们将再来讨论如何使用互操作菜单来实现系统集成。 [OpenWeather]: https://openweathermap.org/

1
0 332
文章 Jingwei Wang · 十二月 23, 2021 6m read

正如你在我的简介中看到的,我在一所大学教书,我想分享我对IRIS(或之前的Caché)教学的看法。

已经有一段时间了,但我还记得在今年早些时候看到YURI MARX GOMES关于 "用InterSystems对象和SQL开发 "一系列课程。他对第1天第2天第3天的课程内容进行了简要的描述,并附有讲师Joel Solon的评论。我心想,分享我自己的经验可能会有趣。

在我真正写下我教给学生的东西之前,先简单介绍一下我的经历。

在我毕业拿到硕士学位回到大学工作后,我们系决定更新我们的课程,在普通课程中增加几门新课程。其中一门是 "后关系型数据库"。它是为研究生第一年的学生讲授的。开始时,它包括72小时的讲座和72小时的实践。现在变为秋季学期72小时的讲座和36小时的实践。

由于我是一名新员工,而且是一名年轻有为的员工,我被赋予了讲授这门新学科的职责。我感到惊讶和惊恐是不言而喻的。首先,我根本没有任何教学方面的实践经验。其次,我只有夏天的三个月时间来学习一项对我来说完全陌生的技术并准备课程的讲授。幸运的是,我已经知道了应该教授哪个数据库。这个数据库就是InterSystems Caché。

1
0 293
文章 Jeff Liu · 十月 26, 2021 21m read
本技术概要(First Look)通过重点概述和基本的实践示例,向您介绍在 InterSystems IRIS®数据平台上使用容器(Container)的基本原理。您将了解容器的目的、重要性和好处,以及 InterSystems 如何实现它们的具体细节。
有关 Docker 容器和 InterSystems IRIS 的完整文档,请参见 Running InterSystems Products in Containers(《在容器中运行 InterSystems 产品》),以及 InterSystems Cloud Manager Guide(《InterSystems 云管理器指南》)的 ICM Overview(ICM 概述)章节。Learn More About InterSystems IRIS in Containers(了解容器中的 InterSystems IRIS 的更多信息)部分提供了到其他参考资料的链接。
要浏览所有的技术概要(First Look),包括可以在 InterSystems IRIS 免费的评估实例上执行的那些,请参见 InterSystems First Looks(《InterSystems 技术概要》)。
 
 

为什么是容器(Container)?

0
0 217
文章 Michael Lei · 六月 23, 2021 15m read

InterSystems 数据平台包括了用于系统监视和警报的实用程序及工具,但对于不熟悉构建于 InterSystems 数据平台(又名 Caché)的解决方案的系统管理员来说,他们需要知道从何处下手以及需要配置什么。

本指南以在线文档和开发者社区帖子为参考,介绍了实现最低限度的监视和警报解决方案的途径,以及如何启用和配置以下组件:

0
0 268
文章 Hao Ma · 六月 4, 2021 3m read

之所以称为Dynamic,是说这个对象在代码编译的时候可以不定义对象的属性和结构,在runtime时才根据装入的数据来产生对象定义。IRIS里用Dynamic Object来处理JSON数据。简单说: 先定义一个Dynamic Object, 把JSON数据装进去,然后用对象的方式处理JSON文档。

让我们看看是它是怎么工作的。

创建一个Dynamic Object很简单, 标准而且啰嗦的写法是:

set dynObject1 = ##class(%DynamicObject).%New()

大家通常用简单的写法,像这样用一个{}来定义Dynamic Object:

DEMO>set dynObject1 = {}
DEMO>zw dynObject1
dynObject1={}  ; <DYNAMIC OBJECT>

字符串,流到DynamicObject的导入导出

把JSON数据从字符串或者流导入DynamicObject被称作Deserializing;反之,把DynamicObject里的JSON导出来到String或者Stream叫Serializing。在类%DynmicObject中用的是%FromJSON()和%ToJSON()两个方法,一个是类方法,一个是实例方法:

//从字符串,流里导入数据到%DynmicObject。str可以是字符串,stream, 或者流文件的URL
ClassMethod %FromJSON(str)  

//从%DynmicObject导出到字符串(出参),或者流(outStrm);是的,我知道这样method很别扭
Method %ToJSON(outStrm As %Stream.Object) As %String

实际使用的例子是这样:

DEMO>set str="{""aNumber"":42,""aDate"":""2021-06-04""}"
DEMO>set dynObject2=##class(%DynamicObject).%FromJSON(str) 
DEMO>zw dynObject2
dynObject2={"aNumber":42,"aDate":"2021-06-04"}  ; <DYNAMIC OBJECT>

上面的例子很傻。既然字符串是定义好的,就没必要先赋值给一个变量,直接用下面的代码就创建了一个Dynamic Object, 省掉了赋值字符串变量里用到的来escape符号"。

set dynObject2 = {"aNumber":42,"aDate":"2021-06-04"}

接着, 我们来看看真正体现Dynamic的对象定义。下面的代码中传入一个String消息,那么就需要用%FromJSON()来把JSON装入DynamicObject

method example1(pInput As %Ens.StringRequest) As %Status
{   //把请求里的JSON字符串装入DynamicObject
    set dynObject2=##class(%DynamicObject).%FromJSON(pInput.StringValue)
    
    //把DynamicObject导出到字符串
    set myString= dynObject2.%ToJSON()
    //把DynamicObject导出到流
    set myStream=##class(%Stream.GlobalCharacter).%New()
    do dynObject2.%ToJSON(myStream)

    //打印结果
    w dynObject2.%ClassName(),!
    w mystring, !
    w myStream.Read(),!
}

以上代码的执行结果是:

%DynamicObject
{"aNumber":42,"aDate":"2021-06-04"}
{"aNumber":42,"aDate":"2021-06-04"}

用DynamicObject处理JSON

把JSON数据装入DynamicObject是为了方便用对象的方式处理JSON,比如取值:

w dynObject2.aName,!
w dynObject.aDate,!

或者,给对象的属性赋值

set dynObject2.aNumber=43
set dynObject2.aDate=$ZD($H)

或者,也可以使用%Get(), %Set()方法,根据key,得到或者修改value,比如

set tempVariable = dynObject2.%Get("aNumber")
do dynObject2.%Set("aNumber",44)

关于%Get(),%Set()还有些复杂的用法,请参考在线文档。

下面是最重要的, 遍历整个DynamicObject

set itr = dynObject2.%GetIterator()
while itr.%GetNext(.key,.val) 
{   
    write key_", "
    write val_", "
    write dynObject2.%GetTypeOf(key),!
} 

其他的方法包括: %Remove(), %IsDefined(), 请自己查阅文档。

DynamicObject的错误处理

Dynamic Object不使用的%Status来做错误处理,因此我们必须用try-catch来捕捉错误,比如下面的代码:

TRY { set invalidObject = {}.%FromJSON("{:}") } CATCH errobj { write errobj.Name_", "errobj.Location", error code "_errobj.Code,! RETURN }

其他的几点注意

有了上面的知识,已经足以在代码中处理JSON文档了。还有几点请注意:

  • %Library.DynamicArray

和DynamicObject的区别是这是一个Array, 用法很类似,请各位自己阅读文档了解。

  • Dynamic Object可以嵌套, 比如这样 set objectStr = {"a":12,"b":"some string","c":{"x":1,"y":2}}

  • 定义Dynamic Object时可以使用ObjectScirpt表达式,比如

      set dynObj = { "Date":($ZD($H,3)) }
    

下篇文章我会介绍%JSON.Adapter

0
0 285