Question
· Jan 3

Troubleshooting SOAP Header Processing Issue Between HealthShare Environments: Seeking Assistance and Insights

First of all, thanks for your help, and time reading this question.

 

Why, when we send a SOAP message from SoapUI to a SOAP service in a HealthShare environment called 'ESBCHUIMI,' it recognizes the 'Credenciales' header, which has 'usuario' and 'password' as properties. This class is a %SOAP.Header.

However, when we load the WSDL using the SOAP wizard from this SOAP Service to another HealthShare environment called ESBSSCC and send it from SoapUI to ESBSSCC, when it is being forwarded from ESBSSCC to ESBCHUIMI, the ESBCHUIMI's service outputs:

'[...] <error xmlns="http://SCS.Servicios/SIPRESatelites">
<text>ERROR #5002: Error de cache: &lt;INVALID OREF&gt;zactualizarEstadoSolicitudOrto+7^Servicios.ProgramasAsistenciales.DragoAE.Ortoprotesis.SIPREtoDragoAEv01r00.1</text>
</error>'

This indicates that it is failing at: 'set request.usuario = ..HeadersIn.GetNext().usuario.'

If we compare both LOGSOAP, we observe the following:

It works from SoapUI to ESBCHUIMI as shown in the LOGSOAP:

01/03/2024 10:25:56 *********************
Input to Web service with SOAP action = "http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sip="http://SCS.Servicios/SIPRESatelites">
   <soapenv:Header>
      <sip:Credenciales>
         <sip:usuario>ABC</sip:usuario>
         <sip:password>DEF</sip:password>
      </sip:Credenciales>
   </soapenv:Header>
   <soapenv:Body>
      <sip:ActualizarEstadoSolicitudOrtoRequestElement>
         <sip:id_solicitud>100014ORTO</sip:id_solicitud>
         <sip:cod_centro_entidad>350311</sip:cod_centro_entidad>
         <sip:num_expediente_tarjeta>6181777</sip:num_expediente_tarjeta>
         <sip:estado>2</sip:estado>
         <!--Optional:-->
         <sip:observaciones></sip:observaciones>
      </sip:ActualizarEstadoSolicitudOrtoRequestElement>
   </soapenv:Body>
</soapenv:Envelope>
---------------
Validate Security header: action="http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto"

 

 

 

However, it does not work when we send it from ESBSSCC to ESBCHUIMI, as shown in the new LOGSOAP:

01/03/2024 10:48:14 *********************
Input to Web service with SOAP action = http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'>
    <SOAP-ENV:Header>
        <Credenciales xmlns="http://SCS.Servicios/ProgramasAsistenciales" xmlns:hdr="http://SCS.Servicios/ProgramasAsistenciales">
            <usuario xsi:type="s:string">ABC</usuario>
            <password xsi:type="s:string">DEF</password>
        </Credenciales>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ActualizarEstadoSolicitudOrtoRequestElement xmlns="http://SCS.Servicios/SIPRESatelites">
            <id_solicitud xsi:type="s:string">100014ORTO</id_solicitud>
            <cod_centro_entidad xsi:type="s:string">350311</cod_centro_entidad>
            <num_expediente_tarjeta xsi:type="s:string">6181777</num_expediente_tarjeta>
            <estado xsi:type="s:string">2</estado>
            <observaciones xsi:type="s:string"/>
        </ActualizarEstadoSolicitudOrtoRequestElement>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

---------------
Validate Security header: action=http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto

ESBSSCC's SOAP Service is configured as follows:

	Class Servicios.ProgramasAsistenciales.DragoAE.Ortoprotesis.SIPREtoDragoAEv01r00 Extends EnsLib.SOAP.Service [ ProcedureBlock ]
	{

	/// This is the namespace used by the Service
	Parameter NAMESPACE = "http://SCS.Servicios/SIPRESatelites";

	/// Use xsi:type attribute for literal types.
	Parameter OUTPUTTYPEATTRIBUTE = 1;

	/// Determines handling of Security header.
	Parameter SECURITYIN = "ALLOW";

	/// This is the name of the Service
	Parameter SERVICENAME = "Ortoprotesis";

	/// This is the SOAP version supported by the service.
	Parameter SOAPVERSION = 1.1;

	/// Namespaces of referenced classes will be used in the WSDL.
	Parameter USECLASSNAMESPACES = 1;


	Method actualizarEstadoSolicitudOrto(idsolicitud As %String(XMLNAME="id_solicitud",REQUIRED=1), codcentroentidad As %String(XMLNAME="cod_centro_entidad",REQUIRED=1), numexpedientetarjeta As %String(XMLNAME="num_expediente_tarjeta",REQUIRED=1), estado As %String(XMLPATTERN="\d{1,100}",REQUIRED=1), observaciones As %String(MAXLEN=4000), Output descripcion As %String(REQUIRED=1)) As %Numeric(XMLNAME="codigo") [ Final, ProcedureBlock = 1, SoapAction = "http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto", SoapBindingStyle = document, SoapBodyUse = literal, SoapMessageName = ActualizarEstadoSolicitudOrtoResponseElement, SoapRequestMessage = ActualizarEstadoSolicitudOrtoRequestElement, WebMethod ]
	{
		set request = ##class(Mensajes.Request.ProgramasAsistenciales.DragoAE.actualizarEstadoSolicitudOrtoRequest).%New()
		set request.idsolicitud = idsolicitud
		set request.codcentroentidad = codcentroentidad
		set request.numexpedientetarjeta = numexpedientetarjeta
		set request.estado = estado
		set request.observaciones = observaciones
		
		set request.usuario = ..HeadersIn.GetNext().usuario
		;set request.usuario = ..HeadersIn.GetNext("Credenciales").usuario
		set request.password = ..HeadersIn.GetNext().password
		;set request.password = ..HeadersIn.GetNext("Credenciales").password
		
		try {
			set sc=..ProcessInput(request, .response)
			set descripcion = response.descripcion
		 } catch {
			set sc = $System.Status.Error()
		 }

		 if $$$ISERR(sc){
			set response = request.NewResponse(response)
			;set response.codigoResultado = "002"
			;set response.descripcionResultado = "Se ha producido un error de comunicación."
		 }
		 else{
			 ;set descripcionResultado= response.descripcionResultado
			 ;set Servicios= response.Servicios
		 }

		 Quit response.codigo
	}


	Method OnProcessInput(pInput As Ens.Request, Output pOutput As Ens.Response) As %Status
	{
		Quit ..SendRequestSync("EnrutadorOrtoSIPREtoDragoAE",pInput,.pOutput)
	}

	XData parameters
	{
	<parameters xmlns="http://www.intersystems.com/configuration" xmlns:cfg="http://www.intersystems.com/configuration">
	  <method name="actualizarEstadoSolicitudOrto">
		<request>
		  <header name="Credenciales" class="EsquemasDatos.ProgramasAsistenciales.DragoAE.s0.Credenciales"/>
		</request>
	  </method>
	</parameters>
	}

	}

ESBSSCC's Web Service Client is configured as follows:

Class WSCLIENTE.ProgramasAsistenciales.DragoAE.OrtoprotesisSoap Extends %SOAP.WebClient [ ProcedureBlock ]
	{

	/// This is the URL used to access the web service.
	Parameter LOCATION = "http://[ESBCHUIMI's IP and PORT/csp/healthshare/esbchuimi/Servicios.ProgramasAsistenciales.DragoAE.Ortoprotesis.SIPREtoDragoAEv01r00.cls";

	/// This is the namespace used by the Service
	Parameter NAMESPACE = "http://SCS.Servicios/SIPRESatelites";

	/// Use xsi:type attribute for literal types.
	Parameter OUTPUTTYPEATTRIBUTE = 1;

	/// Determines handling of Security header.
	Parameter SECURITYIN = "ALLOW";

	/// This is the name of the Service
	Parameter SERVICENAME = "Ortoprotesis";

	/// This is the SOAP version supported by the service.
	Parameter SOAPVERSION = 1.1;

	// Method actualizarEstadoSolicitudOrto(idsolicitud As %String(XMLNAME="id_solicitud",REQUIRED=1), codcentroentidad As %String(XMLNAME="cod_centro_entidad",REQUIRED=1), numexpedientetarjeta As %String(XMLNAME="num_expediente_tarjeta",REQUIRED=1), estado As %String(XMLPATTERN="\d{1,100}",REQUIRED=1), observaciones As %String(MAXLEN=4000), Output descripcion As %String(REQUIRED=1)) As %Numeric(XMLNAME="codigo") [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]

	Method actualizarEstadoSolicitudOrto(idsolicitud As %String(XMLNAME="id_solicitud",REQUIRED=1), codcentroentidad As %String(XMLNAME="cod_centro_entidad",REQUIRED=1), numexpedientetarjeta As %String(XMLNAME="num_expediente_tarjeta",REQUIRED=1), estado As %String(XMLPATTERN="\d{1,100}",REQUIRED=1), observaciones As %String(MAXLEN=4000), Output descripcion As %String(REQUIRED=1), usuario As %String(REQUIRED=1), password As %String(REQUIRED=1)) As %Numeric(XMLNAME="codigo") [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
	{
	 //credenciales en el header
	   set Credenciales = ##class(EsquemasDatos.ProgramasAsistenciales.DragoAE.tns.CredencialesType).%New()
	   set Credenciales.usuario = usuario
	   set Credenciales.password = password  

	   do ..HeadersOut.SetAt(Credenciales, "Credenciales")

	 Quit ..WebMethod("actualizarEstadoSolicitudOrto","ActualizarEstadoSolicitudOrtoRequestElement").Invoke($this,"http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto",.idsolicitud,.codcentroentidad,.numexpedientetarjeta,.estado,.observaciones,.descripcion)
	}

	XData parameters
	{
	<parameters xmlns="http://www.intersystems.com/configuration" xmlns:cfg="http://www.intersystems.com/configuration">
	  <method name="actualizarEstadoSolicitudOrto">
		<request>
		  <header name="Credenciales" class="EsquemasDatos.ProgramasAsistenciales.DragoAE.s0.Credenciales"/>
		</request>
	  </method>
	</parameters>
	}

}

And ESBCHUIMI's SOAP Service is configured as follows:

	Class Servicios.ProgramasAsistenciales.DragoAE.Ortoprotesis.SIPREtoDragoAEv01r00 Extends EnsLib.SOAP.Service [ ProcedureBlock ]
	{

	// Parameter NAMESPACE = "http://SIPRESatelites/SIPRESatelites.wsdl";

	/// This is the namespace used by the Service
	Parameter NAMESPACE = "http://SCS.Servicios/SIPRESatelites";

	/// Use xsi:type attribute for literal types.
	Parameter OUTPUTTYPEATTRIBUTE = 1;

	/// Determines handling of Security header.
	Parameter SECURITYIN = "ALLOW";

	/// This is the name of the Service
	Parameter SERVICENAME = "Ortoprotesis";

	/// This is the SOAP version supported by the service.
	Parameter SOAPVERSION = 1.1;

	/// Namespaces of referenced classes will be used in the WSDL.
	Parameter USECLASSNAMESPACES = 1;

	Method actualizarEstadoSolicitudOrto(idsolicitud As %String(XMLNAME="id_solicitud",REQUIRED=1), codcentroentidad As %String(XMLNAME="cod_centro_entidad",REQUIRED=1), numexpedientetarjeta As %String(XMLNAME="num_expediente_tarjeta",REQUIRED=1), estado As %String(XMLPATTERN="\d{1,100}",REQUIRED=1), observaciones As %String(MAXLEN=4000), Output descripcion As %String(REQUIRED=1)) As %Numeric(XMLNAME="codigo") [ Final, ProcedureBlock = 1, SoapAction = "http://SCS.Servicios/SIPRESatelites/actualizarEstadoSolicitudOrto", SoapBindingStyle = document, SoapBodyUse = literal, SoapMessageName = ActualizarEstadoSolicitudOrtoResponseElement, SoapRequestMessage = ActualizarEstadoSolicitudOrtoRequestElement, WebMethod ]
	{
		set request = ##class(Mensajes.Request.ProgramasAsistenciales.DragoAE.actualizarEstadoSolicitudOrtoRequest).%New()
		set request.idsolicitud = idsolicitud
		set request.codcentroentidad = codcentroentidad
		set request.numexpedientetarjeta = numexpedientetarjeta
		set request.estado = estado
		set request.observaciones = observaciones
		
		set request.usuario = ..HeadersIn.GetNext().usuario
		;set request.usuario = ..HeadersIn.GetNext("Credenciales").usuario
		set request.password = ..HeadersIn.GetNext().password
		;set request.password = ..HeadersIn.GetNext("Credenciales").password
		
		try {
			set sc=..ProcessInput(request, .response)
			set descripcion = response.descripcion
		 } catch {
			set sc = $System.Status.Error()
		 }

		 if $$$ISERR(sc){
			set response = request.NewResponse(response)
			;set response.codigoResultado = "002"
			;set response.descripcionResultado = "Se ha producido un error de comunicación."
		 }
		 else{
			 ;set descripcionResultado= response.descripcionResultado
			 ;set Servicios= response.Servicios
		 }

		 Quit response.codigo
	}

	Method OnProcessInput(pInput As Ens.Request, Output pOutput As Ens.Response) As %Status
	{
		Quit ..SendRequestSync("EnrutadorOrtoSIPREtoDragoAE",pInput,.pOutput)
	}

	XData parameters
	{
	<parameters xmlns="http://www.intersystems.com/configuration" xmlns:cfg="http://www.intersystems.com/configuration">
	  <method name="actualizarEstadoSolicitudOrto">
		<request>
		  <header name="Credenciales" class="EsquemasDatos.ProgramasAsistenciales.DragoAE.tns.CredencialesType"/>
		</request>
	  </method>
	</parameters>
	}

	}

If anyone can provide insights or assistance on the issue described above, it would be greatly appreciated. We are encountering difficulties when sending a SOAP message from ESBSSCC to ESBCHUIMI, specifically at the point where the ESBCHUIMI's service attempts to process the 'usuario' property from the 'Credenciales' header. The error message indicates an issue with cache, pointing to a specific location in the code.

We have provided detailed logs for both successful and unsuccessful scenarios, along with configurations of SOAP services involved in ESBSSCC and ESBCHUIMI. Any help, guidance, or suggestions to troubleshoot and resolve this issue would be valuable.

Thank you for your time, assistance, support, dedication, and any responses provided.

Again: thanks.

Product version: IRIS 2020.1
Discussion (5)1
Log in or sign up to continue

Thanks @Shanshan Yu  for your help.

Yes it does, the ESBCHUIMI's web service client class has it code to handle the SOAP header as follows:

Method actualizarEstadoSolicitudOrto(idsolicitud As %String(XMLNAME="id_solicitud",REQUIRED=1), codcentroentidad As %String(XMLNAME="cod_centro_entidad",REQUIRED=1), numexpedientetarjeta As %String(XMLNAME="num_expediente_tarjeta",REQUIRED=1), estado As %String(XMLPATTERN="\d{1,100}",REQUIRED=1), observaciones As %String(MAXLEN=4000), Output descripcion As %String(REQUIRED=1), usuario As %String(REQUIRED=1), password As %String(REQUIRED=1)) As %Numeric(XMLNAME="codigo") [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
 //credenciales en el header
   set Credenciales = ##class(EsquemasDatos.ProgramasAsistenciales.DragoAE.tns.CredencialesType).%New()
   set Credenciales.usuario = usuario
   set Credenciales.password = password  

   do ..HeadersOut.SetAt(Credenciales, "Credenciales")
   
 Quit ..WebMethod("actualizarEstadoSolicitudOrto","ActualizarEstadoSolicitudOrtoRequestElement").Invoke($this,"http://SIPRESatelites/SIPRESatelites.wsdl/actualizarEstadoSolicitudOrto",.idsolicitud,.codcentroentidad,.numexpedientetarjeta,.estado,.observaciones,.descripcion)
}

The challenge is that there is an Exception between what ESBSSCC's web service client outputs and what ESBCHUIMI's SERVICE class handles as inputs, because it fails at recognizing SOAP Header's Credenciales, and the execution flow breaks at line 7 at ESBCHUIMI's Service Class code here:

set request.usuario = ..HeadersIn.GetNext().usuario
 

We have also tried to call it as follows and it stills failling:

set request.usuario = ..HeadersIn.GetNext("Credenciales").usuario

Being the Error code as follows:

Id.: 320758306
Tipo: Error
Texto: ERROR #6248: La respuesta de SOAP es un error de SOAP: faultcode=Server
faultstring=Error del servidor de aplicaciones.
faultactor=
detail=
<error xmlns="http://SCS.Servicios/SIPRESatelites">
<text>ERROR #5002: Error de cache: &lt;INVALID OREF&gt;zactualizarEstadoSolicitudOrto+7^Servicios.ProgramasAsistenciales.DragoAE.Ortoprotesis.SIPREtoDragoAEv01r00.1</text>
</error>

Could you help us please?

Thanks for your time.

Thanks for your help.

Thanks for your replies.

Thanks  @Shanshan Yu it worked as expected.

We have changed both ESBSSCC's and ESBCHUIMI's NAMESPACE to be: http://SIPRESatelites/SIPRESatelites.wsdl

So then ESBSSCC's SOAP Header class is:

Class EsquemasDatos.ProgramasAsistenciales.DragoAE.tns.CredencialesType Extends (%Persistent, %SOAP.Header) [ ProcedureBlock ]
{

Parameter ELEMENTQUALIFIED = 1;

Parameter NAMESPACE = "http://SIPRESatelites/SIPRESatelites.wsdl";

// Parameter NAMESPACE = "http://SCS.Servicios/ProgramasAsistenciales";

Parameter XMLFORMAT = "literal";

Parameter XMLNAME = "Credenciales";

Parameter XMLSEQUENCE = 1;

Property usuario As %String(MAXLEN = "", XMLNAME = "usuario") [ Required ];

Property password As %String(MAXLEN = "", XMLNAME = "password") [ Required ];

And then, ESBCHUIMI's SOAP Header class as the same NAMESPACE:

Class EsquemasDatos.ProgramasAsistenciales.DragoAE.tns.CredencialesType Extends (%Persistent, %SOAP.Header) [ ProcedureBlock ]
{

Parameter ELEMENTQUALIFIED = 1;

Parameter NAMESPACE = "http://SIPRESatelites/SIPRESatelites.wsdl";

// Parameter NAMESPACE = "http://SCS.Servicios/SIPRESatelites";

Parameter XMLNAME = "CredencialesType";

Parameter XMLSEQUENCE = 1;

Property usuario As %String(MAXLEN = "", XMLNAME = "usuario") [ Required ];

Property password As %String(MAXLEN = "", XMLNAME = "password") [ Required ];

To sum up, the solution was to writte the same NAMESPACE at both ESBSSCC's and ESBCHUIMI's SOAP Header classes:

Parameter NAMESPACE = "http://SIPRESatelites/SIPRESatelites.wsdl";

Again, thanks @Shanshan Yu for your help, time, and examples.