대체 IRIS 메시지 뷰어 구축
이 글Dashboard IRIS History Monitor을 발표한 후에 나는 좋은 피드백과 요청을 받았다.하나의 요청은 증강된 메시지 뷰어입니다.
만약 네가 아직 이렇게 하지 않았다면, 이 프로젝트를 봐라. 그것은 절대로 네 시간의 가치가 있다. 그것은 동상 중의 하나The Best InterSystems Open Exchange Developers and Applications in 2019를 받았다.
나는 "새로운"메시지 뷰어에 포함하고 싶은 기능에 대한 생각을 기초하기 시작했다. 그러나 나는 어떻게 해야만 가장 빠르고 간단한 방식으로 이 자원들을 표시할 수 있을까?
응, 우선 해야 할 일.일반적으로 상호 운용성 제품을 설정한 후 내보낸 후 대상 시스템에 배치합니다documentation.이것은 내가 정말 좋아하지 않는 과정이다.그게 무슨 문제라는 게 아니야, 정말이야.나는 단지 코드를 사용하여 모든 일을 이상화했을 뿐이다.
나는 누군가가 이런 프로젝트를 실행할 때마다 이렇게 시작하기를 바란다.
$ docker-compose build
$ docker-compose up -d
봐!!!이러한 간단한 절차를 고려하여 나는 InterSystems 커뮤니티를 보기 시작했고 힌트를 찾았다.그중 한 게시물은 내가 자신에게 묻는 질문을 제기했다. How to create productions via routine?
그 게시물에서 Eduard Lebedyuk 코드를 사용하여 제품을 만드는 방법을 보여 주었다.
To create production class automatically you need to:
- Create %Dictionary.ClassDefinition object for your test production
- Create Ens.Config.Production object
- Create %Dictionary.XDataDefinition
- Serialize (2) into (3)
- Insert XData (3) into (1)
- Save and compile (1)
나는 Jenny Ames의 평론도 발견했다.
One best practice we often recommend is to build backward. Build business operations first, then business processes, then business services…
그럼 시작합시다!
요청, 비즈니스 운영 및 비즈니스 서비스
diashenrique반.messageviewer.util.설치 생산.말 그대로cls는 우리 제품의 설치를 책임지는 종류입니다.설치 프로그램 목록은 클래스에서 ClassMethod 설치를 호출합니다.
/// Helper to install a production to display capabilities of the enhanced viewer
ClassMethod Install() As %Status
{
Set sc = $$$OK
Try {
Set sc = $$$ADDSC(sc,..InstallProduction()) quit:$$$ISERR(sc)
Set sc = $$$ADDSC(sc,..GenerateMessages()) quit:$$$ISERR(sc)
Set sc = $$$ADDSC(sc,..GenerateUsingEnsDirector()) quit:$$$ISERR(sc)
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
classmethod InstallProduction은 다음 내용을 작성하여 제품의 주요 구조를 결합합니다.Set sc = $$$ADDSC(sc,..CreateRequest("diashenrique.messageviewer.Message.SimpleRequest","Message")) quit:$$$ISERR(sc)
Set sc = $$$ADDSC(sc,..CreateRequest("diashenrique.messageviewer.Message.AnotherRequest","Something")) quit:$$$ISERR(sc)
ClassMethod CreateRequest(classname As %String, prop As %String) As %Status [ Private ]
{
New $Namespace
Set $Namespace = ..#NAMESPACE
Set sc = $$$OK
Try {
Set class = ##class(%Dictionary.ClassDefinition).%New(classname)
Set class.GeneratedBy = $ClassName()
Set class.Super = "Ens.Request"
Set class.ProcedureBlock = 1
Set class.Inheritance = "left"
Set sc = $$$ADDSC(sc,class.%Save())
#; create adapter
Set property = ##class(%Dictionary.PropertyDefinition).%New(classname)
Set property.Name = prop
Set property.Type = "%String"
Set sc = $$$ADDSC(sc,property.%Save())
Set sc = $$$ADDSC(sc,$System.OBJ.Compile(classname,"fck-dv"))
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
이제 Ens에서 비즈니스 운영을 확장하기 위한 클래스를 만듭니다.비즈니스 운영:Set sc = $$$ADDSC(sc,..CreateOperation()) quit:$$$ISERR(sc)
클래스 생성 외에도 MessageMap 및 메소드 Consume도 만들었습니다.ClassMethod CreateOperation() As %Status [ Private ]
{
New $Namespace
Set $Namespace = ..#NAMESPACE
Set sc = $$$OK
Try {
Set classname = "diashenrique.messageviewer.Operation.Consumer"
Set class = ##class(%Dictionary.ClassDefinition).%New(classname)
Set class.GeneratedBy = $ClassName()
Set class.Super = "Ens.BusinessOperation"
Set class.ProcedureBlock = 1
Set class.Inheritance = "left"
Set xdata = ##class(%Dictionary.XDataDefinition).%New()
Set xdata.Name = "MessageMap"
Set xdata.XMLNamespace = "http://www.intersystems.com/urlmap"
Do xdata.Data.WriteLine("<MapItems>")
Do xdata.Data.WriteLine("<MapItem MessageType=""diashenrique.messageviewer.Message.SimpleRequest"">")
Do xdata.Data.WriteLine("<Method>Consume</Method>")
Do xdata.Data.WriteLine("</MapItem>")
Do xdata.Data.WriteLine("<MapItem MessageType=""diashenrique.messageviewer.Message.AnotherRequest"">")
Do xdata.Data.WriteLine("<Method>Consume</Method>")
Do xdata.Data.WriteLine("</MapItem>")
Do xdata.Data.WriteLine("</MapItems>")
Do class.XDatas.Insert(xdata)
Set sc = $$$ADDSC(sc,class.%Save())
Set method = ##class(%Dictionary.MethodDefinition).%New(classname)
Set method.Name = "Consume"
Set method.ClassMethod = 0
Set method.ReturnType = "%Status"
Set method.FormalSpec = "input:diashenrique.messageviewer.Message.SimpleRequest,&output:Ens.Response"
Set stream = ##class(%Stream.TmpCharacter).%New()
Do stream.WriteLine(" set sc = $$$OK")
Do stream.WriteLine(" $$$TRACE(input.Message)")
Do stream.WriteLine(" return sc")
Set method.Implementation = stream
Set sc = $$$ADDSC(sc,method.%Save())
Set sc = $$$ADDSC(sc,$System.OBJ.Compile(classname,"fck-dv"))
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
실제 상호작용 제품을 만들기 전의 마지막 단계에서 업무 서비스를 담당하는 클래스를 만듭니다.Set sc = $$$ADDSC(sc,..CreateRESTService()) quit:$$$ISERR(sc)
UrlMap 및 Http 요청을 수신하는 라우팅이 있습니다.ClassMethod CreateRESTService() As %Status [ Private ]
{
New $Namespace
Set $Namespace = ..#NAMESPACE
Set sc = $$$OK
Try {
Set classname = "diashenrique.messageviewer.Service.REST"
Set class = ##class(%Dictionary.ClassDefinition).%New(classname)
Set class.GeneratedBy = $ClassName()
Set class.Super = "EnsLib.REST.Service, Ens.BusinessService"
Set class.ProcedureBlock = 1
Set class.Inheritance = "left"
Set xdata = ##class(%Dictionary.XDataDefinition).%New()
Set xdata.Name = "UrlMap"
Set xdata.XMLNamespace = "http://www.intersystems.com/urlmap"
Do xdata.Data.WriteLine("<Routes>")
Do xdata.Data.WriteLine("<Route Url=""/send/message"" Method=""POST"" Call=""SendMessage""/>")
Do xdata.Data.WriteLine("<Route Url=""/send/something"" Method=""POST"" Call=""SendSomething""/>")
Do xdata.Data.WriteLine("</Routes>")
Do class.XDatas.Insert(xdata)
Set sc = $$$ADDSC(sc,class.%Save())
#; create adapter
Set adapter = ##class(%Dictionary.ParameterDefinition).%New(classname)
Set class.GeneratedBy = $ClassName()
Set adapter.Name = "ADAPTER"
Set adapter.SequenceNumber = 1
Set adapter.Default = "EnsLib.HTTP.InboundAdapter"
Set sc = $$$ADDSC(sc,adapter.%Save())
#; add prefix
Set prefix = ##class(%Dictionary.ParameterDefinition).%New(classname)
Set prefix.Name = "EnsServicePrefix"
Set prefix.SequenceNumber = 2
Set prefix.Default = "|demoiris"
Set sc = $$$ADDSC(sc,prefix.%Save())
Set method = ##class(%Dictionary.MethodDefinition).%New(classname)
Set method.Name = "SendMessage"
Set method.ClassMethod = 0
Set method.ReturnType = "%Status"
Set method.FormalSpec = "input:%Library.AbstractStream,&output:%Stream.Object"
Set stream = ##class(%Stream.TmpCharacter).%New()
Do stream.WriteLine(" set sc = $$$OK")
Do stream.WriteLine(" set request = ##class(diashenrique.messageviewer.Message.SimpleRequest).%New()")
Do stream.WriteLine(" set data = {}.%FromJSON(input)")
Do stream.WriteLine(" set request.Message = data.Message")
Do stream.WriteLine(" set sc = $$$ADDSC(sc,..SendRequestSync(""diashenrique.messageviewer.Operation.Consumer"",request,.response))")
Do stream.WriteLine(" return sc")
Set method.Implementation = stream
Set sc = $$$ADDSC(sc,method.%Save())
Set method = ##class(%Dictionary.MethodDefinition).%New(classname)
Set method.Name = "SendSomething"
Set method.ClassMethod = 0
Set method.ReturnType = "%Status"
Set method.FormalSpec = "input:%Library.AbstractStream,&output:%Stream.Object"
Set stream = ##class(%Stream.TmpCharacter).%New()
Do stream.WriteLine(" set sc = $$$OK")
Do stream.WriteLine(" set request = ##class(diashenrique.messageviewer.Message.AnotherRequest).%New()")
Do stream.WriteLine(" set data = {}.%FromJSON(input)")
Do stream.WriteLine(" set request.Something = data.Something")
Do stream.WriteLine(" set sc = $$$ADDSC(sc,..SendRequestSync(""diashenrique.messageviewer.Operation.Consumer"",request,.response))")
Do stream.WriteLine(" return sc")
Set method.Implementation = stream
Set sc = $$$ADDSC(sc,method.%Save())
Set sc = $$$ADDSC(sc,$System.OBJ.Compile(classname,"fck-dv"))
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
Visual Studio 코드 사용
% Dictionary 패키지를 사용하여 클래스를 만드는 것은 어려울 수도 있고, 읽기도 어려울 수도 있지만, 매우 편리합니다.더욱 간단하고 코드 가독성이 좋은 방법을 보여주기 위해 저는 Visual Studio 코드를 사용하여 새로운 요청, 업무 서비스와 업무 운영 클래스를 만들 것입니다.
Class diashenrique.messageviewer.Message.SimpleMessage Extends Ens.Request [ Inheritance = left, ProcedureBlock ]
{
Property ClassMessage As %String;
}
Class diashenrique.messageviewer.Operation.ConsumeMessageClass Extends Ens.BusinessOperation [ Inheritance = left, ProcedureBlock ]
{
Method Consume(input As diashenrique.messageviewer.Message.SimpleMessage, ByRef output As Ens.Response) As %Status
{
Set sc = $$$OK
$$$TRACE(pRequest.ClassMessage)
Return sc
}
XData MessageMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<MapItems>
<MapItem MessageType="diashenrique.messageviewer.Message.SimpleMessage">
<Method>Consume</Method>
</MapItem>
</MapItems>
}
}
Class diashenrique.messageviewer.Service.SendMessage Extends Ens.BusinessService [ ProcedureBlock ]
{
Method OnProcessInput(input As %Library.AbstractStream, ByRef output As %Stream.Object) As %Status
{
Set tSC = $$$OK
// Create the request message
Set request = ##class(diashenrique.messageviewer.Message.SimpleMessage).%New()
// Place a value in the request message property
Set request.ClassMessage = input
// Make a synchronous call to the business process and use the response message as our response
Set tSC = ..SendRequestSync("diashenrique.messageviewer.Operation.ConsumeMessageClass",request,.output)
Quit tSC
}
}
코드의 가독성 측면에서 볼 때, 이것은 거대한 차이이다!상호 운용성 제품 생성
상호 운용성 제품 생성을 완료합니다.이를 위해, 우리는 생산 클래스를 만들고 이를 업무 조작과 서비스 클래스와 연결시킬 것이다.
Set sc = $$$ADDSC(sc,..CreateProduction()) quit:$$$ISERR(sc)
ClassMethod CreateProduction(purge As %Boolean = 0) As %Status [ Private ]
{
New $Namespace
Set $Namespace = ..#NAMESPACE
Set sc = $$$OK
Try {
#; create new production
Set class = ##class(%Dictionary.ClassDefinition).%New(..#PRODUCTION)
Set class.ProcedureBlock = 1
Set class.Super = "Ens.Production"
Set class.GeneratedBy = $ClassName()
Set xdata = ##class(%Dictionary.XDataDefinition).%New()
Set xdata.Name = "ProductionDefinition"
Do xdata.Data.Write("<Production Name="""_..#PRODUCTION_""" LogGeneralTraceEvents=""true""></Production>")
Do class.XDatas.Insert(xdata)
Set sc = $$$ADDSC(sc,class.%Save())
Set sc = $$$ADDSC(sc,$System.OBJ.Compile(..#PRODUCTION,"fck-dv"))
Set production = ##class(Ens.Config.Production).%OpenId(..#PRODUCTION)
Set item = ##class(Ens.Config.Item).%New()
Set item.ClassName = "diashenrique.messageviewer.Service.REST"
Do production.Items.Insert(item)
Set sc = $$$ADDSC(sc,production.%Save())
Set item = ##class(Ens.Config.Item).%New()
Set item.ClassName = "diashenrique.messageviewer.Operation.Consumer"
Do production.Items.Insert(item)
Set sc = $$$ADDSC(sc,production.%Save())
Set item = ##class(Ens.Config.Item).%New()
Set item.ClassName = "diashenrique.messageviewer.Service.SendMessage"
Do production.Items.Insert(item)
Set sc = $$$ADDSC(sc,production.%Save())
Set item = ##class(Ens.Config.Item).%New()
Set item.ClassName = "diashenrique.messageviewer.Operation.ConsumeMessageClass"
Do production.Items.Insert(item)
Set sc = $$$ADDSC(sc,production.%Save())
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
Ens 클래스를 사용합니다.구성생산 클래스와 업무 조작과 서비스 클래스를 연결하는 항목.%Dictionary 패키지를 사용하든 VS 코드, Studio 또는 Atelier를 사용하여 클래스를 만들든 상관 없습니다.어쨌든 우리는 해냈다!우리는 코드를 사용하여 상호작용적인 제품을 만들었다.
그러나 이 모든 코드의 최초 목적을 기억하십시오. 제품과 메시지를 만들어서 향상된 메시지 뷰어의 기능을 보여 줍니다.아래classmethods를 사용하면 이 두 업무 서비스를 실행하고 메시지를 생성할 것입니다.
%Net을 사용하여 메시지를 생성하는 중입니다.HttpRequest
ClassMethod GenerateMessages() As %Status [ Private ]
{
New $Namespace
Set $Namespace = ..#NAMESPACE
Set sc = $$$OK
Try {
Set action(0) = "/demoiris/send/message"
Set action(1) = "/demoiris/send/something"
For i=1:1:..#LIMIT {
Set content = { }
Set content.Message = "Hi, I'm just a random message named "_$Random(30000)
Set content.Something = "Hi, I'm just a random something named "_$Random(30000)
Set httprequest = ##class(%Net.HttpRequest).%New()
Set httprequest.SSLCheckServerIdentity = 0
Set httprequest.SSLConfiguration = ""
Set httprequest.Https = 0
Set httprequest.Server = "localhost"
Set httprequest.Port = 9980
Set serverUrl = action($Random(2))
Do httprequest.EntityBody.Write(content.%ToJSON())
Set sc = httprequest.Post(serverUrl)
Quit:$$$ISERR(sc)
}
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
EnsDirector를 사용하여 메시지 생성
ClassMethod GenerateUsingEnsDirector() As %Status [ Private ]
{
New $Namespace
Set $Namespace = ..#NAMESPACE
Set sc = $$$OK
Try {
For i=1:1:..#LIMIT {
Set tSC = ##class(Ens.Director).CreateBusinessService("diashenrique.messageviewer.Service.SendMessage",.tService)
Set message = "Message Generated By CreateBusinessService "_$Random(1000)
Set tSC = tService.ProcessInput(message,.output)
Quit:$$$ISERR(sc)
}
}
Catch (err) {
Set sc = $$$ADDSC(sc,err.AsStatus())
}
Return sc
}
}
이게 코드야.너는 https://github.com/diashenrique/iris-message-viewer에서 완전한 항목을 찾을 수 있다프로젝트 실행
지금 우리 이 프로젝트의 실제 상황을 좀 봅시다.우선, git clone이나 git는 Repo를 로컬 디렉터리에 불러옵니다.
git clone https://github.com/diashenrique/iris-message-viewer.git
그런 다음 이 디렉토리에서 터미널을 열고 실행합니다.docker-compose build
마지막으로 프로젝트에서 IRIS 컨테이너를 실행합니다.docker-compose up -d
현재 우리는 http://localhost:52773/csp/sys/UtilHome.csp 액세스 관리 포털을 사용할 것이다.다음 그림과 같이 상호작용 수명 공간 MSGVIEWER를 보십시오.이것은 우리의 유아 제품으로 두 가지 업무 서비스와 두 가지 업무 운영이 있다.
우리는 많은 정보를 가지고 있다.
사용자 정의 메시지 뷰어에서 모든 내용을 시작하고 실행하면 그 기능들을 보여 줍니다.
향상된 메시지 뷰어
상호 운용성 제품에 대해 활성화된 네임스페이스만 표시됩니다.
http://localhost:52773/csp/msgviewer/messageviewer.csp
향상된 메시지 뷰어는 다양한 필터를 만들고, 열을 n레벨로 그룹화하고, Excel로 내보낼 수 있는 기능과 유연성을 제공합니다.
필요한 결과를 실현하기 위해 다른 필터를 사용할 수 있습니다.Shift 키를 누르고 열 머리글을 클릭하여 여러 정렬을 사용할 수도 있습니다.데이터 그리드를 Excel로 내보낼 수도 있습니다!
또한 필터 생성기 옵션을 사용하여 복잡한 필터를 생성할 수 있습니다.
사용 가능한 열에 따라 데이터를 그룹화할 수 있으며, 필요한 n레벨을 사용하여 정보를 그룹화할 수 있습니다.기본적으로 생성 날짜 필드를 사용하여 그룹을 구성합니다.
열을 선택할 수 있는 기능이 하나 더 있습니다.다음 페이지에는 Ens의 모든 열이 포함됩니다.MessageHeader, 기본 열만 초기 뷰에 표시됩니다.그러나 열 선택기 버튼을 사용하여 다른 열을 선택할 수 있습니다.
한 번만 클릭하면 모든 그룹을 축소하거나 확장할 수 있습니다.
한 번의 클릭으로 모든 그룹을 축소하거나 확장합니다.
SessionId 필드의 정보에는 시각 추적 기능에 대한 링크가 있습니다.
필요한 경우 메시지를 다시 보낼 수 있습니다.필요한 메시지만 선택하고 를 클릭하여 다시 보내십시오.이 기능은 다음과 같은 classMethod를 사용합니다.
##class(Ens.MessageHeader).ResendDuplicatedMessage(id)
마지막으로 앞에서 설명한 대로 데이터 메쉬를 Excel로 내보낼 수 있습니다.
Excel의 결과는 캐시 서버 페이지(CSP)에 정의된 동일한 형식, 내용 및 그룹을 표시합니다.
PS: 이 여정에서 많은 도움을 주셔서 특별히 감사드립니다.
Renan Lourenco
Reference
이 문제에 관하여(대체 IRIS 메시지 뷰어 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/intersystems/building-an-alternative-iris-message-viewer-3pmc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)