#server()#が突然使えなくなるかもしれません
IRISではCSPタグベースの開発は、非推奨(Deplicated)になっています。
非推奨とはいえ、いますぐ使えなくなることはないと思います。
が、CSP機能に含まれるHyperEventの#server()#呼び出しは、かなりやばいということがわかってきました。
これはChromeを始めとするメジャーなブラウザーが提供しているSynchronous XMLHttpRequestという関数を呼び出しています。
この関数をGoogleは10年前くらいから非推奨機能としていて、いつか完全に機能をドロップすると宣言しています。
インターシステムズのドキュメントにもさりげなく記載されています。
とはいえ、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として取得し、クライアントで各コンポーネントを更新するという方法が今時の推奨になります。
Comments
このシンプルな例をREST APIで書き換えるとこんな感じです。
まずはCSPファイルです。
<html>
<body>
<!--フォームの記述-->
<form name="f1">
<input type="text" value="" name="text1">
<input type="button" value="test" onclick="runMyRoutine();">
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- ボタンクリックで最初に呼び出されるJavascript関数 -->
<script language="javascript">
function runMyRoutine() {
axios.get('http://localhost:8080/api/user/getMessage/Hiroshi')
.then(response => {
console.dir(response)
self.document.f1.text1.value = response.data.Message
})
.catch(error => {
console.log(error)
})
}
</script>
</body>
</html>
次に呼び出されるREST APIのクラスです。
Class Samples.API Extends %CSP.REST
{
Parameter CONVERTINPUTSTREAM = 1;
XData UrlMap
{
<Routes>
<Route Url="/getMessage/:name" Method="GET" Call="GetMessage"/>
</Routes>
}
ClassMethod GetMessage(pName As %String) As %Status
{
set status = $$$OK
try {
if $data(%request) {
set %response.ContentType="application/json"
set %response.CharSet = "utf-8"
}
set return = {}
set return.Message = "Hello "_pName
write return.%ToJSON()
}
catch e {
set status = e.AsStatus()
}
quit status
}
}
RESTアプリケーションの設定例.png)
%sessionを使用している場合は、REST APIで書き換えるのは、相当難しいことが判明しました。
(CSPのセッションとRESTのセッションは別物のため)
#callに書き換えるしかなさそうです
cspクラスとして定義し、OnPageメソッドでJSON形式でデータを返すという方式ならば、%sessionを引き継げます。
これをREST APIと言うのは若干抵抗がありますが、そういっても間違いではないでしょう
CSPのセッションとRESTのセッションを共有する方法があることがわかりました。
UseSession=1に設定してCSPのアプリケーション名(/csp/hoge)でセッションクッキーを共有することで%sessionデータを共有できます。