搜索​​​​

清除过滤器
文章
Claire Zheng · 五月 18, 2023

【视频】对话:“数据二十条”与FHIR标准

“数据二十条”体现了怎样的制度创新和政策智慧?FHIR将如何发挥作用?来看InterSystems亚太区总经理老卢(Luciano Brustia)与CHIMA主任委员王才有的精彩探讨!
公告
Claire Zheng · 十一月 9, 2023

InterSystems开发者社区中文版第二届技术征文大赛专家评审团亮相!

大家好! 2023年9月19日-11月24日(北京时间),🏆InterSystems开发者社区中文版第二届技术征文大赛🏆正在进行中(←点击链接进入参赛页面,浏览所有参赛文章)!作为此次大赛重要奖项“专家提名奖”评比的重要部分,我们的专家评审团已组建成团! 以下为我们的专家团成员,来自我们的销售工程师团队与WRC支持团队。 @Yunfei.Lei @Peng.Qiao @Lin.Zhu @jieliang.liu7848 @Ida.Yang @Louis.Lu @Hao.Ma @Jingwei.Wang @Tete.Zhang @Tengzhou.Zhuang 我们期待专家评审团对参赛作品的公平审阅与打分。 作为社区成员,您的个人贡献也会对每一篇参赛文章产生影响,每一次浏览和点赞都将助力您喜欢的文章赢得“开发者社区奖”。 欢迎大家积极投稿、点赞、分享、学习! 欢迎积极参加InterSystems开发者社区中文版第二届技术征文大赛
公告
Claire Zheng · 六月 14, 2023

2023 年 6 月 13 日 - 公告:进程内存使用量增加

InterSystems 已纠正导致进程内存使用量增加的缺陷。 具体来说,在对局部变量执行$Order 、 $Query 或 Merge时,会出现本地进程分区内存消耗增加的问题。虽然这对大多数运行环境没有不利影响,但支持大量进程或严格限制每个进程最大内存使用的环境可能会受到影响。某些进程可能会遇到<STORE> 错误。 该缺陷存在于2023.1.0.229.0中,但它被重新发布为2023.1.0.235.1,并包含了修复程序,以加快修正,而无需客户等待维护版本。 此缺陷的更正标识为 DP-423127 和 DP-423237。这些将包含在所有未来版本中。 该缺陷出现在 InterSystems IRIS ® 、InterSystems IRIS for Health ™ 和HealthShare ® Health Connect 的版本 2022.2、2022.3 和 2023.1(内部版本 229)中。如果您运行的是这些版本之一,我们建议升级到 2023.1(内部版本 235)。 此修复也可通过 Ad hoc 分发获得。 如果您对此警报有任何疑问,请联系全球响应中心。
文章
Louis Lu · 八月 30, 2023

使用代码获取数据库剩余空间

大家可以通过InterSystems IRIS 管理门户SMP查看当前数据库剩余空间,路径是 Management Portal: System Operation > Database 当然大家也可以通过下面的代码查看数据库的可用磁盘空间: /// ZISJ.mac Set stmt=##class(%SQL.Statement).%New() Set status=stmt.%PrepareClassQuery("SYS.Database","FreeSpace") Set rs=stmt.%Execute() While rs.%Next() { Write ! For i=1:1:9 { Write rs.%GetData(i),"," } }
文章
姚 鑫 · 七月 25, 2023

第二章 HL7 架构和可用工具

# 第二章 HL7 架构和可用工具 - HL7 模式和消息概述 ## HL7 模式和消息概述 `InterSystems` 产品可以处理和传递 `HL7` 消息,而无需使用架构来解析它,但将架构与消息关联允许执行以下操作: - 解析消息并访问以下字段值: - 数据转换 - 路由规则 - 自定义 `ObjectScript` 代码 - 验证消息是否符合架构。 每个 `HL7` 消息均由消息类型标识,该消息类型在 `MSH` 段 `MessageType` 字段 (`MSH:9`) 中指定。一些消息类型共享相同的消息结构。例如,在`HL7`版本`2.3.1`中,用于预先接纳患者的`ADT_A05`消息具有与`ADT_A01`接纳消息相同的结构。该架构指定 `ADT_A05` 消息具有结构类型 `ADT_A01`。 为了解析 `HL7` 消息,需要两条信息: - 架构类别 — 这是 `HL7` 版本号,例如 `2.3.1` 或 `2.7`,或者它可能是 `InterSystems` 产品中定义的自定义架构的类别。`production` 从业务服务消息模式类别设置或从数据转换设置获取模式类别。尽管 `HL7` 消息在 `MSH` 段 `VersionID` 字段中包含模式版本号 (`MSH:12`),但 `InterSystems` 不使用此值,因为许多应用程序并未一致地设置此字段。 - 结构类型 - `production` 从 `MSH:9` 字段获取消息类型,然后检查架构定义以获取该消息的结构类型。 在某些情况下,使用 `MSH:9.3` 子字段来限定消息类型。 `MSH:9:`3 子字段在 `HL7` 消息中以两种方式使用:1) 作为消息类型的修饰符,或 2) 指定结构类型。如果 MSH:9:3 修改消息类型(通常为数字),InterSystems 产品会将其作为消息类型的一部分。如果 MSH:9:3 指定结构类型(例如 `ADT_A01`),则 `InterSystems` 在确定消息类型和设置 `Name` 属性时都会忽略它。 `InterSystems` 产品不需要 `MSH:9.3` 子字段来确定结构类型,因为它们从架构中获取结构类型。 当业务服务或数据转换创建 `EnsLib.HL7.Message` 对象来存储 `HL7` 消息时,它会组合架构类别和结构类型,并使用以下语法将其存储在 `DocType` 属性中: ``` category:structureType ``` 例如,类别 `2.3.1` 的有效 `DocType` 值包括 `2.3.1:ACK`、`2.3.1:ADT_A17`、`2.3.1:BAR_P01` 和 `2.3.1:PEX_P07`。消息类型可以与结构类型不同,存储在 `Name` 属性中。 如果在 `ObjectScript` 代码中创建 `EnsLib.HL7.Message` 对象,则应根据 `MSH:9` 字段中的值设置 `DocType` 和 `Name` 属性。 `HL7` 标准允许本地扩展,例如尾部 `Z` 段。这些段未在基本架构类别中定义。如果要访问数据转换、路由规则或 `ObjectScript` 中自定义 `Z` 段中的字段,则需要定义指定扩展消息的自定义架构类别。 可以将自定义 `HL7` 架构置于源代码管理之下。启用源代码控制后,源代码控制选项(例如签出和签入)可从主 `HL7` 模式页面使用,但在用于处理自定义模式的其他页面(例如 `HL7` 模式消息类型页面)上不可用。在使用其他页面编辑架构之前,必须从 `HL7` 架构页面检查整个架构。 `HL7` 模式主页面提供了源代码控制输出窗口,该窗口捕获所有相关 `HL7` 模式页面的源代码控制活动。有关设置源代码控制的信息,请参阅将 `IRIS` 与源代码控制系统集成。 这个应该只是讲的HL7 v2 的消息吧?
问题
li liao · 八月 30, 2023

Caché 2016.1 CDC

参考 https://blog.csdn.net/InterSystems/article/details/115350635 搭建 mirror ,获取数据变更,示例给出了获取数据变更的代码: Class ZCustom.MirrorDejournal Extends SYS.MirrorDejournal{ Method RunFilter( MirrorDBName As %String, GlobalReference As %String, RecordType As %String, Address As %Integer) As %Integer{ Set ^CDCLog( $I($^CDCLog))=$lb(MirrorDBName,GlobalReference,RecordType,Address) Quit 1} 示例代码将变更存储在 global 对象 CDCLog 中,想请问下获取变更前后数据,发送到外部系统,有哪些方式? 可以参考我们的CDC系列文章https://cn.community.intersystems.com/node/491941,谢谢!
公告
Claire Zheng · 十月 17, 2023

重要公告:征文大赛将延期至11月24日!欢迎继续投稿,参加InterSystems开发者社区中文版第二届技术征文大赛!

嗨,开发者们! 我们决定将🏆InterSystems开发者社区中文版第二届技术征文大赛 🏆的参赛时间延长至11月24日,请参赛者关注重要时间节点的变化。 📝 2023年9月19日-11月23日(北京时间),文章发布与点赞收集!在社区发布文章后即可开始为您的文章收集点赞。越早发布文章,就越有时间收集更多点赞(这是您获得“开发者社区奖”的关键)。 📝 2023年11月23日(北京时间),专家打分截止(专家提名奖)。 🎉 2023年11月24日(北京时间),公布获奖名单。 欢迎大家继续积极投稿,赢取大奖! 了解参赛规则及文章样例:点击此处 了解奖品详情:点击此处 欢迎投稿参赛! 快乐分享技术,期待您的大作!✨ 🏆InterSystems开发者社区中文版第二届技术征文大赛 🏆(←点击链接进入参赛页面,浏览所有参赛文章)
文章
Michael Lei · 八月 10, 2023

如何比较两个数据库中的多个Global和Routines

InterSystems 常见问题解答 ※如果您想比较使用Mirror、Shadow或其他机制复制的数据库,请使用此方法。 您可以使用 DATACHECK 实用程序来比较Global。请参阅下面的文档。DataCheck 概述 [IRIS] *** Routines比较使用系统例程 %RCMP 或管理门户。 以下是如何在管理门户中使用它。 例如,假设以下Routine位于 USER 命名空间中。 test() public{ quit "hello" } 假设以下Routine位于 USER2 命名空间中。 test() public{ quit "Hello" } 下面是在连接到 USER 命名空间的终端中运行 %RCOM 的结果。 * 在Compare : 中写入Routine名称以及要与: 进行比较的Routine名称要指定另一个命名空间中的Routine,请指定|“命名空间名称”|例程名称.MAC。 用户>执行 ^%RCMP比较:comptest.mac 与:|"USER2"|comptest.macCompare: // [备注] 如果没有可比较的内容,请按 Enter忽略评论差异?否 => 否忽略前导空格?否 => 否显示结果于Device: c:\temp\comp.txt // [备注] 指定文件名时的文件输出 参数? (“WNS”)=>comptest.MAC |“USER2”|comptest.MAC****************************************************** ******************************用户> 对比结果如下。 常规比较 2021 年 2 月 2 日 2:31 PM来自目录:c:\intersystems\iris\mgr\user\ comptest.MAC |“USER2”|comptest.MAC****************************************************** ******************************竞争测试.MAC+2 退出“你好”......................|“USER2”|comptest.MAC+2 退出“你好”****************************************************** **************************
文章
Weiwei Gu · 九月 14, 2023

VS Code 无法连接到服务器的原因之一

昨天,我在一个客户网站提供从 Studio 迁移到 VS Code 的定制咨询时,就遇到了这种情况。 该站点的服务器已配置为使用delegated authentication,但尚未针对 /api/atelier Web 应用程序设置“delegated”复选框,而 InterSystems ObjectScript 扩展包的成员正是使用该复选框进行连接的。 一旦我们的应用程序设置了其复选框并单击了服务器管理器刷新按钮,就可以在服务器上枚举命名空间。
文章
Weiwei Gu · 八月 14, 2023

调试管理门户加载图片失败的原因

在提交的 WRC case中(Intersystems 全球技术支持响应中心),我们经常看到客户提出有关新 Web 网关设置的问题,其中管理门户加载一半,但不显示图像。本文将解释为什么会出现此错误,以及如何修复它。本说明主要针对服务 InterSystems IRIS 实例的 Web 网关,但相同的说明也应适用于服务 Caché 实例的 CSP 网关。 问题: 您刚刚在独立的 Web 服务器上安装了 Web Gateway。当你去加载管理门户时,你发现它无法显示或加载图像,如下所示: 为什么会发生这种情况: 问题是,为了完整加载管理门户,InterSystems IRIS 必须加载许多 .js、.css 和 .png 文件(静态文件)。如果您看到像上面这样的管理门户页面,请随时打开浏览器的开发人员工具小程序,导航到“网络”选项卡,并确认未提供各种 .js、.css 和 .png 组件: 最初安装 Web Gateway 时,我们仅为以下扩展设置映射: .csp .cls .zen .cxw 这些是客户在自己的自定义应用程序中最常使用的文件扩展名类型,以及用于为 Web Gateway 管理门户提供服务的 .cxw 扩展名。如果您想要加载其他管理门户组件,则必须注册其他文件类型以由 Web 网关提供服务。 如何解决该问题: 要使管理门户完全显示,您必须配置 Web 网关以提供其他文件类型。对于 IIS,您可以为 .js、.png、.css 等扩展名添加单独的映射,也可以添加通配符映射。可以在此处找到有关注册 IIS 的其他文件类型的文档:https: //docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls ?KEY=GCGI_win#GCGI_registering 如果您在 Unix / Linux 系统上的 Apache 之上运行 Web Gateway,您有几个选择。您可以通过添加其他文件扩展名(如 IIS 上的情况)来配置此功能,也可以添加 CSP 位置指令。请参阅此处的文档了解完整详细信息: https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls ?KEY=GCGI_ux,位于“使用 CSP 注册其他文件类型”下
文章
Qiao Peng · 一月 31

用Java开发互操作产品 - PEX

InterSystems IRIS、Health Connect和上一代的Ensemble提供了优秀的互操作架构,但即便有低代码开发能力,很多开发者还是希望能用自己的技术栈语言在InterSystems的产品上开发互操作产品。 考虑到互操作产品本身的开放性要求和各个技术栈背后庞大的生态价值,InterSystems IRIS和Health Connect提供了Production EXtension (PEX)架构,让开发者使用自己的技术栈语言来开发互操作解决方案。目前PEX支持Java、.net、Python。 这里我们介绍使用Java利用PEX进行互操作产品的开发。 一 InterSystems IRIS上使用Java开发的基础 在进入PEX主题前,需要简单介绍一下Java在InterSystems IRIS上开发的各种技术选项,因为PEX也是以这些技术选项为基础的。 如果仅把InterSystems IRIS作为一个数据库看待,可以使用JDBC对它进行SQL访问,这是最传统的开发方式; Java是一个面向对象的开发语言,而InterSystems IRIS也是支持面向对象的数据平台。InterSystems IRIS的外部语言服务器技术,提供了一套Java原生SDK,让Java和InterSystems IRIS可以互相访问对方的对象,甚至Java可以通过它直接访问InterSystems IRIS后台的持久化多维数组。外部语言服务器提供了非常灵活、高效的开发方式; 如果是想把Java对象直接持久化到InterSystems IRIS,除了Hibernate,InterSystems IRIS提供一种更高性能的方法 - XEP(Express Event Persistence表达事件持久化); 最后,Java可以通过PEX开发InterSystems IRIS的互操作产品组件。PEX基于Java原生SDK。 作为多种Java访问方式的基础,InterSystems IRIS的Java外部语言服务器的架构如下: InterSystems IRIS和Java通过动态代理对象的方式操作对方对象,动态代理无需在对方代码变更时重新生成代理类。 InterSystems IRIS提供了intersystems-jdbc-<版本号>.jar,不仅用于JDBC连接、也用于Java外部语言服务器连接,提供Java原生SDK。 在Java端通过jdbc.IRIS管理InterSystems IRIS连接,使用jdbc.IRISObject反向操作IRIS对象。 InterSystems IRIS端提供并管理包括Java语言服务器在内的一系列外部语言服务器。注意,一般情况下,使用系统开箱的这些外部服务器就够了,不需要额外建立额外的Java语言服务器。而且,也无需事先启动,外部语言服务器会在调用时自动启动。 Java连接到InterSystems IRIS,并创建IRIS外部服务器的示例: String connStr = "jdbc:IRIS://127.0.0.1:1972/USER"; String user = "superuser"; String pwd = "SYS"; // 使用DriverManager 创建IRIS连接 // IRISConnection conn = (IRISConnection)java.sql.DriverManager.getConnection(connStr,user,pwd); // 或使用IRISDataSource 创建IRIS连接 IRISDataSource ds = new IRISDataSource(); ds.setURL(connStr); ds.setUser(user); ds.setPassword(pwd); IRISConnection conn = (IRISConnection) ds.getConnection(); // 创建IRIS外部服务器 IRIS irisjv = IRIS.createIRIS(conn); // 调用IRIS类%PopulateUtils的类方法Name,产生随机姓名 String tempTrader = irisjv.classMethodString("%PopulateUtils", "Name"); 二 PEX 开发 PEX针对于互操作产品的开发,通过PEX使用外部语言开发互操作产品所需的组件,甚至可以通过PEX开发互操作产品的所有组件。 2.1 InterSystems IRIS互操作产品架构 典型的InterSystems IRIS互操作产品架构如下,它的典型工作机制是: 业务服务通过入站适配器监听外部系统,例如TCP和文件系统,将数据组织成消息发送给业务流程 业务流程根据流程需要在特定流程节点将消息发送给业务操作 业务操作通过出站适配器访问外部应用,发送数据并获取响应,并将响应数据组织成消息反馈给业务流程 在互操作产品内部流转的都是消息,消息默认自动持久化并可以通过SQL等方式结构化查询 互操作产品涉及3类组件: 业务组件:包括业务服务、业务流程、业务操作 适配器:包括入站适配器和出站适配器 消息 这3类组件都可以通过PEX进行开发。 2.2 PEX 类和类包 InterSystems IRIS 提供了一个intersystems-utils-<版本号>.jar包,提供com.intersystems.enslib.pex类包,用于基于Java开发互操作产品组件。 在Java代码里还要调用IRIS Object Script开发的组件和代码,因此,还需要intersystems-jdbc-<版本号>.jar。 2.3 示例业务场景介绍 下面我们根据一个示例业务场景介绍如何使用Java PEX进行互操作产品的开发。 业务场景是一个银行间汇款的流程: 业务服务(Finance.FromFileTransaction)监听特定文件夹,并从新汇款申请文件中解析出汇款请求,发送给业务流程(Finance.ProcessPaymentRequest); 业务流程先将请求发送给汇出行的业务操作(Finance.ToPayFromBank),获取汇出行的审核结果; 如果汇出行审核批准,则业务流程继续将请求发送给接收行的业务操作(Finance.ToPayToBank) 这里汇出行的业务操作和接收行的业务操作都会将数据写入特定文件夹的文件中。 这个场景中,我们完全使用Java开发全部的组件,包括:请求、响应消息;入站、出站文件适配器;业务操作;业务流程和业务服务。 下面我们就开始吧。 2.4 消息开发 Java消息类是com.intersystems.enslib.pex.Message的子类,消息中的属性,需要定义为public。它会在互操作业务组件间传递时自动持久化。 在IRIS端,Java消息自动映射到EnsLib.PEX.Message,它是一个持久化的IRIS类,包含以下属性: %classname属性:Java消息类名 %json属性:Java消息的JSON类型(IRIS动态对象) 在InterSystems IRIS端,例如消息可视化追踪页面和消息表,你看到的Java消息都是EnsLib.PEX.Message类型。 PEX消息用到的共同账号信息类的示例代码: package Finance; // 封装银行账号信息的类. public class PaymentProfile extends com.intersystems.enslib.pex.Message { public int AccountNumber; public int RoutingNumber; public String UserName; } 请求消息的示例代码: package Finance; import Finance.PaymentProfile; // PEX开发的转账请求消息. public class TransactionRequest extends com.intersystems.enslib.pex.Message { public double TransactionAmount; // 转账金额 public PaymentProfile PayFrom; // 付方银行账号信息 public PaymentProfile PayTo; // 收方银行账号信息 public String FromCurrency; // 付方货币 public String ToCurrency; // 收方货币 // 实例化银行账号属性. public TransactionRequest(){ PayFrom = new PaymentProfile(); PayTo = new PaymentProfile(); } } 响应消息的示例代码: package Finance; // PEX开发的转账响应消息. public class TransactionResponse extends com.intersystems.enslib.pex.Message { public boolean approved; } 2.5 业务组件和适配器的运行时变量 在互操作产品的管理配置页面,可以设置各个业务组件和适配器的配置项,例如文件适配器的文件路径,方便实施和管理。 对于Java开发的业务组件和适配器,同样我们需要这样的配置项。这些配置项,我们称之为运行时变量,这样进行定义: 运行时变量是Java业务组件类和适配器类的public类型的属性 对这些属性使用Java annotation进行元数据描述,例如: @FieldMetadata(IsRequired=true,Description="文件路径") public String FilePath; 后面的Java业务组件和适配器会用到运行时变量的声明方法。 2.6 入站适配器开发 如果要开发Java入站适配器,需要定义一个com.intersystems.enslib.pex.InboundAdapter的Java子类。并在类中实现以下方法: 方法 参数 说明 OnTask 无 适配器根据调用间隔设置,周期性地调用该方法对数据源进行查询;将数据调用BusinessHost.ProcessInput()将数据发送给业务服务;BusinessHost是业务服务的固定的变量名 OnInit 无 适配器初始化的方法 OnTearDown 无 适配器退出清理的方法 例如入站文件适配器示例代码如下: package Finance; import java.io.File; // 导入File类. import java.io.FileNotFoundException; // 导入此类以处理错误. import com.intersystems.enslib.pex.FieldMetadata; // 导入PEX运行时变量类 // 这是一个PEX的入站适配器,检测定义在InboundFilePath的文件夹路径。如果文件夹下有文件,遍历这些文件,使用ProcessInput()将文件路径发送给业务服务 public class PEXInboundAdapter extends com.intersystems.enslib.pex.InboundAdapter { @FieldMetadata(IsRequired=true,Description="输入文件路径") public String InboundFilePath; // 文件夹路径配置项. public void OnTearDown() {} public void OnInit() {} public void OnTask() throws Exception { // 检查文件夹路径,并遍历文件. File folder = new File(InboundFilePath); File[] list = folder.listFiles(); if (list.length > 0) { for (File file : list) { // 忽略.keep后缀文件. // 其它文件路径发送给业务组件BusinessHost. if (file.getName().equals(".keep")) {continue;} BusinessHost.ProcessInput(file.getAbsolutePath()); } } } } 2.7 Java开发组件的注册与更新 开发好的Java组件,需要在InterSystems IRIS端进行注册,让互操作产品可以直接使用这些组件。 注册的方法在Production扩展页面,点击注册新组件: 在远程类名称中填写Java组件类名 在代理名称中填写IRIS生成的代理类名称,可以和Java类名不同。这个类名是在互操作产品中看到和使用的名字。 选择外部语言服务器为%Java Server 将封装有Java组件类的jar文件路径和其它依赖jar文件路径添加到网关额外CLASSPATHS下 注册后就可以在列表中看到注册的组件和组件类型,并在互操作产品中可以直接使用了。 如果后来修改了Java代码,则需要选中已经组册的组件,对其进行更新: * 记得下面这些Java开发的组件也需要注册后使用。 2.8 出站适配器开发 同样,可以通过继承com.intersystems.enslib.pex.OutboundAdapter来开发Java出站适配器类。 它需要实现以下方法: 方法 参数 说明 OnInit 无 适配器初始化的方法 OnTearDown 无 适配器退出清理的方法 其它方法 根据需要 执行具体的适配器操作 例如出站文件适配器示例代码如下,它提供写文件的方法: package Finance; import java.io.File; // 导入File类. import java.io.FileNotFoundException; // 导入此类以处理错误. import java.lang.StringBuffer; // 导入string buffer类. import java.io.FileWriter; // 写文件的包. import java.util.Date; // 处理日期的包. import com.intersystems.enslib.pex.FieldMetadata; // 导入PEX运行时变量类. import java.text.SimpleDateFormat; // 格式化日期字符串的包. // 这是一个PEX的出站适配器,通常被业务操作使用,连接到外部系统. 这里适配器提供WriteToFile()方法,供业务操作调用. public class PEXOutboundAdapter extends com.intersystems.enslib.pex.OutboundAdapter { @FieldMetadata(IsRequired=true,Description="输出文件路径") public String FilePath; // 输出文件路径. public void OnTearDown() {} public void OnInit() {} //写文件的方法,输入参数input是向文件中写入的内容 public Object WriteToFile(java.lang.Object input) throws Exception { // 转换为字符串 String OutputMessage = (String)input; // 允许用户输入的路径有或没有尾部路径分隔符. if (FilePath.substring(FilePath.length() - 1) != File.separator) { FilePath = FilePath + File.separator; } // 用当前日期时间产生文件名. Date today = new Date(); SimpleDateFormat Formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); String DateString = Formatter.format(today); // 产生完整文件路径. String OutputPath = FilePath + DateString; // 创建文件. File OutputFile = new File (OutputPath); // 实例化FileWriter对象. FileWriter writer = new FileWriter(OutputFile); // 将内容写入文件 writer.write(OutputMessage); writer.close(); return null; } } 2.9 业务操作开发 Java业务操作类,是com.intersystems.enslib.BusinessOperation的子类。需要实现以下功能: 方法 参数 说明 OnInit 无 适配器初始化的方法 OnTearDown 无 适配器退出清理的方法 OnMessage 无 个方法会在业务操作收到其它业务组件传递过来的消息时被调用 在该方法内部,可以调用适配器的方法 - Adapter.invoke("适配器方法名", 方法参数) Adapter是适配器对象,已经实例化,无需执行自己的实例化代码。Adapter是固定变量名 getAdapterType 无 返回使用的适配器类名 如果是PEX开发的适配器,返回的是它注册到InterSystems IRIS的代理类名 如果使用默认适配器,返回 Ens.InboundAdapter 如果不使用适配器,返回空字符串 例如我们的示例中,有以下2个业务操作: 1. 与汇出银行接口的业务操作类: package Finance; import Finance.TransactionRequest; import Finance.PaymentProfile; import Finance.TransactionResponse; import java.lang.StringBuffer; // PEX业务操作类,和支付银行接口. // 它从业务流程接收请求消息Finance.ProcessPaymentRequest, 将消息内容写入文件并返回内容为'approval' 的响应消息(Finance.TransactionResponse). public class ToPayFromBank extends com.intersystems.enslib.pex.BusinessOperation { public void OnTearDown() {} public void OnInit(){} // 确定适配器 public String getAdapterType() { return "Finance.PEXOutboundAdapter"; } // 响应请求消息 public java.lang.Object OnMessage(java.lang.Object object) throws java.lang.Exception { // 将输入对象转换为对应的类实例. TransactionRequest request = (TransactionRequest)object; // 初始化StringBuffer对象,构造输出文件内容. StringBuffer outputMessage = new StringBuffer(); // 将数据写入StringBuffer. outputMessage.append("Debit request:" + System.lineSeparator()); outputMessage.append("Route:" + request.PayFrom.RoutingNumber + System.lineSeparator()); outputMessage.append("Account: " + request.PayFrom.AccountNumber + System.lineSeparator()); outputMessage.append("Amount: " + request.TransactionAmount); // 调用出站适配器的方法,将数据写入文件. Adapter.invoke("WriteToFile", outputMessage.toString()); // 实例化响应消息,并对响应消息赋值后返回给业务流程. TransactionResponse response = new TransactionResponse(); response.approved = true; return response; } } 2. 与接收银行接口的业务操作类: package Finance; import Finance.TransactionRequest; import Finance.PaymentProfile; import java.lang.StringBuffer; // PEX业务操作类,和收款银行接口. // 从业务流程接收请求消息,并将消息内容写入文件. public class ToPayToBank extends com.intersystems.enslib.pex.BusinessOperation { public void OnTearDown() {} public void OnInit(){} // 确定适配器 public String getAdapterType() { return "Finance.PEXOutboundAdapter"; } // 响应请求消息 public java.lang.Object OnMessage(java.lang.Object object) throws java.lang.Exception { // 将输入对象转换为对应的消息类实例. TransactionRequest request = (TransactionRequest)object; // 实例化StringBuffer对象以构造文件内容. StringBuffer outputMessage = new StringBuffer(); // 将数据写入StringBuffer. outputMessage.append("credit request:" + System.lineSeparator()); outputMessage.append("SourceRouting:" + request.PayFrom.RoutingNumber + System.lineSeparator()); outputMessage.append("SourceAccount: " + request.PayFrom.AccountNumber + System.lineSeparator()); outputMessage.append("ToAccount: " + request.PayTo.AccountNumber + System.lineSeparator()); outputMessage.append("Amount: " + request.TransactionAmount); // 调用出站适配器方法将数据写入文件 Adapter.invoke("WriteToFile", outputMessage.toString()); // 无需响应消息. return null; } } 2.10 业务流程开发 使用Java开发业务流程,则完全是代码开发模式,而非基于BPL的低代码模式。 Java业务流程类是com.intersystems.enslib.pex.BusinessProcess 的子类,需要实现以下方法: 方法 参数 说明 OnInit 无 适配器初始化的方法 OnTearDown 无 适配器退出清理的方法 OnRequest request 请求消息 处理发送给业务流程的请求消息,这个请求消息启动业务流程 OnResponse request 请求消息, response 响应消息, callRequest - 本次异步调用发起的请求消息, callResponse - 本次异步调用收到的响应消息, completionKey - 异步调用发起时传入的completionKey 处理异步调用返回的响应消息-callResponse OnComplete request 请求消息, response 响应消息 整个业务流程完成时,被调用的方法 另外,类里还可以声明需要在业务流程期间保存的持久化数据,和在BPL中要到的上下文(context)数据一样,例如记录汇出行的审核结果。声明时,需要加@Persistent这个Java annotation: @Persistent // 定义名为runningTotal的持久化的属性 public integer runningTotal = 0; 本用例的业务流程示例代码如下: package Finance; import Finance.TransactionRequest; //导入请求消息类 import Finance.TransactionResponse; //导入响应消息类 // 这是一个PEX业务流程类,它从业务服务(Finance.FromFileService)接收请求消息. // 先将汇款请求消息发送给汇出行业务操作(Finance.ToPayFromBank) 并等待审核结果. 如果批准, 将请求消息发送给接收行业务操作(Finance.ToPayToBank). public class ProcessPaymentRequest extends com.intersystems.enslib.pex.BusinessProcess { public Object OnComplete(Object object,Object object2) {return null;} public void OnTearDown(){} public void OnInit(){} // 无需返回响应消息给调用者 public java.lang.Object OnResponse(java.lang.Object request, java.lang.Object response, java.lang.Object callRequest, java.lang.Object callResponse, java.lang.String completionKey) throws java.lang.Exception { return null; } // 处理请求消息 public java.lang.Object OnRequest(java.lang.Object object) throws java.lang.Exception { // 将输入对象转换为对应的消息类实例. TransactionRequest request = (Finance.TransactionRequest) object; // 将支付请求消息以同步请求的方式发送给汇出行. Object response = SendRequestSync("Finance.ToPayFromBank", request); // 将收到的响应消息对象转换为对应的消息类实例. TransactionResponse bankResponse = (TransactionResponse)response; // 记录汇出行审核结果,用于调试 LOGINFO("汇出行审核结果是:"+bankResponse.approved); // 检查汇出行审核结果,如果是批准,则将汇款请求发送给接收行. if (bankResponse.approved) { // 使用异步调用方式通知接收行,无需等待返回. SendRequestAsync("Finance.ToPayToBank", request); } return null; } } 2.11 业务服务开发 Java业务服务类是com.intersystems.enslib.pex.BusinessService 的子类。它有一个父类定义的属性 – TargetComponentNames, 用于设置发送消息目标的下游业务组件名列表。可以同时发送消息给多个下游业务组件,组件名之间通过逗号分隔。 业务服务可以使用适配器,这时它会根据适配器的设置定期轮询外部系统,例如SQL适配器轮询外部SQL表、文件适配器轮询外部文件夹。但业务服务也可以不使用适配器,而直接被外部系统调用,例如发布为SOAP、RESTful服务的业务服务就不使用适配器。 适配器 执行过程 需要实现的方法 使用专业适配器 适配器的OnTask()方法定期执行获得数据,将数据发送给业务服务的ProcessInput() OnProcessInput() 使用默认适配器 Ens.InboundAdapter 适配器的OnTask()方法定期执行,并调用业务服务的ProcessInput(); 业务服务的OnProcessInput()执行数据获取 OnProcessInput() 不使用适配器 不定期执行,用户代码在需要时通过Director.CreateBusinessService() 创建业务服务,并执行其方法 OnProcessInput() 或其它需要的方法 本示例中的业务服务使用前面Java开发的文件入站适配器,其代码如下: package Finance; import java.io.File; // 导入File类. import java.io.FileNotFoundException; // 导入此类以处理错误. import java.util.Scanner; // 导入Scanner类读取文本文件. import Finance.TransactionRequest; // 导入请求消息类. // 这是一个PEX的业务服务类,从文件读取汇款请求. 将文件内容转换为Finance.TransactionRequest消息对象,并检查运行时变量TargetComponentNames,确定需要把请求消息发送给哪些业务组件. public class FromFileTransaction extends com.intersystems.enslib.pex.BusinessService { public String TargetComponentNames; // 用逗号分隔的发送目标组件列表,运行时从配置项获取. public void OnTearDown() {} public void OnInit() {} // 确定适配器 public String getAdapterType() { return "Finance.PEXInboundAdapter"; } // OnProcessInput根据业务服务的'call interval' 设置会被定期调用. public java.lang.Object OnProcessInput(java.lang.Object messageInput) throws java.lang.Exception { String path = (String)messageInput; File file = new File(path); // 创建scanner对象读取文件. Scanner reader = new Scanner(file); // 实例化请求消息TransactionRequest对象. TransactionRequest request = new TransactionRequest(); // 设置消息属性. request.TransactionAmount = Float.parseFloat(reader.nextLine().split(":")[1]); String tempString = reader.nextLine(); // 解析嵌套的PaymentProfile对象,并赋值给请求消息的PayFrom属性. String[] tempStringArray = tempString.split(":"); String[] PaymentProfile = tempStringArray[1].split("\\|"); request.PayFrom.AccountNumber = Integer.parseInt(PaymentProfile[0]); request.PayFrom.RoutingNumber = Integer.parseInt(PaymentProfile[1]); request.PayFrom.UserName = PaymentProfile[2]; // 解析PaymentProfile对象,并赋值给PayTo属性. tempString = reader.nextLine(); tempStringArray = tempString.split(":"); PaymentProfile = tempStringArray[1].split("\\|"); request.PayTo.AccountNumber = Integer.parseInt(PaymentProfile[0]); request.PayTo.RoutingNumber = Integer.parseInt(PaymentProfile[1]); // 设置剩余属性. request.PayTo.UserName = PaymentProfile[2]; request.FromCurrency = reader.nextLine().split(":")[1]; request.ToCurrency = reader.nextLine().split(":")[1]; reader.close(); // 处理后删除文件. file.delete(); // 获取Split target business component string and send to each component. String[] targetNames = TargetComponentNames.split(","); for (String name : targetNames){ SendRequestAsync(name, request); } return null; } } 2.12 组装互操作产品并进行测试 将这些Java开发的组件组册后,就可以像InterSystems IRIS的本地组件一样使用了。我们将业务操作、业务流程和业务服务依次加入到Production,并配置好相应的配置项: 对于每个业务操作,需要配置一项: 文件路径:输出的文件夹路径 对于业务服务,需要配置两项: InboundFilePath: 监听的汇款请求文件夹路径 TargetComponentNames: 目标业务流程,这里应该填Finance.ProcessPaymentRequest 下面是用于测试的汇款请求文件内容,把它copy到一个文本文件中保存: TransactionAmount:59.43 PayFrom:232422|23532532|TJohnson21 PayTo:24224242|423533453|ERichards55 FromCurrency:USD ToCurrency:USD 启动Production后,可以将测试数据文件copy到业务服务监听到文件夹下。如果成功,应该可以看到这样的消息追踪结果,可以看到,用Java开发的PEX组件运行结果和IRIS自带的组件没有区别: 2.13 需要实现的Java类方法总结 下图总结了用Java开发不同组件时,需要实现的方法,以及这些组件间的调用流程和关系: 完整的规范参见这里。 三 在Java组件中使用Object Script开发的组件 上面是使用Java开发全套互操作产品组件的示例。实际情况下,InterSystems IRIS已经提供了大量适配器、消息和业务组件,而且使用低代码工具 - 例如业务流程建模图形化工具 - 往往更方便,所以通常Java可以使用Object Script开发的大量组件,而无需全部由Java开发。 在低代码开发业务流程时,可以直接在BPL里调用Java PEX开发的业务流程和业务操作,和IRIS本地开发的组件无异。 另外两种典型的用例是Java组件使用Object Script的消息、Java组件使用Object Script的适配器。在Java端使用Object Script类和对象,需要有前面讲的Java外部语言服务器的基础,文档参见这里。 3.1 Java组件使用Object Script的消息 在Java PEX中使用Object Script定义的消息,直接使用IRIS类的反向代理类IRISObject即可。例如在Java PEX业务操作的OnMessage方法中,要获得传入的Object Script消息的属性值,只需要把传入消息对象转换为IRISObject对象,并调用它的getXXX方法获取属性即可,可以这样: @Override public Object OnMessage(Object object) throws Exception { // 处理类型Ens.StringRequest的ObjectScript消息,获取StringValue属性的值 // 使用ObjectScript消息,将Object转换为 IRISObject IRISObject requestObj = (IRISObject)object; 通过IRISObject的getString方法获取它名为StringValue属性的值 String value = requestObj.getString("StringValue"); ... } 那怎么在Java组件中创建新的Object Script消息实例呢?你需要已经建立了IRIS连接的类型为com.intersystems.jdbc.IRIS的实例。 PEX的Java业务组件类和适配器类都继承于Common类,从Common类继承一个公共属性irisHandle,类型为IRISObject。而irisHandle有一个公共属性iris,类型为com.intersystems.jdbc.IRIS。因此可以通过它来创建Object Script消息实例。例如我们要创建一个类型为Ens.StringContainer的响应消息,并给其StringValue属性赋值: @Override public Object OnMessage(Object object) throws Exception { // 处理类型Ens.StringRequest的ObjectScript消息,获取StringValue属性的值 // 使用ObjectScript消息,将Object转换为 IRISObject IRISObject requestObj = (IRISObject)object; String value = requestObj.getString("StringValue"); // 创建一个类型为Ens.StringContainer的ObjectScript响应消息 IRISObject response = (IRISObject)(this.irisHandle.iris.classMethodObject("Ens.StringContainer","%New")); response.set("StringValue",value+"test me"); return response; } 3.2 Java业务组件使用Object Script的适配器 如果Java业务服务使用Object Script的适配器,无需做任何处理,适配器会将数据发送给Java业务服务的OnProcessInput方法,而Java业务服务只需要将接收的数据转换为IRISObject类型进行处理即可。 如果是Java业务操作要使用Object Script适配器,则需要调用适配器的方法。调用适配器方法,可以使用Adapter属性的invoke方法调用适配器类的方法,语法是 Adapter.invoke("方法名", 方法参数),例如: // 使用Object Script的出站文件适配器(EnsLib.File.OutboundAdapter),并调用它的Exists方法检查是否存在文件a.txt Object obj = Adapter.invoke("Exists", "a.txt"); 虽然这里介绍的是使用Java PEX开发互操作产品组件,您也可以使用.net 和Python进行开发,而且任何语言开发的PEX组件都可以一起使用。通过PEX,可以充分利用已有的生态代码和组件快速开发互操作产品。
文章
Hao Ma · 十一月 22, 2023

访问 IRIS 终端:Visual Studio Code 用户综合指南

介绍 由于InterSystems最近宣布从2023.2版本开始停止对InterSystems Studio的支持,转而独家开发Visual Studio Code(VSC)IDE的扩展,相信后者比Studio提供了更优越的体验,我们很多开发者都已切换或开始使用 VSC。很多人可能想知道如何打开终端进行操作,因为VSC没有像Studio那样的输出面板,也没有集成的功能来打开IRIS终端,除非下载InterSystems开发的插件。 概括 介绍 解决方案 对于至少具有 IRIS 2020.1 或 IRIS IRIS 2021.1.2 的用户– 使用 Web 终端 对于至少具有 IRIS 2023.2 的用户 – 使用 WebSocket 终端 对于使用基于 Docker 的 IRIS 的用户 对于在本地计算机上使用 2023.2 之前的 IRIS 版本的用户 对于使用 SSH 连接在基于远程服务器的 IRIS 上进行编码的用户 解决方案 在 VSC 中打开终端的方法有多种,具体取决于您使用的具体配置,我在这里总结了适合任何情况的最佳解决方案: 对于至少具有 IRIS 2020.1.1 或 IRIS 2021.1.2 的用户 – 使用 Web 终端 至少拥有 IRIS 2020.1.1 或 IRIS 2021.1.2 且被允许安装外部扩展的用户(某些人可能由于公司有关第三方应用程序的政策而不允许安装),可能会发现 VSC 的 Web 终端扩展很有用。谁不知道, Web 终端是一个基于 Web 的 InterSystems 产品终端,使用 ObjectScript(例如 IRIS、Caché、Ensemble、HealthShare、TrakCare)构建,允许在浏览器中使用更高级版本的终端( 这里是项目页面)。通过此 VSC 扩展,只需单击一下即可直接从 VSC 启动基于 Web 的终端。 要打开 Web 终端,请单击: InterSystems Tools > 选择一个名称空间 > 单击以下图标之一 ( , )在 VSC 终端面板或浏览器上打开 Web 终端(按 Alt 更改默认图标): 对于至少具有 IRIS 2023.2 的用户 – 使用 WebSocket 终端 至少拥有 IRIS 2023.2 的用户可以利用最新版本的 VSC 扩展中包含的新“ WebSocket 终端”功能,并且不需要其他解决方法。 要打开 WebSocket 终端,请单击: InterSystems Tools > 选择一个名称空间 > 单击 Web 终端旁边的图标。 对于使用基于 Docker 的 IRIS 的用户 在 Docker 中使用 IRIS 环境并使用 VSC 的人员可以直接在 Docker 环境中启动终端会话。 单击状态栏中的 Docker 语音,然后选择Open Terminal in Docker 。 我要感谢@Evgeny.Shvarov 有关这一点的图片和解释。 对于在本地计算机上使用 2023.2 之前的 IRIS 版本的用户 对于使用在本地计算机上运行的 IRIS 版本的用户,可以在 VSC 中设置专用的 IRIS 终端: 打开设置.json 文件。您可以通过多种方式找到它,例如单击“视图”> “命令面板”> 输入:“设置”>打开用户设置 (JSON) 在“ terminal.integrated.profiles.windows ”下添加以下代码: "terminal.integrated.profiles.windows" :{ "IRIS Terminal" : { "path" : [ "C:\\InterSystems\\IRISHealth\\bin\\irissession.exe" ], "args" : [ "IRISHEALTH" ], "icon" : "terminal-cmd" } } 注意:插入irissession.exe的正确路径。 C。要从 VSC 打开终端,请导航至:终端>新终端>启动配置文件... > IRIS 终端。 d.终端菜单中现在应该可以使用“IRIS Terminal”语音: 对于使用 SSH 连接在基于远程服务器的 IRIS 上进行编码的用户 对于使用基于可通过 SSH 连接(例如使用PuTTY )访问的远程服务器(例如公司服务器)的 IRIS 版本的人员来说,可以使用远程 - SSH VSC扩展将 VSC 直接连接到服务器。为此: 安装远程 - SSH:编辑配置文件 VSC 扩展; 单击“远程资源管理器”图标 在侧边栏中; 选择“打开 SSH 配置文件” 并打开配置文件,路径为: C:\Users\<用户名>\.ssh\config 在配置文件中插入以下代码: Host my-putty-connection HostName < IP address or server name > User < username > IdentityFile < private key path on your local machine > Port < port > IP 地址和端口对应于 PuTTY 中指定的主机名和端口,用户名是用于访问远程服务器的用户凭据,IdentityFile 是 PuTTY 私钥的文件路径。 注意:VSC 无法读取 PuTTY (.ppk) 生成的私钥的原始格式。要通过 PuTTY 在 VSC 和远程服务器之间建立连接,您必须复制原始私钥并将新版本转换为 .pem 格式。为了进行转换: 启动 PuTTYgen 应用程序 在“文件”菜单下,单击“加载私钥” 选择 .ppk 格式的私钥,然后选择“打开” 在“转换”菜单下,单击“导出 OpenSSH 密钥”(强制使用新文件格式)。 设置扩展名为 .pem 的新名称,然后单击“保存”按钮。 将此新 .pem 文件的路径链接到 VSC 中的IdentifyFile 参数 保存文件。几秒钟后,新连接应出现在“远程资源管理器”面板中; 单击“在新窗口中连接... ”以在新的 VSC 窗口中打开 SSH 连接: 选择远程计算机的操作系统(仅在第一次访问时) 在新窗口中,导航至:终端>新终端(或使用快捷键 Ctrl + ò 或 Ctrl + Shift + ò)。 您现在已连接到远程计算机,并且可以在 VSC 中使用其 IRIS 终端。 注意:此操作仅在您之前通过 PuTTY 启动远程连接时有效,并且在 PuTTY 关闭或未连接到远程服务器时不起作用。此操作不会启动 PuTTY,它仅允许 VSC 连接到 PuTTY 建立的隧道。 要通过 VSC 启动 PuTTY 连接,您可以使用批处理文件(在 Windows 上)。提供的connect_remote.bat文件使用 PuTTY 附带的 Plink 命令来启动会话: @echo off set SESSION="<your saved session name>" plink -load %SESSION% 要启动会话,只需在 VSC 终端中键入.\connect_remote.bat以打开远程连接并插入您的凭据。 注意:后一种方法使您可以访问支持所有 VSC 快捷方式的终端版本!欢迎回来 Ctrl+V,再见 Shift+Insert 🎉
文章
Michael Lei · 八月 31, 2023

常见问题--如何根据ID重建索引

InterSystems 常见问题解答 通过在持久类(=table)定义中提供的%BuildIndices() 方法的参数中指定要重建索引的 ID 的开始值和结束值,您可以仅重建该范围内的索引。 例如,要仅针对 ID=10 到 20 重建 Sample.Person 类中的 NameIDX 索引和 ZipCode 索引,请执行以下代码(ID 范围在第 5 个和第 6 个参数中指定)。 set status = ##class (Sample.Person). %BuildIndices ( $LB ( "NameIDX" , "ZipCode" ), 1 ,, 1 , 10 , 20 ) $LB() 是$ListBuild() 函数。 %BuildIndices() 方法使用它来指定索引名称。 有关如何重建索引的更多信息,请参阅文档。 2018.1版本请参考此文档。
公告
Michael Lei · 十月 24, 2023

官宣对 CentOS 的支持终止

终止对 CentOS 的支持 自 InterSystems IRIS 2023.3 发布起,CentOS 将不再是受支持的开发平台。 CentOS 一直是一个受支持的开发平台,为开发人员提供了相当于 Red Hat Enterprise Linux (RHEL) 的免费版本,用于 IRIS 开发。您可能知道,Red Hat 对 CentOS 进行了重大更改,CentOS 已成为 RHEL 的“上游”。这意味着它具有 RHEL 中尚未包含的错误和功能,这可能会给在该平台上构建的开发人员带来问题。 我们鼓励使用 CentOS 的开发人员利用 Red Hat 的免费开发人员计划来获得 RHEL 的免费开发许可证。 CentOS 继续支持 IRIS 2023.2(及更早版本)。
文章
Weiwei Gu · 八月 7, 2023

如何自定义 Web 网关错误消息

InterSystems 常见问题解答标题 您可以为以下 Web Gateway 错误消息/系统响应设置单独的错误页面: 服务器错误 服务器繁忙 服务器无法使用 服务器超时 连接关闭 在 Web Gateway 管理界面上进行设置([Management Portal] > [System Administration] > [Configuration] > [Web Gateway Management] > [Configuration] > [Default Parameters])。 在“默认参数”(Default Parameters )菜单的“错误页面”部分中,设置要显示的 html 页面的文件名或发生错误时要重定向到的 URL。 ※Web网关管理界面也可以从以下URL访问。 http://<web server address>:<port>/csp/bin/Systems/Module.cxw 详细信息请参考以下文档自定义错误页面 [IRIS]