EnsLib.SOAP.OutboundAdapter - Bind to Address?
We are attempting to setup an EnsLib.SOAP.OutboundAdapter to send an HL7 message to a vendor hosted AWS site. We have the Certificate from the vendor and defined the TLS setting. However, when we are sending the message we are receiving...
Unable to open TCP/IP socket to server hcis-staging.cbord.com:443
So, we figured it might be a firewall issue. With the TCP Outbound Adapter, we could specify which "Local Interface" to use so that our firewall knew to use the VIP that had has been NAT'd. I don't see this option with the EnsLib.SOAP.OutboundAdapter, so is this possible to do? How can I ensure that when the connection is being made that it is using the VIP address within the message header?
looking at netstat I am not seeing a connection ever being attempted via udp to the URL
How do I ensure that the SOAP request is being bound to the VIP address instead of the local IP Address?
Comments
You can extend EnsLib.SOAP.OutboundAdapter and add support for LocalInterface and use the "new" adapter in your BO.
With "inspiration" 😁 from EnsLib.HTTP.OutboundAdapter, something like:
Class Community.adapter.SoapOutbound Extends EnsLib.SOAP.OutboundAdapter
{
/// In a multi-homed system, specify which network interface the TCP connection should go through. An empty value means to use any interface. <br/>/// To be able to bind to IPv6 interfaces you may need to enable IPv6 in your instance. This is done in the System Management Portal under /// System Administration > Configuration > Additional Settings > Startup, by editing the IPv6 setting.Property LocalInterface As%String(MAXLEN = 250);Parameter SETTINGS = "LocalInterface:Connection:selector?context={Ens.ContextSearch/TCPLocalInterfaces}";
Method OnInit() As%Status
{
Set ..%Client.HttpRequest=##class(%Net.HttpRequest).%New()
Set ..%Client.HttpRequest.LocalInterface=$ZStrip($P(..LocalInterface,"("),"*W")
Return##super()
}
}
I did not tested it, try it and let us know.
Nete, if for any reason you reinstantiate ..%Client.HttpRequest, then you need to set the LocalInterface property.
Having LocalInterface support in EnsLib.SOAP.OutboundAdapter "out of the box" can be worth an entry in the ideas portal.
I ended up doing..
Class osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port Extends (Ens.BusinessOperation, EnsLib.SOAP.GenericOperation) [ ProcedureBlock ]
{
Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter";Property LocalInterface As%String(MAXLEN = 255);Parameter SETTINGS = "LocalInterface:Connection:selector?context={Ens.ContextSearch/TCPLocalInterfaces}";
Method OnInit() As%Status
{
set interface = $ZStrip($P(..LocalInterface,"("),"*W")
set HttpRequest = ##class(%Net.HttpRequest).%New()
set HttpRequest.LocalInterface = interface
$$$LOGINFO("CBORDHL7Port OnInit: LocalInterface="_interface)
QUIT$$$OK
}The $$$LOGINFO is showing the correct address, but I am still having issues connecting. But thanks
That won't work, you are just setting a %Net.HttpRequest object in a (private) variable called HttpRequest that is destroyed when the method ends.
You need to set/change the %Net.HttpRequest instance contained in the ..%Client property of the adapted AFTER the web service client class is set/instantiated in ..%Client.
Did you had a chance to test the modified adapter I've posted? Maybe tomorrow I'll have time to test it.
Class osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port Extends (Ens.BusinessOperation, EnsLib.SOAP.GenericOperation) [ ProcedureBlock ]
{
Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter";Property LocalInterface As%String(MAXLEN = 255);Parameter SETTINGS = "LocalInterface:Connection:selector?context={Ens.ContextSearch/TCPLocalInterfaces}";
Method OnInit() As%Status
{
set interface = $ZStrip($P(..LocalInterface,"("),"*W")
Set ..%Client.HttpRequest=##class(%Net.HttpRequest).%New()
set ..%Client.HttpRequest.LocalInterface = interface
QUIT$$$OK
}I tried using ..%Client but got..
ERROR: osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port.cls
ERROR: osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port.1(4) : MPP5376 : Method or Property '%Client' does not exist in this class.
TEXT: Set ..%Client.HttpRequest=##class(%Net.HttpRequest).%New()
ERROR: osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port.1(5) : MPP5376 : Method or Property '%Client' does not exist in this class.
TEXT: set ..%Client.HttpRequest.LocalInterface = interface
When I tried to compile.
Another option, in your BO add:
Property LocalInterface As%String(MAXLEN = 255);Parameter SETTINGS = "LocalInterface:Connection:selector?context={Ens.ContextSearch/TCPLocalInterfaces}";Then before calling the service (..Adaper.Invoke*()) add this:
If 'IsObject(..Adapter.%Client.HttpRequest) {
Set..Adapter.%Client.HttpRequest=##class(%Net.HttpRequest).%New()
}
Set..Adapter.%Client.HttpRequest.LocalInterface=$ZStrip($P(..LocalInterface,"("),"*W")
Edit to add: Why are you extending EnsLib.SOAP.GenericOperation?
For a SOAP BO using EnsLib.SOAP.OutboundAdapter the class signature is supposed to be:
Class osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port Extends Ens.BusinessOperation
Still not working right..
Class osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port Extends Ens.BusinessOperation [ ProcedureBlock ]
{
Parameter ADAPTER = "EnsLib.SOAP.OutboundAdapter";Property LocalInterface As%String(MAXLEN = 255);Parameter SETTINGS = "LocalInterface:Connection:selector?context={Ens.ContextSearch/TCPLocalInterfaces}";
Method OnInit() As%Status
{
If 'IsObject(..Adapter.%Client.HttpRequest) {
Set..Adapter.%Client.HttpRequest=##class(%Net.HttpRequest).%New()
}
Set..Adapter.%Client.HttpRequest.LocalInterface=$ZStrip($P(..LocalInterface,"("),"*W")
}Terminating Job 819984 / 'NutritionCBOARDNetMenuSOAP' with Status = ERROR <Ens>ErrException: <SUBSCRIPT>OnInit+1^osuwmc.Nutrition.OSU.CBOARDNetMenuOperation.CBORDHL7Port.1 *IsObject("") -- logged as '-' number - @' If 'IsObject(..Adapter.%Client.HttpRequest) {', %QuitTask=
Sorry, my bad, a typo, please replace IsObject with $IsObject
If '$IsObject(..Adapter.%Client.HttpRequest) {