Article
· Aug 30, 2023 5m read

Add/Edit Business Hosts to Interoperability production - A different approach

Wanted to share something I learned recently while working on a problem. We needed to add and change some Business Hosts in one of our edge productions.

In the past, we simply added the production class to CCR and then spreading it around. But there was a problem because different developers were working on different things, and we only wanted to include only the relevent production changes onto the CCR. 

Here's a little piece of code that can help add new things to an existing production:

class HSEDGE1PKG.ProductionDefinition
{

/// define the Productions Definitions which are listed below
/// should be a comma seperated string
Parameter ProdDefinitions = "EdgeGatewayProduction";
XData EdgeGatewayProduction
{
<Item Name="EnsLib.HL7.Service.FileService" Category="" ClassName="EnsLib.HL7.Service.FileService" PoolSize="1" Enabled="true" Foreground="false" DisableErrorTraps="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="InactivityTimeout">0</Setting>
    <Setting Target="Host" Name="TargetConfigNames">HS.Gateway.HL7.InboundProcess</Setting>
    <Setting Target="Host" Name="AckMode">Never</Setting>
    <Setting Target="Host" Name="MessageSchemaCategory">2.5</Setting>
    <Setting Target="Adapter" Name="FilePath">..\..\Data\HSEDGE1\HL7In</Setting>
  </Item>
  <Item Name="HUB" Category="" ClassName="HS.Hub.HSWS.RemoteOperations" PoolSize="1" Enabled="true" Foreground="false" DisableErrorTraps="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="InactivityTimeout">0</Setting>
    <Setting Target="Host" Name="ServiceName">HSREGISTRY</Setting>
    <Setting Target="Adapter" Name="ResponseTimeout">2592000</Setting>
    <Setting Target="Host" Name="FailureTimeout">-1</Setting>
    <Setting Target="Host" Name="Retry">1</Setting>
    <Setting Target="Host" Name="RetryInterval">120</Setting>
  </Item>
  <Item Name="HS.Gateway.HSWS.WebServices" Category="" ClassName="HS.Gateway.HSWS.WebServices" PoolSize="0" Enabled="true" Foreground="false" Comment="" LogTraceEvents="false" Schedule="">
    <Setting Target="Host" Name="InactivityTimeout">0</Setting>
    <Setting Target="Host" Name="ECRTarget">HS.Gateway.ECR.Manager</Setting>
    <Setting Target="Host" Name="PushRepMgr">HS.Gateway.ECR.Push.RepositoryManager</Setting>
    <Setting Target="Host" Name="ECRProcess">HS.Gateway.ECR.Process</Setting>
    <Setting Target="Host" Name="ResourceRequired">%HS_WebServices</Setting>
    <Setting Target="Host" Name="GatewayName">j2windowsvm:HSEDGE1</Setting>
    <Setting Target="Host" Name="AnalyticsNotificationTargets">AnalyticsSubscriptionHandler</Setting>
  </Item>
}



ClassMethod AddUpdateProductions() As %Status
{
    #dim status as %Status = $$$OK
    // set the XDATA IDS
    Set xdataID =""
    Set tInitNamespace = $namespace
    //loop through the defined production definitions 
    //if multiple productions needs to be updated simply add new xdata blocks
    Set tProdDefinitionsList = $ListFromString(..#ProdDefinitions,",")
    Set n = $ListLength(tProdDefinitionsList)
    
    // loop through the defined production definitions
    For xdataID=1:1:n {

        #dim tFromProd As Ens.Config.Production
        #dim tItem As Ens.Config.Item
        
        Set status = ..OpenProduction($classname(),$list(tProdDefinitionsList,xdataID),.tFromProd)
        
        //switch to the corret namespace
        set tNamespace = "HSEDGE01"
        set $namespace = tNamespace
        
        // Open the original production, and add items
        Set tToProduction=##class(Ens.Config.Production).%OpenId(tFromProd.Name,,.tSC) Throw:$$$ISERR(tSC)
        For tI=1:1:tFromProd.Items.Count() {
            Set tItem=tFromProd.Items.GetAt(tI)
            Set tSC=..AddConfigItem(tItem,tToProduction) 
            Quit:$$$ISERR(tSC)
        }
        
        Set:$$$ISOK(tSC) tSC=..SaveProduction(tToProduction)
        Kill tFromProd,tToProduction,tItem
        
    }
    
    set $namespace = tInitNamespace
    Quit status
}

/// This will look for the production Item in pToProd
/// if pItem.Name exists in pToProd delete it and 
/// add pItem with the above defined setting in the XData block
ClassMethod AddConfigItem(pItem As Ens.Config.Item, pToProd As Ens.Config.Production) As %Status
{
    #dim tItem As Ens.Config.Item
    #dim tFromItem As Ens.Config.Item
    set tFoundItem=""
    // check if production item exists and remove it
    Set tI=""
    For tI=1:1:pToProd.Items.Count() {
        set tItem = pToProd.Items.GetAt(tI)
        If tItem.Name=pItem.Name{
            Set tFoundItem=1
            do pToProd.Items.RemoveAt(tI)
            Quit
        }
    }
    
    //add the production item
    set tSC = pToProd.Items.Insert(pItem)

    Quit tSC
}

/// method to open a production
ClassMethod OpenProduction(pProdClass As %String, pProductionDef As %String, Output pProdRef As Ens.Config.Production) As %Status
{
    Quit ##Class(Ens.Util.XML.Reader).ObjectFromXData(.pProdRef,pProdClass,pProductionDef,"Ens.Config.Production")
}

// Save pProd (oRef)
ClassMethod SaveProduction(pProd As Ens.Config.Production) As %Status
{
    Do {
        Set tSC=pProd.%Save() Quit:$$$ISERR(tSC)
        Set tSC=pProd.SaveToClass() Quit:$$$ISERR(tSC)
        Set tProdClass=pProd.Name
        Set tSC = $System.OBJ.Compile(tProdClass,"-d") Quit:$$$ISERR(tSC)
        // Only reload on IRIS versions starting with 2020.1
        // Needed to reswizzle
        If ($System.Version.GetMajor() >= 2020) {
            Set tSC = pProd.%Reload() Quit:$$$ISERR(tSC)
        }
    } While 0
    Quit tSC
}

}

The good thing about this way is that we can just copy a part of the code from the production class to make our changes.

I hope you find this helpful. I am sure we can make this code even better, but it's working well for me right now.

Discussion (0)1
Log in or sign up to continue