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: <INVALID OREF>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"
XMLXML
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
ObjectScriptObjectScript
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>
}
}
ObjectScriptObjectScript
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>
}
}
ObjectScriptObjectScript
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>
}
}
ObjectScriptObjectScript
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.
Does your ESBCHUIMI client class have the following code?
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:
We have also tried to call it as follows and it stills failling:
Being the Error code as follows:
faultstring=Error del servidor de aplicaciones.
faultactor=
detail=
<error xmlns="http://SCS.Servicios/SIPRESatelites">
<text>ERROR #5002: Error de cache: <INVALID OREF>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.
I think there may be an issue with the namespace of the header class. Perhaps you can modify or copy a new header class and modify its namespace to http://SCS.Servicios/SIPRESatelites
like this
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:
Again, thanks @Shanshan Yu for your help, time, and examples.