Skip to main content

Use Embedded Python in Interoperability Productions

If you are writing custom business host classes or adapter classes for interoperability productions in InterSystems IRIS, any callback methods must be written in ObjectScript. A callback method is an inherited method that does nothing by default, but is designed to be implemented by the user. The ObjectScript code in a callback method can, however, make use of Python libraries or call other methods implemented in Python.

The following example shows a business operation that takes the string value from an incoming message and uses the Amazon Web Services (AWS) boto3 Python library to send that string to a phone in a text message via the Amazon Simple Notification Service (SNS). The scope of this AWS library is out of scope for this discussion, but you can see in the example that the OnInit() and OnMessage() callback methods are written in ObjectScript, while the methods PyInit() and SendSMS() are written in Python.

/// Send SMS via AWS SNS
Class dc.opcua.SMS Extends Ens.BusinessOperation
{

Parameter INVOCATION = "Queue";

/// AWS boto3 client
Property client As %SYS.Python;

/// json.dumps reference
Property tojson As %SYS.Python;

/// Phone number to send SMS to
Property phone As %String [ Required ];

Parameter SETTINGS = "phone:SMS";

Method OnMessage(request As Ens.StringContainer, Output response As Ens.StringContainer) As %Status
{
   #dim sc As %Status = $$$OK
   try {
      set response = ##class(Ens.StringContainer).%New(..SendSMS(request.StringValue))
      set code = +{}.%FromJSON(response.StringValue).ResponseMetadata.HTTPStatusCode
      set:(code'=200) sc = $$$ERROR($$$GeneralError, $$$FormatText("Error sending SMS,
         code: %1 (expected 200), text: %2", code, response.StringValue))
   } catch ex {
      set sc  = ex.AsStatus()
   }
   
   return sc
}

Method SendSMS(msg As %String) [ Language = python ]
{
   response = self.client.publish(PhoneNumber=self.phone, Message=msg)
   return self.tojson(response)
}

Method OnInit() As %Status
{
   #dim sc As %Status = $$$OK
   try {
      do ..PyInit()
   } catch ex {
      set sc = ex.AsStatus()
   }
   quit sc
}

/// Connect to AWS
Method PyInit() [ Language = python ]
{
   import boto3
   from json import dumps
   self.client = boto3.client("sns")
   self.tojson = dumps
}

}
Note:

The code in the OnMessage() method, above, contains an extra line break for better formatting when printing this document.

One exception to this rule is that you can implement a callback method in Python if it does not use the input from the adapter.

The following business service example is known as a poller. In this case, the business service can be set to run at intervals and generates a request (in this case containing a random string value) that is sent to a business process for handling. In this example the OnProcessInput() callback method can be implemented in Python because it does not make use of the pInput argument in the method’s signature.

Class Debug.Service.Poller Extends Ens.BusinessService
{

Property Target As Ens.DataType.ConfigName;

Parameter SETTINGS = "Target:Basic";

Parameter ADAPTER = "Ens.InboundAdapter";

Method OnProcessInput(pInput As %RegisteredObject, Output pOutput As %RegisteredObject, 
    ByRef pHint As %String) As %Status [ Language = python ]
{
    import iris
    import random
    fruits = ["apple", "banana", "cherry"]
    fruit = random.choice(fruits)
    request = iris.cls('Ens.StringRequest')._New()
    request.StringValue = fruit + ' ' + iris.cls('Debug.Service.Poller').GetSomeText()
    return self.SendRequestAsync(self.Target,request)
}

ClassMethod GetSomeText() As %String
{
    Quit "is something to eat"
}

}

For more information on programming for interoperability productions, see Programming Business Services, Processes and Operations.

FeedbackOpens in a new tab