Nueva publicación

Rechercher

Artículo
· 17 hr atrás Lectura de 4 min

#server()#が突然使えなくなるかもしれません

IRISではCSPタグベースの開発は、非推奨(Deplicated)になっています。

非推奨とはいえ、いますぐ使えなくなることはないと思います。

が、CSP機能に含まれるHyperEventの#server()#呼び出しは、かなりやばいということがわかってきました。

これはChromeを始めとするメジャーなブラウザーが提供しているSynchronous XMLHttpRequestという関数を呼び出しています。

この関数をGoogleは10年前くらいから非推奨機能としていて、いつか完全に機能をドロップすると宣言しています。

Stackoverflowの該当記事

インターシステムズのドキュメントにもさりげなく記載されています。

HyperEventCallメソッド

とはいえ、10年もそのままなので、希望的観測をすれば、今後も使える可能性は高いかもしれません。

しかし、ある日突然なくなるリスクはゼロではありません。

ですので、#server()#呼び出しをお手元のコードからなるべく早く取り除くのが賢明です。

それでは、どうすれば良いのか?

ということですが、今のご時世で考えれば、REST APIに変えましょうというのが美しい世界ですが、おそらく書き換えのコストは、半端じゃないでしょう。

ということで、現実的な解は、#Call()#に置き換えることだと思います。

しかし、#call()への書き換えも一筋縄ではいかない可能性をあります。

#serverと#callの最大の違いは、#serverの場合は、戻り値を取得できる点です。

そして、この戻り値を返すようなコーディングをしている場合、書き換えは結構手間がかかる可能性が高いです。

一方、戻り値がなく、呼び出されるメソッド内で処理が完結する場合は、単純な文字列置き換えで済む可能性があります。

最も単純なパターンを考えてみます。

以下は、#server()#の戻り値をテキストボックスの値(value)に直接設定する例です。

<!--フォームの記述-->
<form name="f1">
<input type="text" value="" name="text1">
<input type="button" value="test" onclick="runMyRoutine();">
</form>
<!-- ボタンクリックで最初に呼び出されるJavascript関数 -->
<script language="javascript">
function runMyRoutine() {
self.document.f1.text1.value = #server(..MyMethod('Hiroshi'))#;
}
</script>
<!-- Javascriptの#serverから呼び出されるIRISメソッド -->
<script language="cache" method="MyMethod" arguments="Name:%String" returntype=%String>
Quit "Hello "_Name
</script>

#call()#は戻り値を返せないので、代わりに以下のような形に変更する必要があります。

つまり呼び出されるメソッドの中で&javascript(マクロ or ディレクティブ)を使用して、フォームのコンポーネントに設定する必要があります。

<!--フォームの記述-->
<form name="f1">
<input type="text" value="" name="text1">
<input type="button" value="test" onclick="runMyRoutine();">
</form>
<!-- ボタンクリックで最初に呼び出されるJavascript関数 -->
<script language="javascript">
function runMyRoutine() {
#call(..MyMethod('Hiroshi'))#;
}
</script>
<!-- Javascriptの#callから呼び出されるIRISメソッド -->
<script language="cache" method="MyMethod" arguments="Name:%String" returntype=%String>
&javascript< CSPPage.document.f1.text1.value = 'Hello #(Name)#'; >
Quit "Hello "_Name
</script>

 

実際には、複数の項目をまとめて戻り値として取得し、それをJavascriptで分解して、各コンポーネントに設定するということも行なっている場合には、修正もより複雑になっていく可能性があります。

そして&javascriptの多用は、通信という観点では、非常にコストが高く、特にレイテンシー(応答時間の長さ)のペナルティが大きいです。

WIFI経由でアクセスする要件がある場合は、注意が必要です。

やはり理想的にはREST APIで一般的な非同期通信のお作法に則ったプログラミングを行い、取得するデータはなるべく1つのJSONとして取得し、クライアントで各コンポーネントを更新するという方法が今時の推奨になります。

1 nuevo comentario
Comentarios (1)1
Inicie sesión o regístrese para continuar
Artículo
· 18 hr atrás Lectura de 4 min

ミラー環境のアップグレード手順(メンテナンスリリースバージョン編)

これは InterSystems FAQ サイトの記事です。

こちらの記事では、ミラー環境をメンテナンスリリースバージョン(例:2025.1.0 -> 2025.1.1)にアップグレードする際の手順についてご説明します。

脆弱性の問題の対応などで、最新メンテナンスリリースバージョンへのアップグレードが必要な場合はこちらの方法をご使用ください。

こちらの手順は、「ミラー環境アップグレード中にアプリケーションの変更を伴わない」ことを前提とした手順になります。
こちらのドキュメント にある以下のイメージの、「 Procedure 1: Maintenance Release Upgrades with No Application Changes」の手順です。
※ ミラーが使用できなくなるのは、計画的フェイルオーバーの実行時間のみです。

   

【注意1】
InterSystems IRIS for Health および Health Connect でミラーリングを構成する場合は、HSSYSを必ずミラーリングするようにしてください。また、アップグレードは2024.1以降のバージョンへ行うようにしてください。


【注意2】
ミラーリング構成のInterSystems IRISでは、ジャーナルファイルの互換性を保つため、バックアップメンバーを先に、プライマリを後にアップグレードする必要があります。これは、古いバージョンでは新しい形式のジャーナルファイルを正しくリストアできない可能性があるためです。ジャーナルファイルのリストアは、作成元と同じかそれより新しいバージョンでのみ保証されます。

ジャーナル復元の互換性(アップグレードの影響)

手順は以下のようになります。
もし、DR非同期メンバも構成している場合は、1の前、つまり一番最初に停止&アップグレードを行います。
(手順は、こちら になります)


1.事前準備

2.バックアップ(B) で フェイルオーバーなし を設定

3.バックアップ(B) を停止&アップグレード

4.バックアップ(B) のフェイルオーバーなしをクリア

5.プライマリー(A) をシャットダウン&アップグレード(バックアップ(B) がプライマリとなる)

6.新しいプライマリ(B) をシャットダウン(ミラーがフェイルオーバーし、(A) がプライマリーになる)


 

では、詳しい手順を説明します。

1.事前準備

ミラーモニタで現在の状態を確認します。
アップグレードプロセス全体を通してミラーモニターを使用し、ミラーメンバーのシャットダウン、フェイルオーバー、または再起動を含むステップを実行した場合は、実行後にミラーモニターが変更を正しく反映していることを確認してください。

   
 

2.バックアップ(B) で「フェイルオーバーなし」を設定します

バックアップ(B) が完全にアップグレードされるまでフェイルオーバーが発生しないように、「フェイルオーバーなし」の設定を行います

管理ポータル:
[システムオペレーション] > [ミラーモニタ]

   

ミラーを停止します

   


3.バックアップ(B) を停止&アップグレードします

4.バックアップ(B) のフェイルオーバーなしをクリアします 

ミラーを開始します

   


フェイルオーバーなしをクリアします(フェイルオーバーありの設定に戻します)

   

5.プライマリー(A) をシャットダウン&アップグレードします(バックアップ(B) がプライマリーとなる) 

アップグレード直後

 


6.新しいプライマリ(B) をシャットダウンします(ミラーがフェイルオーバーし、(A) がプライマリーになる)

新しいプライマリ(B) をシャットダウン後、(A) がプライマリとなります

(B) を開始することで、元の構成に戻ります。

これでアップグレード作業は終了です。おつかれさまでした。
 


★非同期DRメンバのアップグレード

1.ミラーを停止します

管理ポータル:
[システムオペレーション] > [ミラーモニタ]
「このメンバ上でミラーを停止」ボタンをクリック

 

2.インスタンスを停止します

3.アップグレードを行います

4.ミラーを開始します

管理ポータル:
[システムオペレーション] > [ミラーモニタ]
「このメンバ上でミラーを開始」ボタンをクリック


詳細は以下のドキュメントをご覧ください。

ミラーのアップグレード
Choosing Mirror Upgrade Procedure

Comentarios (0)0
Inicie sesión o regístrese para continuar
Comentarios (0)1
Inicie sesión o regístrese para continuar
Artículo
· 15 feb, 2026 Lectura de 7 min

How to easily add a validation against OpenAPI specifications to your REST APIs

In this article, I aim to demonstrate a couple of methods for easily adding validation to REST APIs on InterSystems IRIS Data Platform. I believe a specification-first approach is an excellent idea for API development. IRIS already has features for generating an implementation stub from a specification and publishing that specification for external developers (use it with iris-web-swagger-ui for the best results). The remaining important thing not yet implemented in the platform is the request validator. Let's fix it!

The task sounds as follows: all inbound requests must be validated against the schema of the API described in OpenAPI format. As you know, the request contains: method (GET, POST, etc.), URL with parameters, headers (Content-Type, for example), and body (some JSON). All of it can be checked. To solve this task, I will be using Embedded Python because the rich library of open source Python code already has 2 suitable projects: openapi-core, openapi-schema-validator. One limitation here is that the IRIS is using Swagger 2.0, an obsolete version of OpenAPI. Most of the tools do not support this version, so the first implementation of our validator will be restricted to checking the request body only.

Solution based on the openapi-schema-validator

Key inputs:

  • Solution is fully compatible with the recommended InterSystems specification-first way in API development. No need for modifications in the generated API classes, except for the one small, more on this later
  • Checking the request body only
  • We need to extract the definition for the request type from the OpenAPI specification (class spec.cls
  • The matching request JSON to the spec definition is done by setting a vendor-specific content type

First, you need to set a vendor-specific content type in the consumes property of the OpenAPI specification for your endpoint. Which one must look something like this: vnd.<company>.<project>.<api>.<request_type>+json. For example, I will use:

"paths":{
      "post":{
        "consumes":[
          "application/vnd.validator.sample_api.test_post_req+json"
        ],
...

Next, we need a base class for our dispatch class. Here is the full code of this class; the code is also available on Git.

Class SwaggerValidator.Core.REST Extends %CSP.REST
{

Parameter UseSession As Integer = 1;
ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue As %Boolean) As %Status
{
	Set tSC = ..ValidateRequest()
    
    If $$$ISERR(tSC) {
        Do ..ReportHttpStatusCode(##class(%CSP.REST).#HTTP400BADREQUEST, tSC)
        Set pContinue = 0
    }

    Return $$$OK
}

ClassMethod ValidateRequest() As %Status
{
    Set tSC = ##class(%REST.API).GetApplication($REPLACE($CLASSNAME(),".disp",""), .spec)
    Return:$$$ISERR(tSC) tSC

    Set defName = $PIECE($PIECE(%request.ContentType, "+", 1), ".", *)
    Return:defName="" $$$ERROR($$$GeneralError, $$$FormatText("No definition name found in Content-Type = %1", %request.ContentType))
    
    Set type = spec.definitions.%Get(defName)
    Return:type="" $$$ERROR($$$GeneralError, $$$FormatText("No definition found in specification by name = %1", defName))
    
    Set schema = type.%ToJSON() 
    Set body = %request.Content.Read()

    Try {Set tSC = ..ValidateImpl(schema, body)} Catch ex {Set tSC = ex.AsStatus()}

    Return tSC
}

ClassMethod ValidateImpl(schema As %String, body As %String) As %Status [ Language = python ]
{
    try:
        validate(json.loads(body), json.loads(schema))
    except Exception as e:
        return iris.system.Status.Error(5001, f"Request body is invalid: {e}")

    return iris.system.Status.OK()
}

XData %import [ MimeType = application/python ]
{
import iris, json
from openapi_schema_validator import validate
}

}

We are doing the next things here:

  1. Overrides OnPreDispatch() for adding validation. This code will execute for each call of our API
  2. Uses ##class(%REST.API).GetApplication() to get the specification in a dynamic object (JSON)
  3. Extracts the definition name from the Content-Type header
  4. Takes the request schema by definition name: spec.definitions.%Get(defName)
  5. Sends request schema + request body to Python code for validation

As you see, it is all pretty simple. Now all you need to do is change the Extends section of your disp.cls to SwaggerValidator.Core.REST. And of course, install the openapi-schema-validator Python library to the server (as described here).

Solution based on the openapi-core

Key inputs:

  • This solution works with a hand-coded REST interface. We do not use API Management tools to generate the code from the OpenAPI specification. We only have a REST service as a %CSP.REST subclass
  • So, we are not attached to the 2.0/JSON version and will be using OpenAPI 3.0 in YAML format. This version offers more opportunities, and I find YAML more readable
  • The following elements will be checked: path and query parameters in the URL, Content-Type, and request body

For starters, let's take our specification located on <server>/api/mgmnt/v1/<namespace>/spec/<web-application>. Yes, we have a generated OpenAPI specification even for manually coded REST APIs. This is not a complete spec because it has no schemas of requests and responses (the generator does not know where to get them). But the platform has already done half the work for us. Let's put this specification to XData block named OpenAPI in class Spec.cls. Next, we need to convert the specification to OpenAPI 3.0/YAML format and add definitions for request/responses. You can use a converter or just ask Codex:

Please, convert spec in class @Spec.cls to Swagger version 3.0 and YAML format

In the same way, we can ask Codex to generate request/response schemas based on JSON samples.

BTW, vibe coding works pretty well in IRIS development, but it is a subject for a separate topic. Please, let me know if it is interesting for you!

As in the previous solution, we must create a base class for our REST API class. This class is very similar:

Class SwaggerValidator.Core.RESTv2 Extends %CSP.REST
{

Parameter UseSession As Integer = 1;
ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue As %Boolean) As %Status
{
	Set tSC = ..ValidateRequest()
    
    If $$$ISERR(tSC) {
        Do ..ReportHttpStatusCode(##class(%CSP.REST).#HTTP400BADREQUEST, tSC)
        Set pContinue = 0
    }

    Return $$$OK
}

ClassMethod ValidateRequest() As %Status
{
    Set tSC = ..GetSpec(.swagger) 
    Return:$$$ISERR(tSC)||(swagger="") tSC

    Set canonicalURI = %request.CgiEnvs("REQUEST_SCHEME")_"://"_%request.CgiEnvs("HTTP_HOST")_%request.CgiEnvs("REQUEST_URI")
    Set httpBody = $SELECT($ISOBJECT(%request.Content)&&(%request.Content.Size>0):%request.Content.Read(), 1:"")
    Set httpMethod = %request.CgiEnvs("REQUEST_METHOD")
    Set httpContentType = %request.ContentType
    Try {
        Set tSC = ..ValidateImpl(swagger, canonicalURI, httpMethod, httpBody, httpContentType)
    } Catch ex {
        Set tSC = ex.AsStatus()
    }

    Return tSC
}

/// The class Spec.cls must be located in the same package as the %CSP.REST implementation
/// The class Spec.cls must contain an XData block named 'OpenAPI' with swagger 3.0 specification (in YAML format) 
ClassMethod GetSpec(Output specification As %String, xdataName As %String = "OpenAPI") As %Status
{
    Set specification = ""
    Set specClassName = $CLASSNAME()
    Set $PIECE(specClassName, ".", *) = "Spec"
    Return:'##class(%Dictionary.ClassDefinition).%Exists($LISTBUILD(specClassName)) $$$OK
    Set xdata = ##class(%Dictionary.XDataDefinition).%OpenId(specClassName_"||"_xdataName,,.tSC)
    If $$$ISOK(tSC),'$ISOBJECT(xdata)||'$ISOBJECT(xdata.Data)||(xdata.Data.Size=0) {
		Set tSC = $$$ERROR($$$RESTNoRESTSpec, xdataName, specClassName)
	}
    Return:$$$ISERR(tSC) tSC
    
    Set specification = xdata.Data.Read()
    Return tSC
}

ClassMethod ValidateImpl(swagger As %String, url As %String, method As %String, body As %String, contentType As %String) As %Status [ Language = python ]
{
    spec = Spec.from_dict(yaml.safe_load(swagger))
    data = json.loads(body) if (body != "") else None
    headers = {"Content-Type": contentType}
    
    req = requests.Request(method=method, url=url, json=data, headers=headers).prepare()
    openapi_req = RequestsOpenAPIRequest(req)

    try:
        validate_request(openapi_req, spec=spec)
    except Exception as ex:
        return iris.system.Status.Error(5001, f"Request validation failed: {ex.__cause__ if ex.__cause__ else ex}")

    return iris.system.Status.OK()
}

XData %import [ MimeType = application/python ]
{
import iris, json, requests, yaml
from openapi_core import Spec, validate_request
from openapi_core.contrib.requests import RequestsOpenAPIRequest
}

}

What to look out for: a class that contains a specification must be named Spec.cls and located in the same package as your %CSP.REST implementation. Specification class looks like:

Class Sample.API.Spec Extends %RegisteredObject
{

XData OpenAPI [ MimeType = application/yaml ]
{
    ... your YAML specification ...
}
}

To enable validation, you just need to extend your API class by inheriting from SwaggerValidator.Core.RESTv2 and place the Spec.cls file next to it.

That is all that I wanted to tell you about Swagger validation. Please feel free to ask me questions.

Comentarios (0)1
Inicie sesión o regístrese para continuar
Pregunta
· 14 feb, 2026

isc-rest dependency error

I want to implement isc-rest in my new project iris-budget/module.xml at master · oliverwilms/iris-budget

I get this error:

#8 11.30 Building dependency graph...
#8 12.69 ERROR! Could not find satisfactory version of isc.rest in any repositories. Required by: iris-budget 0.0.1: ^2.0.0
#8 ERROR: process "/bin/sh -c iris start IRIS && \tiris session IRIS < iris.script &&     ([ $TESTS -eq 0 ] || iris session iris -U $NAMESPACE \"##class(%ZPM.PackageManager).Shell(\\\"test $MODULE -v -only\\\",1,1)\") &&     iris stop IRIS quietly" did not complete successfully: exit code: 1
 

2 nuevos comentarios
Comentarios (2)2
Inicie sesión o regístrese para continuar