搜索​​​​

清除过滤器
文章
Qiao Peng · 一月 10, 2021

2020线上峰会——第1天数据平台专题会议的精彩回顾

InterSystems 2020线上峰会第二周拉开帷幕。首日专题会议涵盖了大量精彩内容,包括38场主题各异的专题会议。我认为有必要回顾一些重大的公告和谈话要点。 IntegratedML 在正式发布之后公布后global availability for IntegratedML, 本周的多个专题会议都将重点介绍IntegratedML。今天,Thomas Dyar与Baystate Health人口健康项目的业务分析师Joe Cofone进行了交流,讨论InterSystems和Baystate如何利用丰富的Health Insight数据和由IntegratedML构建的预测模型来建立“机器学习沙箱”进而构建应用程序。 如果你错过了本次内容,请查看 "AD000 针对医疗应用的Health Insight& 和IntegratedML展示 ". 明天还将有3场关于IntegratedML的单独会议: "CL006 IntegratedML入门", "DA006 如何使用H2O和IntegratedML", 和 "DA005 使用IntegratedML和DataRobot进行机器学习"! 自适应分析 上周我们还公布了InterSystems IRIS自适应分析, 通过对InterSystems IRIS和IRIS医疗版进行扩展,可为分析最终用户提供更大的灵活性、可扩展性以及更高的效率。 今天有两场会议提供了更多关于这方面的信息。第一场会议简单介绍了计划的方案及其潜在收益,第二场会议对该方案能够解决的问题类型进行了演示和讨论。 我们正在寻找早期采用者,如果您有兴趣,请联系Carmen Logue。明天的会议将涉及更多有关数据仓库 和 商业智能 的信息,敬请关注。 嵌入式Python 上周主题报告中的另一项重要信息是我们在将来会提供嵌入式的Python支持,我们已经对其进行了简要介绍。借助嵌入式Python,IRIS内核可以并排运行Python和ObjectScript,以高速访问Python中的数据,并在Python和ObjectScript之间进行了桥接。其实,我们已经获得了在Objectscript中使用嵌入式Python的经验,包括加载Python库、调用方法和函数等等。我们即将举办一场关于如何在SQL中使用嵌入式Python的分享,欢迎大家观看。如果您有兴趣帮助我们开发嵌入式Python,请通过python-interest@intersystems.com.与我们联系。 Kafka 今天我们还宣布了InterSystems将为具有IRIS互操作性的Apache Kafka提供内置支持。Kafka是世界上扩展性最强(最受欢迎)的流数据服务。企业可以将其应用在消息队列、更改数据捕获等所有事件中。该集成系统支持多种系统架构与IRIS进行互操作,无需使用额外代码实现。 明天的专题会议还将继续介绍Kafka集成相关的话题,因为最新版本的InterSystems API Manager(IAM)同样添加了Kafka插件,可将API流量发布到Kafka主题。我们已经在IAM中很好地演示了开发者门户的增强功能,可以帮助您更加轻松地构建和定制真正适合公司品牌的开发者门户。我们明天将详细介绍IAM。 VS Code - ObjectScript 哇,我们已经介绍了这么多公告了,但我们想说的远不止这些。在上周的主题峰会上,我们正式发布了1.0版本的 Intersystems ObjectScript for Visual Studio Code 插件,将ObjectScript开发引入了市场上最受欢迎的IDE(集成开发环境)平台。该版本可以在所有的操作系统上运行,并支持GitHub和Azure DevOps等客户端源代码控制系统。尤其值得注意的是,这是一项源自开发者论坛的开源项目,InterSystems将和我们的开发者们将持续合作开发该项目。 DEE004 会议对该项目进行了快速概述和简短演示。可以点击此处的演示区域 或在 YouTube上查看更多的演示内容。 In DEE007 在DEE007 会议中,我们的几位产品经理和VS Code – ObjectScript项目管理委员会的两名社区成员一起为大家带来了精彩的现场问答。本周将有更多关于VS Code的内容——请查看 "DEE006 用于ObjectScript的Visual Studio代码:选择IDE/源代码控件组合" 和 "DEE005 用于ObjectScript的Visual Studio代码:服务器端源代码控件". 今天开始的 实战实验室也不可错过。 我们还提供了IntegratedML实战实验室和其他热门话题,例如下面这个话题: FHIR和API管理 FHIR一直是业界的热门话题,也是我们的合作伙伴比较感兴趣的话题,所以我们在许多专题会议中都涵盖了FHIR相关的主题。我们简要介绍了FHIR——FHIR是医疗保健可操作性的新标准,受到了美国政府的大力支持。美国政府通过ONC最终规则,对FHIR进行标准化并禁止信息封锁。英国等其他国家的政府也在授权FHIR参与所有新的数字健康计划。 IAM可妥善处理众多开发事务,例如安全性、日志记录、监视和控制对FHIR资源的访问等,从而简化FHIR应用程序的构建流程。用户可以通过开发门户轻松学习和测试FHIR查询。建议大家观看。 可以通过FHIR搜索查询患者、观察、诊断报告等FHIR资源。语法基于REST,但是必须为每个FHIR资源查找查询参数。使用修饰符和连接(例如 _include和_revinclude)的高级查询有时会出现令人困惑的语法,不过我们构建了一个工具来简化这些查询,从而提高生产效率并减轻初学者的负担。 NLP 在线上峰会的推动下,我们还发布了开源NLP(自然语言处理)库iKnow的1.0版本,现已完全以Python包的形式提供。Aohan和Benjamin在DA010专题会议中对这一激动人心的版本进行了概述及使用介绍,相关演示可在 演示区.查看。 演示区 您可以在线上峰会注册中心主区打开The 演示区 ,并按照自己的节奏观看超过25个的演示。 现场问答 第一天结束时我们进行了现场问答,明后两天也会有现场问答环节。大家可以借此机会,针对专题会议中或上周主题演讲中遇到到的任何问题向我们提问。更多信息请参见: https://community.intersystems.com/post/ask-intersystems-product-managers-live-qa-session-vsummit20 这绝对是忙碌的一天!接下来还有两天的专题会议。如果您还没有注册,现在还为时不晚,您可以点击这里 免费注册。 那么,您今天关注的重点是什么呢?请在下方的评论中告诉我们。 祝好! Jeff
问题
Weiwei Yang · 一月 25, 2021

docker deploy

生产环境要使用80端口访问服务器,采用直接部署程序的方式,是在Linux服务器上同时部署HealthConnect和Apache。类似的现在想要使用Docker技术,在一台服务器上部署了HealthConnect和Apache容器,该如何配置http.conf文件,使80端口的请求转到HealthConnect上呢?如果这种方式不可行,有没有其他方法呢? 你好, 请参考在Openexchange中发布的例子:Example of InterSystems IRIS with external Apache and WebGateway( https://openexchange.intersystems.com/package/iris-webgateway-example)
问题
Wang li · 三月 30, 2021

HealthShare如何实现socket接口开发

大家好,我想咨询下如何实现用HealthShare开发socket的接口,例如开发socket对外的BS,以及socket调用的BO 您好,InterSystem的产品家族都支持直接使用Socket,借助UDP或TCPIP与第三方通信,参考 TCP:https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=GIOD_tcp UDP:https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=GIOD_udp 如果是使用BS或者BO的话,则可以使用IRIS提供的多种适配器按需开发获得,参考 https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=PAGE_interop_protocols 好的,谢谢
问题
郭 恩意 · 九月 5, 2023

执行SQL时报错504

执行SQL语句查询数据时,提示unexpected status code, unable to process HyperEvent:Gateway timeout(504) 您好,方便告知您的联系方式?我们会直接联系您处理问题。 黄嘉 InterSystems 我的电话是:18603816613 Hi 恩意, 这个 504 您是在哪一个界面得到的呢? 是在cache 的网页后台运行查询时候报错,还是使用第三方的客户端比如 jdbc 或者odbc的时候报的错? 是在使用cache 的网页后台运行查询时候报错
文章
Jeff Liu · 三月 15, 2021

iris-analytics-package 上场!

大家好, 现在是九局下半,但在我们的技术世界大赛还留了几手![laugh](https://community.intersystems.com/sites/all/libraries/ckeditor/plugins/smiley/images/teeth_smile.png "laugh") iris-analytics-package 旨在演示各公司可以如何轻松简单地在其软件中利用 InterSystems Analytics 支持。 无论是创建新的简单解决方案,还是使用 OpenExchange 改进现有解决方案。 大多数升级到 InterSystems IRIS 的公司都在利用该工具提供的所有功能;他们了解前沿技术,处于领先地位。 我们在本次竞赛中的方案有着不同的目标,即那些已使用 InterSystems 很长时间,但仍然未挖掘到其全部潜能的公司。 此项目是以其他项目为基础和灵感来创建的。 感谢 @Evgeny.Shvarov @Guillaume.Rongier7183 @Peter.Steiwer * [DeepSeeWeb](https://openexchange.intersystems.com/package/DeepSeeWeb) * [csvgen](https://openexchange.intersystems.com/package/csvgen) * [csvgen-ui](https://openexchange.intersystems.com/package/csvgen-ui) * [AnalyzeThis](https://openexchange.intersystems.com/package/AnalyzeThis) 这些项目一起成就了这个简单的向导。### 导入向导 主页面看起来很简单,涉及的过程也很直接。 正确使用向导需要填写几个字段: 1. 选择 CSV 文件 2. 分隔符 3. 类名称 4. 选择是否要创建多维数据集 5. 多维数据集名称 6. 选择向导是否应创建仪表板示例 为了使创建的内容可视化,我们使用 DeepSeeWeb 来实现。 ### 点击上传按钮后,gif 可能看起来定住了,但原因是记录太多。 选定的 CSV 文件超过 **15Mb**, 导入 **134100 条记录**!![]顺便说一下,此演示的数据集来自人道主义数据交换 - 一站式查找、分享和使用人道主义数据您可以尝试使用同一数据集;CSV 文件位于以下文件夹 iris-analytics-package/data 如果您喜欢这个应用程序,并认为我们值得您投票,请为 **iris-analytics-package** 投上一票! [https://openexchange.intersystems.com/contest/current](http://If%20you%20liked%20the%20app%20and%20think%20I%20deserve%20your%20vote,%20please%20vote%20for%20npm-iris!%20%20laugh%20https://openexchange.intersystems.com/contest/current)
文章
姚 鑫 · 三月 8, 2021

第五章 SQL定义表(三)

# 第五章 SQL定义表(三) # 使用DDL定义表 可以使用标准DDL命令在InterSystems SQL中定义表: InterSystems SQL中可用的DDL命令 - `ALTER`命令 `ALTER TABLE`,`ALTER VIEW` - `CREATE` 命令 `CREATE TABLE`,`CREATE VIEW`,`CREATE INDEX`,`CREATE TRIGGER` - `DROP` 命令 `DROP TABLE`,`DROP VIEW`,`DROP INDEX`,`DROP TRIGGER` 可以通过多种方式执行DDL命令,包括: - 使用动态SQL。 - 使用嵌入式SQL。 - 使用DDL脚本文件。 - 使用ODBC调用。 - 使用JDBC调用。 ## 在嵌入式SQL中使用DDL 在ObjectScript方法或例程中,可以使用嵌入式SQL来调用DDL命令。 例如,以下方法创建一个`Sample.Employee`表: ```java /// d ##class(PHA.TEST.SQL).CreateTable() ClassMethod CreateTable() As %String { &sql(CREATE TABLE Sample.Employee ( EMPNUM INT NOT NULL, NAMELAST CHAR (30) NOT NULL, NAMEFIRST CHAR (30) NOT NULL, STARTDATE TIMESTAMP, SALARY MONEY, ACCRUEDVACATION INT, ACCRUEDSICKLEAVE INT, CONSTRAINT EMPLOYEEPK PRIMARY KEY (EMPNUM))) IF SQLCODE=0 {WRITE "Table created" RETURN "Success"} ELSEIF SQLCODE=-201 {WRITE "Table already exists" RETURN SQLCODE} ELSE {WRITE "Serious SQL Error, returning SQLCODE" RETURN SQLCODE_" "_%msg} } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).CreateTable() Table already exists ``` 调用此方法时,它将尝试创建`Sample.Employee`表(以及相应的`Sample.Employee`类)。如果成功,则将`SQLCODE`变量设置为0。如果失败,则`SQLCODE`包含指示错误原因的SQL错误代码。 这样的DDL命令失败的最常见原因是: - `SQLCODE -99`(违反权限):此错误表明没有执行所需DDL命令的权限。通常,这是因为应用程序尚未确定当前用户是谁。可以使用`$SYSTEM.Security.Login()`方法以编程方式执行此操作: ```java DHC-APP>w $SYSTEM.Security.Login("yx","123456") 0 ``` `SQLCODE -201`(表或视图名称不是唯一的):此错误表明正在尝试使用已经存在的表的名称创建新表。 ## 使用类方法执行DDL 在ObjectScript中,可以使用`Dynamic SQL%SQL.Statement`对象使用`Dynamic SQL`准备和执行DDL命令。 下面的示例定义了一个使用动态SQL创建表的类方法: ```java ClassMethod DefTable(user As %String,pwd As %String) As %Status [Language=objectscript] { DO ##class(%SYSTEM.Security).Login(user,pwd) SET myddl=2 SET myddl(1)="CREATE TABLE Sample.MyTest " SET myddl(2)="(NAME VARCHAR(30) NOT NULL,SSN VARCHAR(15) NOT NULL)" SET tStatement=##class(%SQL.Statement).%New() SET tStatus=tStatement.%Prepare(.myddl) IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT} SET rset=tStatement.%Execute() IF rset.%SQLCODE=0 {WRITE "Created a table"} ELSEIF rset.%SQLCODE=-201 {WRITE "table already exists"} ELSE {WRITE "Unexpected error SQLCODE=",rset.%SQLCODE} } ``` 与嵌入式SQL示例一样,如果当前没有用户登录,则此方法将失败。 ## 通过导入和执行DDL脚本定义表 可以使用`IRIS()`方法从终端会话中交互式地导入InterSystems SQL DDL脚本文件,也可以使用`DDLImport(“ IRIS”)`方法作为后台作业来导入InterSystems SQL DDL脚本文件。此方法可以导入和执行多个SQL命令,使可以使用txt脚本文件来定义表和视图,并用数据填充它们。 如果要将表从另一供应商的关系数据库迁移到InterSystems IRIS,则文本文件中可能包含一个或多个DDL脚本。 InterSystems IRIS提供了几种`%SYSTEM.SQL`方法来帮助将此类表加载到InterSystems IRIS中。可以使用通用的`DDLImport()`方法或特定供应商的`%SYSTEM.SQL`方法。供应商特定的SQL转换为InterSystems SQL并执行。错误和不支持的功能记录在日志文件中。 例如,从ObjectScript命令行加载一个Oracle DDL文件: 1. 使用InterSystems IRIS启动器菜单中的“终端”命令启动终端会话。 2. 切换到希望在其中加载表定义的名称空间: ```java SET $namespace = "MYNAMESPACE" ``` 3. 调用所需的DDL导入方法: ```java DO $SYSTEM.SQL.Oracle() ``` 并按照终端上显示的说明进行操作。 ![image](/sites/default/files/inline/images/1_23.png) # 定义分片表 创建分片表有三个要求。 1. 许可证密钥必须支持分片。使用管理门户,系统管理,许可,许可证密钥显示当前许可证或激活新许可证。 2. 必须在IRIS实例上启用分片。必须具有`%Admin_Secure`特权才能启用分片。使用“管理门户”,“系统管理”,“配置”,“系统配置”,“分片配置”来选择“启用分片”按钮。这使当前的InterSystems IRIS实例可以在分片群集中使用。选择“为任何角色启用此实例”或“仅对碎片主机角色启用此实例”。按确定。重新启动您的InterSystems IRIS实例。 3. 必须在IRIS实例上部署分片群集。此分片群集包含一个分片主名称空间。如果未为分片配置当前名称空间,则尝试定义分片表失败,并显示错误#9319:当前名称空间%1没有配置分片。 然后,可以在Shard Master命名空间中定义一个分片表,该表已定义为分片集群的一部分。可以使用`CREATE TABLE`通过指定分片键来定义分片表。或者,可以创建一个持久化类,该持久化类投影到分片表。 # 通过查询现有表定义表 可以使用`$SYSTEM.SQL.QueryToTable()`方法基于一个或多个现有表来定义和填充新表。指定一个查询和一个新的表名称。现有表名和/或新表名可以是合格的或不合格的。该查询可以包含`JOIN`语法。该查询可以提供列名别名,这些别名将成为新表中的列名。 1. `QueryToTable()`复制现有表的DDL定义,并为其指定指定的新表名。它复制查询中指定的字段的定义,包括数据类型,`maxlength`和`minval / maxval`。它不复制字段数据约束,例如默认值,必需值或唯一值。它不会将引用从字段复制到另一个表。 如果查询指定`SELECT *`或`SELECT%ID`,则将原始表的`RowID`字段复制为数据类型为整数的非必需,非唯一数据字段。 `QueryToTable()`为新表生成唯一的`RowID`字段。如果复制的`RowID`名为`ID`,则生成的`RowID`名为`ID1`。 `QueryToTable()`为此新表创建一个对应的持久化类。持久类定义为DdlAllowed。新表的所有者是当前用户。 不管源表中的这些设置如何,新表都将使用`Default Storage = YES`定义,并且`Supports Bitmap Indices = YES`。 为新表创建的唯一索引是`IDKEY`索引。没有位图范围索引生成。复制字段的索引定义不会复制到新表中。 2. `QueryToTable()`然后使用查询选择的字段中的数据填充新表。它将表格的“范围大小”设置为100,000。它估计`IDKEY`块计数。运行“音调表”以设置实际的“范围大小”和“块计数”,以及每个字段的“选择性”和“平均字段大小”值。 `QueryToTable()`既创建表定义,又用数据填充新表。如果只希望创建表定义,请在查询`WHERE`子句中指定一个不选择任何数据行的条件。例如,`WHERE Age < 20 AND Age > 20`. 下面的示例从S`ample.Person`复制`“名称”`和`“年龄”`字段,并创建一个AVG(Age)字段。这些字段定义用于创建名为`Sample.Youth`的新表。然后,该方法`where Age < 21`. 的那些记录的`Sample.Person`数据填充`Sample.Youth`。`AvgInit`字段包含创建表时所选记录的合计值。 ```java DO $SYSTEM.SQL.QueryToTable("SELECT Name,Age,AVG(Age) AS AvgInit FROM Sample.Person WHERE Age < 21","Sample.Youth",1,.errors) ``` ```java DHC-APP> DO $SYSTEM.SQL.QueryToTable("SELECT Name,Age,AVG(Age) AS AvgInit FROM Sample.Person WHERE Age < 21","Sample.Youth",1,.errors) Preparing query... Creating class... Compiling class... Copying data... ``` ![image](/sites/default/files/inline/images/2_13.png) # 外部表 在InterSystems SQL中,还可以具有“外部表”,这些表在SQL词典中定义但存储在外部关系数据库中。外部表的行为就像它们是本机InterSystems IRIS表一样:可以对它们发出查询并执行`INSERT`,`UPDATE`和`DELETE`操作。 InterSystems SQL网关提供对外部数据库的访问,该网关使用ODBC或JDBC提供透明的连接。 # List表 `INFORMATION.SCHEMA.TABLES`持久类显示有关当前名称空间中所有表(和视图)的信息。它提供了许多属性,包括模式和表名称,表的所有者以及是否可以插入新记录。 `TABLETYPE`属性指示它是基表还是视图。 以下示例返回当前名称空间中所有表和视图的表类型,架构名称,表名称和所有者: ```java SELECT Table_Type,Table_Schema,Table_Name,Owner FROM INFORMATION_SCHEMA.TABLES ``` ![image](/sites/default/files/inline/images/3_11.png) `INFORMATION.SCHEMA.CONSTRAINTTABLEUSAGE`持久类为为当前名称空间中的每个表定义的每个主键(显式或隐式),外键或唯一性约束显示一行。 `INFORMATION.SCHEMA.KEYCOLUMNUSAGE`为定义为当前名称空间中每个表的这些约束之一的一部分的每个字段显示一行。 # 列出列名和数字 可以通过以下四种方式列出指定表的所有列名(字段名): - `GetColumns()`方法。这列出了所有列名和列号,包括隐藏的列。 `ID(RowID)`字段可以隐藏也可以不隐藏。 `x__classname`列始终是隐藏的;除非使用`Final class`关键字定义了持久类,否则它将自动定义。 - 管理门户网站SQL界面(系统资源管理器,SQL)架构内容的“目录详细信息”选项卡。它列出了所有列名和列号(包括隐藏的列)以及其他信息,包括数据类型和指示列是否被隐藏的标志。 - `SELECT TOP 0 * FROM`表名。这将按列号顺序列出所有非隐藏的列名。请注意,由于隐藏的列可以按列号顺序出现在任何位置,因此您无法通过计算这些非隐藏的列名来确定列号。 - `INFORMATION.SCHEMA.COLUMNS`持久类为当前名称空间中每个表或视图中的每个非隐藏列列出一行。 `INFORMATION.SCHEMA.COLUMNS`提供了大量属性,用于列出表和视图列的特征。请注意,`ORDINALPOSITION`与列号不同,因为不计算隐藏字段。 `GetColumns()`方法同时计算隐藏字段和非隐藏字段。 下面的示例使用`INFORMATION.SCHEMA.COLUMNS`列出一些列属性: ```java SELECT TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT,IS_NULLABLE,UNIQUE_COLUMN,PRIMARY_KEY FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='Sample' ``` ![image](/sites/default/files/inline/images/4_7.png) ## GetColumns()方法 要以列号顺序列出表中的列名,可以使用`GetColumns()`方法,如下所示: ```java /// d ##class(PHA.TEST.SQL).GetColumn() ClassMethod GetColumn() { SET stat=##class(%SYSTEM.SQL).GetColumns("Sample.Person",.byname,.bynum) IF stat=1 { SET i=1 WHILE $DATA(bynum(i)) { WRITE "name is ",bynum(i)," col num is ",i,! SET i=i+1 } } ELSE { WRITE "GetColumns()无法找到指定的表" } } ``` `GetColumns()`列出所有已定义的列,包括隐藏的列。如果表引用了嵌入式`%SerialObject`类,则`GetColumns()`首先列出持久性类中的所有列,包括引用`%SerialObject`的属性,然后列出所有`%SerialObject`属性。在下面的`GetColumns()`结果中显示了这一点: ```java DHC-APP>d ##class(PHA.TEST.SQL).GetColumn() name is ID col num is 1 name is Age col num is 2 name is DOB col num is 3 name is FavoriteColors col num is 4 name is Home col num is 5 name is Name col num is 6 name is Office col num is 7 name is SSN col num is 8 name is Spouse col num is 9 name is x__classname col num is 10 name is Home_City col num is 11 name is Home_State col num is 12 name is Home_Street col num is 13 name is Home_Zip col num is 14 name is Office_City col num is 15 name is Office_State col num is 16 name is Office_Street col num is 17 name is Office_Zip col num is 18 ``` 还可以使用此方法确定指定列名的列号,如下所示: ```java /// d ##class(PHA.TEST.SQL).GetColumn1() ClassMethod GetColumn1() { SET stat=##class(%SYSTEM.SQL).GetColumns("Sample.Person",.byname) IF stat=1 { WRITE "Home_State is column number ",byname("Home_State"),! } ELSE { WRITE "GetColumns()无法找到指定的表" } } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).GetColumn1() Home_State is column number 12 ```
文章
姚 鑫 · 九月 16, 2022

第三十四章 在 Windows 上使用 IRIS(一)

# 第三十四章 在 Windows 上使用 IRIS(一) 在 `Microsoft Windows` 平台上管理 `IRIS` 数据平台实例非常简单。可以使用管理门户和 `IRIS` 启动器执行大多数任务。还可以从命令提示符控制 `IRIS` 实例。 本主题使用 `install-dir` 来指代 `IRIS` 安装目录——可以在安装指南的默认安装目录部分找到默认目录。 **注意:不要对 `IRIS IRIS.DAT` 数据库文件使用 `Windows` 文件压缩。 (通过右键单击 `Windows` 资源管理器中的文件或文件夹并选择属性,然后选择高级,然后压缩内容以节省磁盘空间来压缩文件;压缩后,文件夹名称或文件名在 `Windows` 资源管理器中呈现为蓝色。)如果压缩一个`IRIS.DAT` 文件,它所属的实例将无法启动,并出现误导性错误。** # 管理对 `IRIS` 实例的访问 ## `InterSystems` 服务 所有 `IRIS job`和进程都从 `InterSystems` 服务、 `IRIS Controller for ` 运行。 `InterSystems` 服务具有的权限由其关联的 `Windows` 用户帐户决定。当这是本地 `SYSTEM` 帐户时, `IRIS` 可以访问 `Windows` 系统上的所有文件和权限。为了维护一个更安全和限制性更强的环境,应该为服务选择一个仅具有所需权限和访问权限的 `Windows `帐户。 在正常安装和锁定安装中, `IRIS` 创建两个本地用户组来授予对实例的访问权限。当为 `InterSystems` 服务指定一个 `Windows` 用户帐户而不是默认的本地 `SYSTEM` 帐户时 `IRIS` 将该 `Windows` 用户帐户添加到每个组。这些组是: - `IRISServices`,它授予启动、停止和控制 `IRIS` 实例的权限。 - `IRIS_Instance_instancename`,授予对安装树的访问权限——`IRIS` 的安装目录及其所有子目录。 **注意:这些组可能不会授予 `IRIS` 执行某些操作所需的所有权限。要确保 `IRIS` 对安装树之外的所有实例、日志和日志文件具有所需的访问权限,请授予 `IRIS_Instance_instancename` 组对这些文件和包含它们的目录的完全访问权限。如有必要,还可以授予该组额外的权限。** 通常,在安装期间为 <instance-name> 选择 `IRIS` 控制器的 `Windows` 帐户,如安装指南的 `Windows` 用户帐户部分所述。 ## 限制对安装树的访问 默认情况下,任何经过身份验证的 `Windows` 用户都可以访问安装树,这可能是不可取的。以下命令为经过身份验证的用户删除 `Windows` 访问控制条目 (ACE): ```java icacls /remove "NT AUTHORITY\Authenticated Users" ``` 运行此命令后,只有管理员用户或 `IRIS_Instance_instancename` 组中的用户才能访问安装树。 **重要提示:如果不这样做,任何可以登录到主机 `Windows` 系统的用户都可以轻松地修改文件、更改设置或完全禁用 `IRIS` 实例。** 在某些情况下,除了 `IRIS` 控制器用于 ` ` 服务的帐户之外,可能还希望授予另一个 `Windows` 帐户访问安装树的权限。例如,这可能包括运行自动化任务的帐户,或直接登录到 `Windows` 服务器以访问 `IRIS` 的帐户(通过本地终端会话或调用自定义调用可执行文件)。可以通过将任何此类帐户添加到 `IRIS_Instance_instancename` 组来为其提供所需的访问权限。 # 更改 InterSystems 服务帐户 在命令行中输入以下内容以更改用于 `IRIS Controller for `的` Windows` 用户帐户: ```java \bin\IRISinstall.exe setserviceusername ``` 此命令将 `Windows` 用户帐户更改为指定的帐户。它还将用户添加到 `IRISServices` 和 `IRIS_Instance_instancename` 组,并在必要时创建这些组。运行此命令并重新启动 `IRIS` 实例后,该实例将在新指定的 `Windows` 用户帐户下运行。
公告
Qiao Peng · 三月 3, 2021

IAM 1.5.0.9 正式发布

InterSystems API Manager (IAM) 版本1.5已正式发布。 IAM容器,包括从原有IAM版本升级的所有相关工件, 现在可以在 WRC 软件发布网址 组件区下载。 该版本的小版本号是 IAM 1.5.0.9-4。 InterSystems API Manager 1.5 使管理API通讯、与你的环境集成、加载API用户更加容易。它包含很多新特性,包括: 改进的用户体验 新的开发者门户工具 对Kafka connectivity的支持 这个版本基于Kong Enterprise version 1.5.0.9。之前的IAM版本包括一个贴牌版本的Kong Enterprise, 在本版本中的Kong Enterprise不再贴牌。 这个变化让我们可以更快的节奏带给您新的版本,并更有效地利用Kong提供的文档和其它资源。 请在 这里 查看IAM 1.5 的文档。这个文档仅说明IAM特殊的元素。产品中的文档链接直接打开Kong Enterprise的文档。 从IAM 0.34-1 升级需要通过3个中间版本累积升级,在 文档中有详细的说明。 IAM 仅以OCI (Open Container Initiative) 或 Docker 容器格式发放。容器镜像可运行在Linux x86-64 和 Linux ARM64的OCI 兼容的运行引擎上, 详情请参考 支持的平台。 Best Regards, Stefan 欢迎开发者们多关注!
公告
Claire Zheng · 三月 18, 2021

Global Masters的成员们,即日起在社区发布帖子和译文贴可获得两倍积分!

中文社区的开发者们,大家好! 我们调整了开发者社区的积分规则,将其调整为双倍积分!自2021年3月18日起,如果您在社区贡献了文章或问题,将获得: 在英文社区获得200积分在西语、葡语、日语和中文社区将获得400积分* 针对译文帖子,将获得100积分 另外,你还可以从特定文章/评论中获得更多积分,详见下表: 第1篇文章 第5篇文章 第10篇文章 第25篇文章 第50篇文章 1,500 分 7,500 分 15,000 分 40,000 分 75,000分 第1个问题 第5个问题 第10个问题 第25个问题 第50个问题 500 分 2,000 分 5,000 分 15,000 分 30,000 分 而且你将可以获得奖励徽章!在 这篇文章里, 你可以看到对应等级和徽章(把鼠标放在徽章上查看如何获得)。 *我们将在一段时间内提升西语/葡语/中文/日语社区的积分 更多关于Global Masters倡导中心的信息: 如何加入InterSystems Global Masters倡导中心? Global Masters徽章:规则解读 如果您还没有加入InterSystems Global Masters倡导中心 , 现在就加入吧! 如果您有任何疑问,欢迎跟帖回复!
问题
Liang Jianhui · 六月 13, 2022

HealthShare Patient Index

在找 HealthShare Patient Index 的相关视频和资料,求分享,谢谢 https://learning.intersystems.com/course/view.php?id=632, 更多视频欢迎在learning.intersystems.com 上搜索即可。谢谢! Hi @Liang.Jianhui , 可以参考这个页面的内容:https://www.intersystems.cn/interoperability-platform/patient-index 社区里也有很多:https://community.intersystems.com/smartsearch?search=patient+index,需要哪片文章可以告诉我们,我们可以帮忙翻译。 Only members of audience '1.0 HealthShare Content Access' can self-enrol. 这种情况是我没有权限吗?需要怎么做才能有权限? 你好!您是在点击这个链接:https://learning.intersystems.com/course/view.php?id=632时出现的问题吗?你需要先试着注册一下才能获取权限。如果还是不行,可以告诉我需要查看的资料,我看怎么分享您。谢谢! 你好,我是点击链接之后进入的,也进行了注册登录。 注册登录之后,仍然没有权限。Only members of audience '1.0 HealthShare Content Access' can self-enrol. 还是出现这个提示。我想了解HSPI 在interSystems系统中是如何应用的,以及worklist是怎么生成链接的。谢谢。 您提到的这个部分是需要WRC权限才可以观看的,WRC是我们的全球响应中心服务账户,您可以参考如下信息获取WRC支持: InterSystems全球响应中心(WRC)联络信息 电话: +86 400-601-9890 邮件: support@intersystems.com 网站: https://wrc.intersystems.cn/ https://wrc.intersystems.com
公告
Michael Lei · 二月 21, 2022

欢迎大家为中国参赛者Wu Fatian 踊跃投票!

投票三部曲: 1. 注册用户或登陆; 2. 成为社区活跃者获取投票资格 3. 投票 good! 欢迎大家把对我们的需求发表在讨论区: intersystems-产品学习使用问题经验分享讨论区--https://cn.community.intersystems.com/post/intersystems-%E4%BA%A7%E5%93%81%E5%AD%A6%E4%B9%A0%E4%BD%BF%E7%94%A8%E9%97%AE%E9%A2%98%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E8%AE%A8%E8%AE%BA%E5%8C%BA 这个绿色的 vote的 button 并不工作,试试这个链接 https://openexchange.intersystems.com/contest/21 it is a screenshot.... 点击查看 最新投票规则,在英文原帖的评论区我们的工作人员会每天更新排名,欢迎关注:D 暂时群众投票排名第一,@Fatian Wu加油! Expert Nomination, Top 3 appmsw-sql2xlsx by @Sergey Mikhailenko iris-python-dashboards by @Evgeniy Potapov DIMSE Iris Dicom Fhir Service by @Ron Sweeney ➡️ Voting is here. Community Nomination, Top 3 IRIS-Database-and-Machine-Learning-Based-Approaches-for-Prediction-of-Spontaneous-Intracerebral-Hemo by @Fatian Wu iris-python-dashboards by @Evgeniy Potapov appmsw-sql2xlsx by @Sergey Mikhailenko ➡️ Voting is here. Experts, we are waiting for your votes! 🔥 Participants, improve & promote your solutions! 武同学仍然排名第三,加油! Expert Nomination, Top 3 django-iris by @Dmitry Maslennikov appmsw-sql2xlsx by @Sergey Mikhailenko iris-python-dashboards by @evgeniy Potapov ➡️ Voting is here. Community Nomination, Top 3 django-iris by @Dmitry Maslenniko appmsw-sql2xlsx by @Sergey Mikhailenko IRIS-Database-and-Machine-Learning-Based-Approaches-for-Prediction-of-Spontaneous-Intracerebral-Hemo by @Fatian Wu
问题
jingwei lu · 三月 16, 2022

如何获得WRC网站登录权限

因为最近再研究Cache,发现Cache安装程序官方上找不到了,又从一个帖子上看到Cache安装程序在WRC上面有,话说这个WRC账号是不是类似于Oracle的MOS账号? 我从官网机器人那得到指示给support@intersystems.com发邮件,可能是因为塑料英语,石沉大海了。另外我想问问这个账号是不是只对那些买了产品或服务的客户单位公开? 请哪位大神为我指点迷津,谢谢 是的,WRC主要面向我们在服务有效期内的客户,请把您的单位名称写在邮件里,邮件也可以支持中文的,没有问题。谢谢! 既然是再研究,何不试试我们最新的InterSystems IRIS。如果以前研究过Caché 会发现,IRIS 还是同样的架构、同样的开发语言、同样的global存储,只是人机交互更流畅、性能更快,增加更多扩展,机器学习、python、丰富的外部BI工具适配、容器化部署、API管理等等等等,都等着你探索。 要想体验就在社区主页左边,选择下载InterSystems IRIS。 WRC可以说是我们对客户的支持中心,所以只面对我们的客户开放注册。
问题
Liang Jianhui · 八月 24, 2022

log文件内容存储到DB中

现在有一个需求。想将intersystems系统产生的alerts.log文件的内容保存到一个表中。有什么工具或者API 能自动格式化log文件到DB吗,还是需要手动解析log文件然后在存储到DB中。 这是两件事:1. 把log里的记录结构化。 2. 保存到DB。 关于1,如果你用的是最新的iris版本, 可以直接拿到结构化的log, 看这个链接: https://docs.intersystems.com/iris20221/csp/docbook/Doc.View.cls?KEY=ALOG 如果是老版本没有结构化,您得自己去做文本处理。好在这个log非常简单。比如下面两行: 08/30/22-11:03:57:775 (6964) 2 [Utility.Event] Previous system shutdown was abnormal, system forced down or crashed. Fast shutdown complete.08/30/22-11:03:59:541 (7716) 2 [Utility.Event] Preserving journal files c:\intersystems\hcdemo\mgr\journal\20220824.002 and later for journal recovery and transaction rollback如果您要只是把日期时间,警告类型,级别,内容分开,它基本就是分开的,用的是空格。 如果您想把内容页结构化,这就花功夫了, 我上面的链接里的工具也不做这个事。 2. 存入DB您得自己解决,IRIS提供文本,API, 没有SQL查询,好在有一大堆监控工具都干这事,就是监控文本文件写入数据库。
文章
Qiao Peng · 一月 31, 2024

用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 · 一月 15, 2021

IAM实践指南——OAuth 2.0下的API保卫战(第一部分)

介绍 目前,诸多应用程序通过开放授权框架(OAuth)来安全、可靠、高效地访问各种服务中的资源。InterSystems IRIS目前已兼容OAuth 2.0框架。事实上社区有一篇关于OAuth 2.0和InterSystems IRIS的精彩文章,链接如下。 然而,随着API管理工具的出现,一些组织开始将其用作单点身份验证,从而防止未经授权的请求到达下游服务,并将授权/身份验证复杂性从服务本身分离出来。 您可能知道,InterSystems已经推出了自己的API管理工具,即InterSystems API Management (IAM),以IRIS Enterprise license(IRIS Community版本不含此功能)的形式提供。这里是社区另一篇介绍InterSystems AIM的精华帖。 这是三篇系列文章中的第一篇,该系列文章将展示如何在OAuth 2.0标准下使用IAM简单地为IRIS中的未经验证的服务添加安全性。 第一部分将介绍OAuth 2.0相关背景,以及IRIS和IAM的初始定义和配置,以帮助读者理解确保服务安全的整个过程。 本系列文章的后续部分还将介绍两种使用IAM保护服务的可能的场景。在第一种场景中,IAM只验证传入请求中的访问令牌,如果验证成功,则将请求转发到后端。在第二种场景中,IAM将生成一个访问令牌(充当授权服务器)并对其进行验证。 因此,第二篇将详细讨论和展示场景1中的配置步骤,第三篇将讨论和演示场景2中的配置以及一些最终要考虑的因素。 如果您想试用IAM,请联系InterSystems销售代表。 OAuth 2.0背景 每个OAuth 2.0授权流程基本上都由4个部分组成: 用户 客户端 授权服务器 资源所有者 简单起见,本文使用“资源所有者密码凭证”OAuth流(可以在IAM中使用任何OAuth流)。另外,本文将不指定任何使用范围。 注意:因为资源所有者密码凭证流直接处理用户凭证,所以应该只在客户端应用程序高度受信任时使用。在大多数情况下,客户端应为第一方应用程序。 通常,资源所有者密码凭证流遵循以下步骤: 用户在客户端应用程序中输入凭证(如用户名和密码) 客户端应用程序将用户凭证和自身的标识(如客户端ID和客户端密钥)一起发送到授权服务器。授权服务器验证用户凭证和客户端标识,并返回访问令牌 客户端使用令牌访问资源服务器上的资源 资源服务器首先验证收到的访问令牌,然后再将信息返回给客户端 考虑到这种情况,你可以在两种场景下使用IAM应对OAuth 2.0: IAM充当验证器,验证客户端应用程序提供的访问令牌,仅在访问令牌有效时才将请求转发给资源服务器;在这种情况下,访问令牌将由第三方授权服务器生成 IAM既充当授权服务器(向客户端提供访问令牌),又充当访问令牌验证器,在将请求重定向到资源服务器之前验证访问令牌。 IRIS和IAM初始定义和配置 本文中使用名为“/SampleService”的IRIS Web应用程序。从下面的截屏中可以看到,这是一个在IRIS中部署的未经身份验证的REST服务: 此外,在IAM端配置了一个名为“SampleIRISService”的服务,其包含一个路由,如以下截屏所示: 再者,在IAM中配置了一个名为“ClientApp”的客户端(初始没有任何凭据),用来识别谁在调用IAM中的API: 经上述配置,IAM将发送到以下URL的每个GET请求代理到IRIS: http://iamhost:8000/event 此时还没有使用身份验证。所以,如果将一个简单的GET请求(未进行身份验证)发送到URL: http://iamhost:8000/event/1 我们将获得期望的响应。 本文中,我们使用名为“PostMan”的应用程序发送请求并检查响应。在下面的PostMan截屏中,可以看到简单的GET请求及其响应。 请继续阅读本系列的第2篇,了解如何配置IAM来验证传入请求中的访问令牌。