Skip to Content
Technical Articles
Author's profile photo Ivan Alekseev

Returning custom exceptions for synchronous messages in SAP PI/PO

Hello, folks.

In this article I want to talk about the opportunity to catch and return to sender-system different types of exceptions which can be occurred in synchronous scenarios in SAP PI with help of custom EJB module at sender communication channel.

For better understanding, what for do we need that module, let’s take a look at one particular example: sender-system calling SAP PI SOAP service synchronously, then SAP PI calling receiver-system, let’s say some database(JDBC-receiver) and returning response to original sender-system. One of requirements from sender-system to this service could be following: it expects response message in one strict format no matter was database call successful or for some reason an exception was occurred during executing integration scenario. Could be that sender-system expects some certain elements to be filled with values in case of exception or error.

Example: sender-system sends SOAP request with CompanyID expecting to get some extra info about that company from receiver-system.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:test:company">
	<soapenv:Header/>
	<soapenv:Body>
		<urn:CompanyInfo_Request>
			<CompanyID>771575035533</CompanyID >
		</urn:CompanyInfo_Request>
	</soapenv:Body>
</soapenv:Envelope>

In case of successful call, response message from database going to look like this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:test:company">
	<soapenv:Header/>
	<soapenv:Body>
		<urn:CompanyInfo_Response>
			<status>0</status>
			<error_text/>		 
			<DateExcerpt>2017-04-28</DateExcerpt>
			<OGRN>317774600137769</OGRN>
			<DateOGRN>2017-03-22</DateOGRN>
			<INN>771575035533</INN>
			<CodeTypeIP>1</CodeTypeIP>
			<NameTypeIP>1</NameTypeIP>
			<PhysicalPerson>
				<DateStart>2017-03-22</DateStart>
				<GRN>317774600137769</GRN>
				<PhysicalNameRus>
					<FirstName>Sergey</FirstName>
					<LastName>Alekseev</LastName>
					<MiddleName>Aleksandrovich</MiddleName>
				</PhysicalNameRus>
			</PhysicalPerson>
		</urn:CompanyInfo_Response>
	</soapenv:Body>
</soapenv:Envelope>

Note that response message has <status> and <error_text> elements: in case of successful DB call <status> filled with “0” in response message mapping and <error_text> is empty. But in case if some type of error taken place during the execution of this scenario, sender-system expects <status> to be filled with certain error-code and <error_text> filled with error description.

Now, imagine database server is unavailable or user which credentials used in receiver communication channel has been locked. What sender-system will receive in this case? Response message will look approximately like this (Note: In case of HTTP_AAE or REST sender adapters response message will look slightly different but not tremendously helpful):

<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP:Body>
		<SOAP:Fault>
			<faultcode>SOAP:Server</faultcode>
			<faultstring>Server Error</faultstring>
			<detail>
				<s:SystemError xmlns:s="http://sap.com/xi/WebService/xi2.0">
					<context>XIAdapter</context>
					<code>ADAPTER.JAVA_EXCEPTION</code>
					<text>com.sap.engine.interfaces.messaging.api.exception.MessagingException: com.sap.engine.interfaces.messaging.api.exception.MessagingException: Error when attempting to get processing resources: com.sap.aii.af.lib.util.concurrent.ResourcePoolException: Unable to create new pooled resource: DriverManagerException: Cannot establish connection with the registered driver. com.microsoft.sqlserver.jdbc.SQLServerDriver returns: Login failed for user 'test1'..
: com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user 'test1'. 
at com.sap.aii.adapter.soap.web.SOAPHandler.processSOAPtoXMB(SOAPHandler.java:772)
at com.sap.aii.adapter.soap.web.MessageServlet.doPost(MessageServlet.java:530)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
at javax.servlet.http.HttpServlet.__AW_service(HttpServlet.java:847)
at javax.servlet.http.HttpServlet.service(HttpServlet.java)
. . .
					</text>
				</s:SystemError>
			</detail>
		</SOAP:Fault>
	</SOAP:Body>
</SOAP:Envelope>

As we can see, in case if any exception has been occurred while message being processed through integration engine pipeline, client system will receive response message with error stack trace in strictly defined structure. Response operation mapping being ignored and there is no standard way to change SAP-defined adapter exception message structure.

In order to overcome this problem I have developed custom EJB module, which can be used on sender communication channel supporting synchronous communication (SOAP, REST, HTTP adapters). In case of successful processing message through integration engine pipeline, client system will receive response message from receiver-system – standard processing of response message from receiver-system won’t be affected by this custom module. But in case if some exception occurred at any stage of integration engine pipeline execution (receiver determination, operation mapping, receiver system call etc.), custom module will catch that exception and call certain operation mapping, which name we’ll submit as a parameter of this module. Original message will be processed to this operation mapping (BI or AM version depending on a module parameter value) and exception description if needed. Result of execution this operation mapping will return to a sender system, so we can define structure of this response message for those cases when exception during pipeline message processing occurred.

EAR project which is ready for deploy can be downloaded from github repository by following link:

https://github.com/IAlekseev91/customModulePI

To use this module you will have to remove standard module entry in Processing Sequence on the “Module” tab in sender communication channel. Exactly replace standard module entry (in many cases – CallSapAdapter) with localejbs/CustomAdapterBean. In case if you want or need to use standard for default module parameters, you may as well use them with CustomAdapterBean.



Also I do recommend you to use key “cab” for this custom module because it will generate entries in message audit log and communication channel monitor processing log starting with this prefix.

Table with parameters available for use with CustomAdapterBean module:

Parameter name Available values Default value Obligatory parameter Description
catchException true/false false no True – when exception/error being occurred, its being caught by module and processed considering parameters listed below.
False – module works just as a standard module which has been removed from processing sequence.
Being used for switching to standard message processing on the go.
moduleName string value localejbs/CallSapAdapter no Name of standard module that has been removed from processing sequence.
operationSpecific true/false false no True – in case of multiple operations on sender service interface for every operation distinct operation mapping will be executed in case of exception/error.
operationMappingName string value yes, when operationSpecific = false Operation mapping name which going to be executed upon exception/error while processing message.
Has to be unique across the whole ESR.
operationName.*
where * – serial number of service interface operation
string value yes, when operationSpecific = true Name of service interface operation.
operationMappingName.*
where * is a serial number of service interface operation, which particular operation mapping will be called for
string value yes, when operationSpecific = true Operation mapping name which is going to be executed for particular service interface operation in case of exception/error while processing message.
When set up as “null” no operation mapping for particular service interface operation will be executed. Sender-system will receive error message in default adapter format.
Has to be unique across the whole ESR.
saveOriginalMessage true/false false no True – original request from sender system (BI version) will be transferred to error handling operation mapping from module’s parameter.
Vice versa, when set as “false”, AM version of original request will be transferred to error handling operation mapping from module’s parameter.
Keep in mind “false” value requires additional attention to message structures when creating ErrorHandling operation mapping.
For example, if exception/error will take place before AM version of original request has been created in pipeline, module will try to execute ErrorHandling operation mapping for BI version of original request.
saveException true/false false no True – error description being saved in attachment with opportunity of its following extraction in operation mapping.
wsUser string value yes Name of SAP PI user account. User has to be able to call web services (SAP_XI_APPL_SERV_USER role)
pwd.wsPassword string value yes User account password.
saveLogVersion true/false false no True – after execution of operation mapping which has been set up in parameter message version being saved in Message Editor: Versions, displayed with caption “Fault”.

If  SAP PI/PO landscape you work with includes SAP Web Dispatcher, you will need to submit the address of SAP WD to this custom module parameter. To accomplish that you will need to edit application settings: host:port/nwa -> Configuration -> Infrastructure -> Application Modules. On the overview tab you filter applications by name “moduleCustomAdapterEJB.jar” and then input the web address of SAP Web Dispatcher as value for parameter “addressSAPWD” at the “Environment and References” tab.



Let’s make an example considering all mentioned above using CustomAdapterBean.

Parameters for module will look like this:

Parameter name Parameter value
catchException true
operationMappingName om_getCompany_errorHandling
saveException true
saveOriginalMessage true
wsUser pi_user
pwd.wsPassword *****

Beforehand, in Enterprise Service Builder operation mapping om_getCompany_ErrorHandling has been created. It will be called by custom module upon catching exception while processing message through integration engine pipeline. Source operation is going to be sender service interface original operation, for target operation you going to have to create service interface intentionally (let’s call it *_errorHandling) and set up as a request structure the one you wish sender system to receive in case of exception during message processing through pipeline (in many cases it’s going to be same as original sender service interface operation response structure).

As far as sender service interface operation is synchronous, target operation also has to be synchronous. Meanwhile response structure does not have any meaning and won’t be used ever – operation mapping will ignore it.

It is only important to set mapping programm for request which is going to create target response structure for original sender service interface operation and will be received by sender-system. For the sake of our example we can use next type of message mapping:



Element <status> we will fill with digit value signalizing about exception during message processing.



Element <error_text> we’ll fill with error description text concatenated with value of element <CompanyID> from original request message.

Error description text can be extracted with help of user defined function “getAttachmentById”. As mentioned above, error text will be saved in attachment (by setting value of custom module parameter “saveException” to “true”), so for it’s extraction UDF will be needed. Check code of this UDF below:


public String getAttachmentById(String id, Container container) throws StreamTransformationException {
	InputAttachments inputAttach = container.getGlobalContainer().getInputAttachments();
	if (inputAttach.areAttachmentsAvailable()) {
		Attachment attach = inputAttach.getAttachment(id);
		if (attach == null) {
			throw new StreamTransformationException("Unable to find attachment with id: " + id);
		}
		return new String(attach.getContent());
	} else {
		throw new StreamTransformationException("Attachments not available. Please check that the parameter 'Read attachment' in operation mapping is set to true");
	}
}

Custom module will save attachment under name “Exception” so this name has to be used as an input parameter for UDF.

Let’s see what sender-system will receive in case of error.

Request message from sender-system:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:test:company">
	<soapenv:Header/>
	<soapenv:Body>
		<urn:CompanyInfo_Request>
			<CompanyID>771575035533</CompanyID >
		</urn:CompanyInfo_Request>
	</soapenv:Body>
</soapenv:Envelope>

Response:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:test:company">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:CompanyInfo_Response>
		 <status>1</status>
		 <error_text>Error while get info for Company with id 771575035533:  com.sap.engine.interfaces.messaging.api.exception.MessagingException: com.sap.engine.interfaces.messaging.api.exception.MessagingException: Error when attempting to get processing resources: com.sap.aii.af.lib.util.concurrent.ResourcePoolException: Unable to create new pooled resource: DriverManagerException: Cannot establish connection with the registered driver. com.microsoft.sqlserver.jdbc.SQLServerDriver returns: Login failed for user 'test1'..: com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user 'test1'</error_text>		 
      </urn:CompanyInfo_Response>
   </soapenv:Body>
</soapenv:Envelope>

As we can see, in case if there was an error occurred while trying to establish connection to database (receiver-system), we have received response in desired structure.

I’ll be glad if this module will help you out with structuring responses according to format defined by sender-system.

Thanks for reading and good luck.

Thanks for help to Ivan Mamontov.

Assigned Tags

      36 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Iddo Rijsdijk
      Iddo Rijsdijk

      Good blog, Ivan. This looks very helpful. I will definitely try this out when the time is right!

      Author's profile photo Yuliya Vladykova
      Yuliya Vladykova

      Thanks for the blog, I will try to do it.

      Author's profile photo Apu Das
      Apu Das

      Hey Ivan,

      Good blog. Is it possible to share the source code?

       

       

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hi there.

      Thanks for reading the blog.

      Yeah, i can not list the source code anywhere but you can download ear-project from GitHub repository and decompile moduleCustomAdapterEJB.jar to get the source code.

      Author's profile photo Julia Nedic-Seuberth
      Julia Nedic-Seuberth

      Hello Ivan,

       

      thank you very much for this post.

      Can this also be used for the WS_AAE adapter?

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello Julia.

      Your are welcome.

      Yes this module can be used with this adapter type as well.

      Author's profile photo Nikiforos Chouzouris
      Nikiforos Chouzouris

      Hi Ivan,

      thanks for this 🙂

      On our development system this worked like a charm. Easy and fast.

      Sadly we are running into some issues on our QA system. I think the issues stem from the fact that the system is an extended AAE.

      When catching an exception the module has difficulties loading the original message, because the URL /rep/support/SimpleQuery doesn't exist on the extended AAE. (see screenshot)

      Any idea if there is a workaround for this?

      Thanks!

      Greetings from Vienna,

      Nick

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello Nick.

      Glad to know it's been youseful.

      Thanks for your feedback.

      I kind of foreseen that case: Parameter “addressSAPWD” which i mentioned in original post can help in this situation as well, just put your Central AAE http://host:port as it's value.

       

      Cheers from Moscow. 🙂

      Ivan

      Author's profile photo Nikiforos Chouzouris
      Nikiforos Chouzouris

      Hi Ivan,

      you rock 🙂

      It worked!

       

      Author's profile photo Youssef El Ouatiq
      Youssef El Ouatiq

      Hi Ivan,

      thank you for this very usefull Blog and Solution, Can the Module also be used in Odata Adapter?

      Merry Christmas and thank you

      Youssef

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello, Youssef.

      Good question. I do not know the answer though: OData – quite rarely used adapter here. I suspect, it might but you’d have to check that yourself.
      I’ll appreciate any info about the test

      Merry Christmas ?

      Regards, Ivan

      Author's profile photo Soporte Notas
      Soporte Notas

      Hi. Can be used for RFC Adapter?

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello.

      Yes, this type is supported too.

      Author's profile photo Soporte Notas
      Soporte Notas

      Oh.

       

      Thanks a lot.

      Author's profile photo Jorge Gomez Lopez
      Jorge Gomez Lopez

      Hi Ivan,

       

      This seems great for a problema I'm having, but it seems that the ear is not deployable on PI 7.11 (for the lack of the Rest Adapter)

      Do you think you could recompile it for this PI version? (or handle it the source to me, in order to recompile it myself)?

      Thanks!

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author
      Hi Jorge.
      Thank you for your feedback.
      Yes, I have recompiled the project without classes’ dependencies for REST adapter. The updated archive is available here:
      Unfortunatly, I don’t have PI version 7.11, so I can’t check the updated archive for this version but I hope it could solve your problem.
      Hope this helps, I will wait your further comments.
      Author's profile photo Functional Consultants
      Functional Consultants

      Hi Ivan Alekseev ,

       

      I am getting Module ejb exception while using it for RFC sender adapter. PFB screenshot.

       

       

      Regards,

      Rajesh

       

      Author's profile photo Functional Consultants
      Functional Consultants

      Hi Ivan,

       

      Please help, how to register RFC for push_channel_status..

       

       

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hi Rajesh.

      Thanks for you feedback.

      I fixed the bug. Please, download the updated archive.

      Regards, Ivan

      Author's profile photo Functional Consultants
      Functional Consultants

      Hi Ivan,

       

      Thanks Ivan for the quick response..I will test it and update you...

       

      Thank you so much!

      Regards,

      Rajesh

      Author's profile photo Kerem Tarhan
      Kerem Tarhan

      Hi Ivan,

      Your solution works perfectly for the errors at receiver side but not at sender side. I tried your module for the errors at SOAP sender channel side but it doesnt work. I exposed a SOAP

      service. The client sometimes send "&" character in xml fields and it gets the parser error before

      adapter modules. Is there another way other that writing our own soap adapter? What do you think?

      BRlogviewer

      logviewer

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hi Kerem

      Thanks for your feedback.

      Firstly I'd like to comment your message about error exception in SOAP sender channel. It works a bit different: yes, errors for sender channel are intercepted too, but only after they appears in chain handled module. For example, validation error in Sender channel is intercepted with this module.

      Now about your error: it wasn't intercepted because this error had happened before the message appeared in channel modules (as far as I understand the error had happened inside the servlet XISOAPAdapter/MessageServlet before the message went to Chain modules).

      If you need to intercept such types of errors, it seems to me its pretty hard to solve the issue with the custom SOAP adapter, because (as I wrote above) this error happens before SAP modules start to work - and we do not have builtin (standart) options to change this servlet. For me one the ways to solve the issue is using HTTP sender channel - this channel is able to receieve messages in any format. So you can create your own module with all necessary checks with deleting SOAP envelope messages for further processing.

      Hope this help,

      Regards, Ivan

      Author's profile photo Ray Hu
      Ray Hu

      Hello Ivan,

       

      Very nice sharing.

      I'm getting java.lang.NoClassDefFoundError: org/jsoup/Connection$Method when calling OM with Jsoup. Any suggest for such error?

      javax.ejb.EJBException: nested exception is: java.lang.RuntimeException: java.lang.NoClassDefFoundError: org/jsoup/Connection$Method
      java.lang.RuntimeException: java.lang.NoClassDefFoundError: org/jsoup/Connection$Method
      at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:99)
      at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166)

       

      Best Regards,

      Ray

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hi, Ray.

      Excuse me for not responding sooner.

      I've checked this module with using operation mapping, that calls external classes (library jsoup in this case), and it worked witout errors. So i have a guess you have an error in creation your operation mapping (without my module). May i ask you to check operability of your operation mapping by using test button in ESR - in this case this error appears as well?

      Regards, Ivan.

       

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

      Thank you for the blog.

      We are using the adapter module, however, we have encounter error while calling the module - CallSAPAdapter

      Error -

      Returning to application. Exception : com.sap.engine.interfaces.messaging.api.exception.MessagingException: Cannot invoke call from within a transactional context.

       

      Could you please let us know if you have come across this error?

      We are on SAP PO 7.5.

       

      Regards,

      Meenakshi Pradhan

       

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello, Meenakshi.

      Could you please give me a little more details (adapter type, channel settings, etc.) about the integration configuration (ICo) where you are using this module. Does it have any special settings?

      Regards, Ivan.

       

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

      Thank you for replying.

      The scenario is -

      1. Synchronous scenario - Soap to proxy scenario
      2. Sender Soap channel with Do not use SOAP Envelope checked.
      3. In the SOAP webservice url "nosoap=true" is used.

      While testing the interface with the custom adapter module we are getting the exception.

      Exception -

      Returning to application. Exception : com.sap.engine.interfaces.messaging.api.exception.MessagingException: Cannot invoke call from within a transactional context.

      Regards,

      Meenakshi Pradhan

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello, Meenakshi.

      Thanks for information.

      I checked - this scenario works for me (both a successful call and an error (stop the receiver channel)).

      Сould you show your audit log of message?

      Regards, Ivan.

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

       

      Please find below the screenshot of the audit log  - 

       

      Regards,

      Meenakshi Pradhan

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello, Meenakshi.

      Can you return to the default channel configuration (return the CallSapAdapter module) and retry the call?

      Regards, Ivan.

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

      Thank you. The module is now working and we are able to get the response.

      However, the module works fine if the web dispatcher url is http and fails when the url is https.

      The error - CAB: Error while send request/parse response to/from SimpleQuery:
      Unable to find tag <TABLE> with results!

      The simple query response is not same when the web dispatcher url is http vs https.

      Does the module only work for http and not with https ?

      Regards,

      Meenakshi Pradhan

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello, Meenakshi.

      Thanks for your reply.

      Actually, the module does not support URL specified as https://* in param addressSAPWD. I assumed that SimpleQuery call is, in fact , internal SAP PO call, so there are no reasons to support https.

      I could be able to make desired changes if you really need.

      Regards, Ivan.

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

      Thank you for getting back to me.

      I agree SimpleQuery is internal to SAP PO, however, the requirement is to use https instead of http.

      Could you please let us know how it can be done?

       

      Regards,

      Meenakshi Pradhan

       

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

      Could you please share the adapter module that would work with https ?

      As we have the requirement to use https instead of http.

      Thank you.

      Regards,

      Meenakshi Pradhan

      Author's profile photo Ivan Alekseev
      Ivan Alekseev
      Blog Post Author

      Hello, Meenakshi.

      I've done changes in the module - now it supports https protocol.

      New version is available on github.

      Regards, Ivan.

      Author's profile photo Meenakshi Pradhan
      Meenakshi Pradhan

      Hi Ivan,

      Thank you.

      The module is working.

      Regards,

      Meenakshi Pradhan