Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
iijimam committed Oct 23, 2020
0 parents commit 32cdcd6
Show file tree
Hide file tree
Showing 19 changed files with 769 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"objectscript.conn": {
"server": "test",
"active": true,
"ns": "USER"
},
"intersystems.servers": {
"test": {
"webServer": {
"scheme": "http",
"host": "localhost",
"port": 52773
},
"username": "_SYSTEM"
},
"test2":{
"webServer": {
"scheme": "http",
"host": "localhost",
"port":52776
},
"username": "_SYSTEM"
}
}
}
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#イメージのタグはこちら(https://hub.docker.com/_/intersystems-iris-data-platform)でご確認ください
ARG IMAGE=store/intersystems/iris-community:2020.1.0.215.0
ARG IMAGE=store/intersystems/iris-community:2020.2.0.211.0
ARG IMAGE=store/intersystems/iris-community:2020.4.0.521.0
ARG IMAGE=store/intersystems/iris-community:2020.3.0.221.0
FROM $IMAGE

USER root
RUN apt-get update
RUN apt-get -y install locales && \
localedef -f UTF-8 -i ja_JP ja_JP.UTF-8

# jdbc related
RUN DEBIAN_FRONTEND=noninteractive apt -y install openjdk-8-jre \
&& apt clean

###########################################
#### Set up the irisowner account and load application
USER ${ISC_PACKAGE_MGRUSER}


ENV SRCDIR=/irisdev/src
COPY ./src $SRCDIR/

RUN iris start $ISC_PACKAGE_INSTANCENAME \
&& printf 'Do ##class(Config.NLS.Locales).Install("jpuw") Do ##class(Security.Users).UnExpireUserPasswords("*") h\n' | iris session $ISC_PACKAGE_INSTANCENAME -U %SYS \
&& printf 'Set tSC=$system.OBJ.Load("'$SRCDIR'/Installer.cls","ck") Do:+tSC=0 $SYSTEM.Process.Terminate($JOB,1) h\n' | iris session $ISC_PACKAGE_INSTANCENAME -U %SYS \
&& printf 'set tSC=##class(ZSelflearning.Installer).RunInstall("'$SRCDIR'") Do:+tSC=0 $SYSTEM.Process.Terminate($JOB,1) h\n' | iris session $ISC_PACKAGE_INSTANCENAME -U %SYS \
&& iris stop $ISC_PACKAGE_INSTANCENAME quietly
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Interoperability(相互運用性)を使ってみよう
このGitでは、InterSystems IRIS / InterSystems IRIS for Health の Interoperability メニューの使い方をサンプルを利用しながら確認できるコンテナを提供しています。
このサンプルのコンテナは、[InterSystems IRIS Community Editionのイメージ](https://hub.docker.com/_/intersystems-iris-data-platform)を使用しています(Pullできない場合はイメージ、タグ名をご確認ください)。
[Intersystems IRIS for Health の Community Edition のイメージ](https://hub.docker.com/_/intersystems-iris-for-health)もあります。お好みでイメージを切り替えてご利用ください。

この他、JDBCでの接続が行えるように OpenJDK もインストールしています。
詳細は、[Dockerfile](./Dockerfile) をご参照ください。


## [コミュニティ](https://jp.community.intersystems.com)にサンプルについての解説を記述しています。
索引ページ:https://jp.community.intersystems.com/node/483021



## ディレクトリ/サンプルファイルについて
サンプルファイルについて詳細は以下の通りです。

|種別|ファイル|説明|
|:--|:--|:--|
|ビジネス・サービス|[FileBS.cls](/src/Start/FileBs.cls)|ファイルインバウンドアダプタを利用したビジネス・サービスクラス|
|ビジネス・サービス|[WebServiceBS.cls](/src/Start/WS/WebServiceBS.cls)|Webサービス用のビジネス・サービスクラス|
|ビジネス・サービス|[NonAdapterBS.cls](/src/Start/NonAdapterBS.cls)|アダプタを使用しないビジネス・サービスクラス(ストアドプロシージャ/RESTから呼び出すときに使用する)|
|ビジネス・プロセス|[WeatherCheckProcess.cls](/src/Start/WeatherCheckProcess.cls)|お天気APIとデータベースの更新処理を順序を守って実行するビジネス・プロセスクラス|
|ビジネス・オペレーション|[GetKionOperation.cls](/src/Start/GetKionOperation.cls)|お天気APIにアクセスして指定する都市の天気情報を取得するビジネス・オペレーションクラス|
|ビジネス・オペレーション|[InsertOperation.cls](/src/Start/InsertOperation.cls)|IRIS内データベースにINSERTを実行するビジネス・オペレーションクラス(コンテナ開始時このクラスを利用しています)|
|ビジネス・オペレーション|[SQLInsertOperation.cls](/src/Start/SQLInsertOperation.cls)|SQLアウトバウンドアダプタを利用したビジネス・オペレーションクラス(コンテナ開始時JDBCで接続できるように設定されています)|
|メッセージ|[Request.cls](/src/Start/Request.cls)|プロダクション内で使用する要求(リクエスト)メッセージクラス|
|メッセージ|[Response.cls](/src/Start/Response.cls)|プロダクション内で使用する応答(レスポンス)メッセージクラス|
|プロダクション|[Production.cls](/src/Start/Production.cls)|管理ポータルで設定する定義を保存しているプロダクション用クラス(このクラスの修正は管理ポータルで行います)|
|データ登録用クラス|[WeatherHistory.cls](/src/Start/WeatherHistory.cls)|データ登録用クラス(テーブル)で取得した天気の情報と購入商品名を登録するテーブル|
|インストーラー用クラス|[Installer.cls](/src/Installer.cls)|コンテナビルド時に初期実行する内容を含めたインストーラークラス メモ:[インストーラーについて](https://docs.intersystems.com/iris20201/csp/docbookj/DocBook.UI.Page.cls?KEY=GCI_manifest)|


## コンテナ起動までの手順
詳細は、[docker-compose.yml](./docker-compose.yml) をご参照ください。

Git展開後、**./ は コンテナ内 /irisdev/app ディレクトリをマウントしています。**
また、IRISの管理ポータルの起動に使用するWebサーバポートは 52773 が割り当てられています。

```
git clone このGitのURL
```
cloneしたディレクトリに移動後、以下実行します。

```
$ docker-compose build
```
ビルド後、コンテナを開始します。
```
$ docker-compose up -d
```
コンテナを停止する方法は以下の通りです。
```
$ docker-compose stop
```

## プロダクションのデータを送信してみる
コンテナ開始後、以下のURLにアクセスします。ユーザ名(_system)とパスワード(SYS)を指定してログインします。
http://localhost:52773/csp/sys/UtilHome.csp

管理ポータル > [Interoperability] > [構成] > [プロダクション] を開きます。

(コンテナ作成時にプロダクション:Start.Production を自動起動する設定としているためプロダクションは開始しています)

また、コンテナ作成時に REST 用のベース URL(/start)が設定されています。
以下URLにアクセスしてプロダクションにデータを送信します。
例)
http://localhost:52773/start/weather/ちくわ/豊橋市

正しく情報が送信できると、以下の文字列が表示されます。
{"Message":"天気情報確認:依頼しました","Status":1}

天気を取得し、データベースに登録できているかどうかは、メッセージの参照とStart.WeatherHistoryテーブルを参照して確認します。

メッセージの確認:
管理ポータル > [Interoperability] > [表示] > [メッセージ] を開き「ソース」欄に「Start.NonAdapterBS」が表示されている行を探し、セッション番号をクリックしてトレースを確認します。

テーブルデータの確認:
管理ポータル > [システムエクスプローラ] > [SQL] > ネームスぺースUSERに変更 > スキーマ:Start > テーブル:WeatherHistory > 画面右端「テーブルを開く」クリック
15 changes: 15 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3.6'
services:
iris:
build:
context: .
dockerfile: Dockerfile
container_name: selflearning-interoperability
restart: always
ports:
- 1972:1972
- 52773:52773
- 53773
volumes:
- ~/iris.key:/usr/irissys/mgr/iris.key
- ./src:/irisdev/src
63 changes: 63 additions & 0 deletions src/Installer.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Class ZSelflearning.Installer
{

XData MyManifest [ XMLNamespace = INSTALLER ]
{
<Manifest>
<Namespace Name="USER" Create="no">
<Import File="${SRCDIR}/Start" Flags="ck" Recurse="1" />
<Invoke Class="Ens.Director" Method="SetAutoStart" CheckStatus="true">
<Arg Value="Start.Production"/>
</Invoke>
</Namespace>
</Manifest>
}

ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]
{
#; XGL ドキュメントでこのメソッドのコードを生成する.
Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "MyManifest")
}

/// REST用ベースURL /start の設定(ディスパッチクラス:Start.REST)と
/// SQLゲートウェイの設定 と
/// SSL構成の設定 
ClassMethod RunInstall(dir As %String) As %Status
{
#dim ex As %Exception.AbstractException
set status=$$$OK
try {
set var("SRCDIR")=dir
set status=..setup(.var)
$$$THROWONERROR(ex,status)
set webName = "/start"
set webProperties("DispatchClass") = "Start.REST"
set webProperties("NameSpace") = "USER"
set webProperties("Enabled") = 1
set webProperties("AutheEnabled") = 64
set webProperties("MatchRoles")=":%All"
set status = ##class(Security.Applications).Create(webName, .webProperties)
$$$THROWONERROR(ex,status)

// JDBCを利用するSQLゲートウェイの設定
set jdbcgw=##class(%Library.SQLConnection).%New()
set jdbcgw.Name="IRIS1"
set jdbcgw.URL="jdbc:IRIS://localhost:1972/USER"
set jdbcgw.Usr="_SYSTEM"
set jdbcgw.classpath=".:/usr/irissys/dev/java/lib/JDK18/intersystems-jdbc-3.2.0.jar"
set jdbcgw.driver="com.intersystems.jdbc.IRISDriver"
set jdbcgw.isJDBC=1
set jdbcgw.pwd="SYS"
set status=jdbcgw.%Save()
$$$THROWONERROR(ex,status)
// SSL構成の追加
set status=##class(Security.SSLConfigs).Create("openweather")
$$$THROWONERROR(ex,status)
}
catch ex {
set status=ex.AsStatus()
}
quit status
}

}
34 changes: 34 additions & 0 deletions src/Start/FileBS.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Class Start.FileBS Extends Ens.BusinessService
{

Parameter ADAPTER = "EnsLib.File.InboundAdapter";

/// ファイルインバウンドアダプタの例<br>
/// 入力ファイルには、1行1リクエストで 購入商品名,天気を調査する都市名 を記入する<br>
/// 例)<br>
/// 雪見だいふく,札幌市 <br>
/// ちくわ,豊橋市 <br>
///  野沢菜,長野市 <br>
///
Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %RegisteredObject) As %Status
{
set st=$$$OK
#dim ex As %Exception.AbstractException
try {
// AtEndプロパティがに1が設定されない限りループしながら1行ずつ実行する
while '(pInput.AtEnd) {
set record=pInput.ReadLine()
set request=##class(Start.Request).%New()
set request.Product=$piece(record,",",1)
set request.Area=$piece(record,",",2)
set st=..SendRequestAsync("Start.WeatherCheckProcess",request)
$$$THROWONERROR(ex,st)
}
}
catch ex {
set st=ex.AsStatus()
}
Quit st
}

}
89 changes: 89 additions & 0 deletions src/Start/GetKionOperation.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
Class Start.GetKionOperation Extends EnsLib.REST.Operation
{

Parameter ADAPTER = "EnsLib.HTTP.OutboundAdapter";

Property Adapter As EnsLib.HTTP.OutboundAdapter;

Parameter INVOCATION = "Queue";

/// APIキーを指定します
Property appid As %String;

Parameter SETTINGS = "appid:OpenWeatherMap";

/// お天気APIを利用
/// 例)https://api.openweathermap.org/data/2.5/weather?appid=c2d335870321c22878a9317fdb2cce5a&units=metric&q=国分寺市&lang=ja
/// https://openweathermap.org/current
/// クエリパラメータの units(units=metic は摂氏で返送)と lang(lang=ja)はコードで設定
/// クエリパラメータの q は調べる天気の地名やコード
/// Osakaまたは大阪市、Tokyoまたは東京都、Shinjukuまたは新宿区など
/// 国コードでも指定可 https://ja.wikipedia.org/wiki/ISO_3166-1
/// apiid c2d335870321c22878a9317fdb2cce5a (自分で取得する必要有)
/// HTTP応答の dt には Unix UTCの時間
Method GetKion(pRequest As Start.Request, Output pResponse As Start.Response) As %Status
{
#dim ex As %Exception.AbstractException
#dim tHttpResponse As %Net.HttpResponse
set st=$$$OK
try {
set queryparameter="?units=metric&lang=ja&q="_pRequest.Area_"&appid="_..appid
//set queryparameter="?units=metric&lang=ja&q="_pRequest.Area_"&appid=c2d335870321c22878a9317fdb2cce5a"
set URL=..Adapter.URL_queryparameter
$$$TRACE(URL)
set st=..Adapter.GetURL(URL,.tHttpResponse)

// アダプタからエラーが返り、%Net.HttpResponseのオブジェクトが存在し
// %Net.HttpResponseのDataプロパティがオブジェクトの場合はStreamであり、その場合にSizeが0でないときに
// 全エラーメッセージを文字列に変換し、ステータスエラーを作成する。
If $$$ISERR(st)&&$IsObject(tHttpResponse)&&$IsObject(tHttpResponse.Data)&&tHttpResponse.Data.Size {
Set st=$$$ERROR($$$EnsErrGeneral,$$$StatusDisplayString(st)_":"_tHttpResponse.Data.Read())
}
$$$THROWONERROR(ex,st)
If $IsObject(tHttpResponse) {
set pResponse=##class(Start.Response).%New()
//JSONオブジェクトに変換(tHttpResponse.Dataにはストリームが格納されています)
set weatherinfo={}.%FromJSON(tHttpResponse.Data)
set pResponse.AreaDescription=weatherinfo.weather.%Get(0).description
set pResponse.KionMax=weatherinfo.main."temp_max"
set pResponse.KionMin=weatherinfo.main."temp_min"
set pResponse.Area=weatherinfo.name
//UTC時間なので日本時間にするために9時間(9*60*60)足す
set unixEpochFormat=weatherinfo.dt+32400
set dt=$system.SQL.Functions.DATEADD("s",unixEpochFormat,"1970-01-01 00:00:00")
set pResponse.AreaPublicTime=dt
}
}
catch ex {
set st=ex.AsStatus()
}

Quit st
}

/// UNIXエポックタイム→内部日付への変換
ClassMethod fromUnixToHorolog(unixEpochFormat) As %String
{
// UTC時間なので日本時間に変更のため9時間足す
/*set unixEpochFormat=unixEpochFormat+(9*60*60)
set unixEpochInDays = unixEpochFormat\86400
set remainderSeconds = unixEpochFormat#86400
set epochStartDayHorolog = $zdh("01/01/1970")
set daysSinceHorologStart = epochStartDayHorolog + unixEpochInDays
return daysSinceHorologStart_","_remainderSeconds
*/
//UTC時間なので日本時間にするために9時間(9*60*60)タス
set unixEpochFormat=unixEpochFormat+32400
return $system.SQL.Functions.DATEADD("s",unixEpochFormat,"1970-01-01 00:00:00")
}

XData MessageMap
{
<MapItems>
<MapItem MessageType="Start.Request">
<Method>GetKion</Method>
</MapItem>
</MapItems>
}

}
50 changes: 50 additions & 0 deletions src/Start/InsertOperation.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
Class Start.InsertOperation Extends Ens.BusinessOperation
{

Parameter INVOCATION = "Queue";

Method Insert(pRequest As Start.InsertRequest, Output pResponse As Ens.Response) As %Status
{
set st=$$$OK
#dim ex As %Exception.AbstractException
try {
// /* objectで更新する場合 */
/*
set obj=##class(Start.WeatherHistory).%New()
set obj.Product=pRequest.Product
set obj.Area=pRequest.WeatherInfo.Area
set obj.AreaDescription=pRequest.WeatherInfo.AreaDescription
set obj.AreaPuclicTime=pRequest.WeatherInfo.AreaPublicTime
set obj.KionMin=pRequest.WeatherInfo.KionMin
set obj.KionMax=pRequest.WeatherInfo.KionMax
$$$THROWONERROR(ex,obj.%Save())
*/
// /* SQLで更新する場合*/
set cols(2)=pRequest.WeatherInfo.Area
set cols(3)=pRequest.WeatherInfo.AreaDescription
set cols(4)=pRequest.WeatherInfo.AreaPublicTime
set cols(6)=pRequest.WeatherInfo.KionMax
set cols(7)=pRequest.WeatherInfo.KionMin
set cols(8)=pRequest.Product
&sql(insert into Start.WeatherHistory values :cols())
if SQLCODE<0 {
throw ##class(%Exception.SQL).CreateFromSQLCODE(SQLCODE,%msg)
}
}
catch ex {
set st=ex.AsStatus()
}
Quit st
}

XData MessageMap
{
<MapItems>
<MapItem MessageType="Start.InsertRequest">
<Method>Insert</Method>
</MapItem>
</MapItems>
}

}
Loading

0 comments on commit 32cdcd6

Please sign in to comment.