Category: Tutorials

BPMN Undeployment with NWDS

BPMN Undeployment with NWDS

Scenario

If you do not need a process anymore, it makes sense to undeploy a BPMN to free some resources.

Undeployment of a BPMN with NWDs

A BPMN can be undeployed with the help of the Netweaver Developer Studio (NWDS). Simply follow the steps below:

  1. Open the NWDS and connect to your PO system
  2. Open the “Deployment” perspective
  3. Wait till the list of BPMNs on the left side is loaded, click on your process and drag the object into the “Undeployment list” on the right side
  4. Click on the “Start” button

    NWDS: Process undeployment
    NWDS: Process undeployment
  5. After some seconds the process should be undeployed
SOAP Authentication with URL Parameters

SOAP Authentication with URL Parameters

Scenario

In one of my latest project we set up a SOAP communication with a partner. Unfortunately, the partner was not able to include basic authentication header when sending a SOAP message. As we did not want to expose our SOAP Sender communication channel to the web, but could not wait for the partner to find a way to use basic authentication, we looked for another solution.

Solution

It is possible to include the webservice credentials into the URL. Just add the following two parameters to the query string of your URL and replace USER and PASSWORD with the configured values.

&j_username=USER&j_password=PASSWORD

Please keep in mind that this solution is highly insecure as the username and password are exposed!

Create Webservice Mock Service with SOAP UI

Create Webservice Mock Service with SOAP UI

Scenario

If you want to see the message which is send by a SOAP, REST, XI or HTTP Receiver Communication Channel, you can use SOAP UI to create a Mock Service to log the headers and payloads of the message.

Create Mock Service with SOAP UI

  1. Create a new Project or open an existing one
  2. Right click on your request and select “New REST/SOAP MockService” (SOAP service will respond with a SOAP envelope, REST service will send back an empty response) and name it
  3. If you like to specify port and path, click on the gearwheel and specify both. Otherwise your endpoint will be listening on https://localhost:8080/

    SOAP UI: Configure Mock Service parameters
    SOAP UI: Configure Mock Service parameters
  4. Open the “OnRequest Script” Tab and paste the following line into the editor
    log.info(mockRequest.getRequestContent())
  5. Open the “Script Log” Tab and start your Mock Service with the green play button

    SOAP UI Mock Service: Log Payload of requests
    SOAP UI Mock Service: Log Payload of requests

Configure Receiver Communication Channel

  1. Find out your local IP Address (for example with this website)
  2. Make sure that your PC is reachable from PI (Firewall)
  3. Add your IP Address with the above configured port and path to the URL of your Receiver Communication Channel
  4. Send a request to your endpoint. The payload will be shown in the “Script Log”

Additional options

You can use the full scope of Groovy to write your scripts. Please find below two useful snippets to log your requests.

To log the headers use:

log.info(mockRequest.getRequestHeaders())

To write the request data into a file use:

def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def projectroot = groovyUtils.projectPath
def inputFile = new File(projectroot + "\\request.txt")

log.info("Writing request to file: " + projectroot + "\\request.txt")
inputFile.setBytes(mockRequest.getRawRequestData())

For more information of the mockRequest class in SOAP UI, check the class documentation.

Also it is possible to send custom responses, please check the SOAP UI Documentation for more information.

Find complete BPMN error traces

Find complete BPMN error traces

Scenario

During the development of a BPMN on SAP Process Orchestration you will probably arrive at a point where your Process does not work as expected. One way to find the issue is to check the traces in the Log Viewer, to find out more about the error.

Find the traces in the Log Viewer

  1. Triggered the BPMN to run again
  2. To check the BPM Status open PIMON (http://your.po:port/pimon)
  3. Go to Monitoring -> Processes and Tasks -> Manage Process
  4. Open the “History” Tab and select “Show: Advanced”. You can find the Log ID in the log entries below.
    Manage Processes: Find Log Id
    Manage Processes: Find Log Id

    If the following message is shown:

    For more details, decrease severity of log controller as described in SAP Note 1753560.

    Please check the section Increase BPMN Trace level and afterwards start again with step 1.

  5. Open  the NetWeaver Administrator (http://your.po:port/nwa)
  6. Got to Troubleshooting -> Logs and Traces -> Log Viewer
  7. Open View -> Open View -> System Logs and Traces

    Open "System Logs and Traces" view in Log Viewer
    Open “System Logs and Traces” view in Log Viewer
  8. Add a filter for Log ID and enter the Log ID out of the “Manage Processes” View

    NWA Log Viewer: Filter for LogId
    NWA Log Viewer: Filter for Log ID
  9. You can find the whole error trace in the filtered results.

Increase BPMN trace level

To increase the BPMN trace level follow the steps below:

  1. Open  the NetWeaver Administrator (http://your.po:port/nwa)
  2. Go to Configuration -> Infrastructure -> Log Configuration
  3. Select “Show: Tracing Locations”
  4. Click on “Open Filter” and filter for Location “BPMNException”
  5. Change Severity for location “ExceptionAdapter$BPMNException” to “ALL”

    NWA Log Configuration: Increase Severity for ExceptionAdapter$BPMNException
    NWA Log Configuration: Increase Severity for ExceptionAdapter$BPMNException
  6. Click on “Save Configuration” and trigger your BPMN again

Also, check out SAP Note 1753560.

“Start Process” in Process Repository is disabled

“Start Process” in Process Repository is disabled

Scenario

If you develop a BPMN, you probably have to manually trigger the process multiple times to check that everything works as expected. One way to trigger a BPMN is the usage of the “Start Process” function in the Process Repository.

You can find the Process Repository in the NetWeaver Administrator -> Processes and Tasks -> Process Repository.

Error

The “Start Process…” button in the Process Repository is disabled.

"Start Process..." button in Process Repository is disabled
“Start Process…” button in Process Repository is disabled

Solution

The role “SAP_BPM_SuperAdmin” is necessary to use the “Start process…” function. To add the role to your user, follow the steps below:

  1. Open the NetWeaver Administrator (http://your.pi/nwa)
  2. Go to Configuration -> Security -> Identity Management
  3. Select you User and open the “Assigned Roles” Tab
  4. Click on “Modify” and search for the role “SAP_BPM_SuperAdmin”
  5. Select the role, click on “Add” and afterwards on “Save”
    Add role SAP_BPM_SuperAdmin to user
    Add role SAP_BPM_SuperAdmin to user

     

After refreshing the repository browser, the “Start Process…” button should be available.

Graphical Mapping with Plain Text to XML conversion

Graphical Mapping with Plain Text to XML conversion

Scenario:

Synchronous communication between a SAP system and a non SAP websystem. The SAP system sends a request via Proxy to SAP PI, which forwards the request via SOAP to a webservice. The webservice sends a synchronous XML response back to PI and PI forwards it back to the SAP system. So far so good.

But, in case of an error, the webservice responds with a plain text message only, which fails on PI during the mapping.

Solution:

Therefore, a mapping, which wraps non XML responds into an XML envelope is necessary. As the response is mapped to a different data structure, I decided to create a standard message mapping, which checks the first character for “<“. If the character is “<“, the standard message mapping is executed. In case it is any other character, the complete message is wrapped into a XML envelope.

To create this behavior, I added the following transform function into the “Attributes and Methods”:

public void transform(TransformationInput in, TransformationOutput out) throws StreamTransformationException {
	String strXML = new String();
	String outputPayload = null;
	// convert TransformationInput and TransformationOutput to InputStream and OutputStream
	InputStream i = (InputStream) in.getInputPayload().getInputStream();
	OutputStream o = (OutputStream) out.getOutputPayload().getOutputStream();

	// convert InputStream to String
	try {
		BufferedReader inpxml = new BufferedReader(new InputStreamReader(i));
		StringBuffer buffer = new StringBuffer();
		String line="";

		while ((line = inpxml.readLine()) != null) {
			buffer.append(line);
		}
		strXML=buffer.toString();

	} catch (Exception e) {
		System.out.println("Exception Occurred");
	}

	// check if input is XML
	if (strXML.startsWith("<")) {
		// if input is XML, use regular graphical mapping
		super.transform(in, out);
	} else {
		// if input is non XML, wrap input into XML envelope
		outputPayload =
		"<?xml version='1.0' encoding='UTF-8'?>"
		+ "<ns0:message xmlns:ns0='http://tempuri.org/message'>"
		+ strXML
		+ "</ns0:message>";

		// write payload into OutputStream
		try {
			o.write(outputPayload.getBytes("UTF-8"));
		} catch (Exception e) {
			System.out.println("Exception Occurred");
		}

	}

}
JAVA Mapping in Graphical Mapping
JAVA Mapping in Graphical Mapping
Unique Filenames with AS2 Communication Channel

Unique Filenames with AS2 Communication Channel

During the implementation of multiple AS2 interfaces, I found myself very often in a situation where the communication partner expected unique AS2 filenames. Unfortunately, if you leave the filename parameter in an AS2 Receiver Communication Channel (CC) blank, the filename will always be your PIs system name. In case you enter a value like “Invoice”, the filename will always be set to “Invoice”.

Solution:

  1. You can use a dynamic configuration to generate unique filenames. Just add a UDF to you message mapping which sets the property “AS2Filename” in the namespace “http://sap.com/xi/XI/AS2/AS2“. Also, do not forget to enable the checkbox “Respect parameters” in the AS2 Communication Channels configuration.
  2. If you want to generate random, unique filenames only, a dynamic configuration feels like to much effort. Fortunately, there is an easier way to generate unique filename. Just put “%MSGID” into the “Filename” parameter of your AS2 Receiver Communication Channel. The parameter will be replaced with the PIs message ID, which should be unique. Additionally, it is possible to combine the placeholer with static text like “%MSGID.xml”.
    MSGID placeholder in filename parameter in AS2 Receiver Communication Channel
    MSGID placeholder in filename parameter in AS2 Receiver Communication Channel

    Be aware that in case your message fails, in every attempt to resend the mesasge the filename will be the same. Luckily, there are more placeholders available:

    Placeholder Description
    %SEQNUM A sequence number, starting with 1
    %RTSEQNUM A server wide sequence number, starting with 1
    %START The start time of the adapter
    %TIME The archiving period in milliseconds
    %MSGID The XI message ID

If you would like to find out more about the AS2 Adapter, check out the SAP Documentation.

Archive Files with the File Receiver Communication Channel

Archive Files with the File Receiver Communication Channel

The File Sender Communication Channel is able to move processed file to an archive directory and append the current timestamp. The File Receiver Communication Channel lacks an parameter to archive files. This is okay in most cases. The receiving system should take care of the file after processing. But, what if the demand is to move a file to an archive directory on the receiving system before overwriting it?

Solutions:

  1. It is possible to use an (cc)BPM(N) which orchestrates the archiving and the creation of the new file. You would need a configuration, a File Sender Communication Channel, a File Receiver Communication Channel and dummy interfaces to grab the old file and move it to a new directory. After the archiving is done, you can use a second configuration to store the new file. In addition, a third configuration is necessary which receives the source file and triggers the ccBPM or BPM. One BPM and three configurations – a lot afford for a simple archive.
  2. The File Receiver Communication Channel has a parameter to run script or commands on the operating system before and after creating the file. A simple move command wil do the trick.
    If your SAP Process Integration / Process Orchestration runs on Unix, use

    mv test.xml archive/test_$(date +%Y-%m-%d).xml

    If your SAP Process Integration / Process Orchestration runs on Windows, use

    ren “test.xml” “test_%date:~10,4%%date:~7,2%%date:~4,2%.xml”

    Move command in File Receiver Communicaiton Channel
    Move command in File Receiver Communicaiton Channel

    In case you use dynamic filenames, you can use the following placeholders:

    Placeholder Description
    %F target file path
    %f target file name

    Unfortunately, this will only work in NFS mode. You could create a script which connects to the FTP server and archives the file and run this script with the Communication Channel, but I would highly advise against this.

To read more about the File Receiver Communication Channel, check out the SAP Documentation.

Filter for Filename or Subject in AS2 Sender Communication Channel

Filter for Filename or Subject in AS2 Sender Communication Channel

In a current project we had the demand to send XML files from a windows server to an SAP ERP system via SAP PO. As additional requirement the files should be signed and an acknowledgment should be send back to the sender system. Therefore, we decided against the classical (S)FTP(S) and for AS2, as signature and Message Delivery Notifications (MDN) are firm elements of the AS2 specification. With mendelson AS2 there is an excellent tool available, which grabs files out of a directory and sends it to an AS2 receiver, in this case SAP PO.
Unfortunately, XML files with different data structures (Receipts, Orders, Invoices, …) were stored in the same directory and therefore send to the same URL. As the filenames looked like “Order_xxxxxxx.xml” and “Invoice_xxxxxxxx.xml” we looked for a way to separate the different files on SAP PI.

Filter for AS2 filename on SAP Process Orchestration / Process Integration

The AS2 Sender communication channel is not able to filter for a filename schema, hence you would receive all the different files with one AS2 Sender Communication Channel and route them through one Integrated Configuration (ICO). There are multiple ways to handle this:

  • You could use the EDI Separator to filter the files in a second step, but I highly recommend against using the EDI Separator in XML scenarios.
  • The filename is available as dynamic configuration and can be used as condition in an ICO.

    AS2Filename as condition in an Integrated Configuration
    AS2Filename as condition in an Integrated Configuration
  • If the structure of the XML files is different you can use an exists check as condition in your ICO.

    Check for an XPath in the condition of an ICO
    Check for an XPath in the condition of an ICO

Separating the different files with conditions in the ICO is possible, but bad practice. You have to use a dummy Sender Interface, as the data can have different structures. As a result, the selection of an Operation Mapping and the PI checks wont work. Fortunately, with mendelson AS2 it is possible to use the filename as subject. Just open the Partner configuration and type “${filename}” into the Payload Subject field.

Configure mendelson AS2 to use the filename as subject
Configure mendelson AS2 to use the filename as subject

Filter for AS2 subject on SAP Process Orchestration / Process Integration

A great feature of the AS2 Sender Communication Channel is to use regular expressions for the different expected values, like the subject. If you would like to receive only AS2 messages with a subject starting with “Order_” you can simply use “Order_.*”.

Regular Expressions in AS2 Sender Communication Channel
Regular Expressions in AS2 Sender Communication Channel

The dot has the meaning of any character and the Asterisk means zero or more occurrences. To learn more about regular expressions or test your regular expression the page regex101.com is a good place to start.

Commit fault: ASJ.ejb.005043 (Failed in component: sap.com/com.sap.aii.ad)

Commit fault: ASJ.ejb.005043 (Failed in component: sap.com/com.sap.aii.ad)

Scenario

Simple ERP to PI communication via IDOC.

Error

The IDOC is not send out to PI and the following error message is shown in transaction SM58 on ERP system:

Commit fault: ASJ.ejb.005043 (Failed in component: sap.com/com.sap.aii.ad)

Error in SM58
Error in SM58

Solution

To find out why the IDOC cannot be send to our PO system we will check the channel monitoring of the IDOC sender communication channel first. If there is no error in the channel monitor, we have to do dive deeper into the system, by using the XPI Inspector:

  1. Open the XPI Inspector on your SAP PO system.

    http://po.host.name/xpi_inspector

  2. Select Example “50 (XI Channel)” and add your IDOC sender communication channel by searching for the channel name, checking the checkbox and clicking the “Add selected” button.

    XPI Inspector configuration page
    XPI Inspector configuration page
  3. It is best to stop the XPI inspector as soon as possible. Otherwise, you have to look through thousands of log entries. Therefore, open SM58 and search for you message to be prepared to resend the IDOC (Edit -> Execute LUW (F6)).
  4. Hit the “Start” button in XPI inspector and wait till the start page is loaded.
  5. Resend the IDOC (Edit -> Execute LUW (F6)) in SM58.
  6. Click the “Stop” button in XPI inspector and wait for the result page to show up.
  7. Click on the number in the “Records Count” column of the Server Nodes table. If you have multiple Server Nodes, you have to go through all of them.

    XPI Inspector result page
    XPI Inspector result page
  8. Search for a log entry with your IDOC (you can use the browser search CTRL+F and search for your IDocNumber, MessageType or anything else)
    Client = 001
    CreationDate = 20170615
    CreationTime = 171650
    Direction = 1
    EDIMessage =
    EDIMessageGroup =
    EDIMessageType =
    EDIStandardFlag =
    EDIStandardVersion =
    EDITransmissionFile =
    ExpressFlag =
    IDocNumber = 0000000052812406
    IDocSAPRelease = 750
    IDocCompoundType = null
    IDocType = DELVRY07
    IDocTypeExtension =
    MessageCode =
    MessageFunction =
    MessageType = Z_DELV_IT
    OutputMode = 2
    SenderAddress =
    SenderLogicalAddress =
    SenderPartnerFunction =
    SenderPartnerNumber = A22001
    SenderPartnerType = LS
    SenderPort = SAPA22
    Serialization = 20170615171650
    RecipientAddress =
    RecipientLogicalAddress =
    RecipientPartnerFunction =
    RecipientPartnerNumber = RECPPRN
    RecipientPartnerType = LS
    RecipientPort = A000000003
    Status = 30
    TestFlag =
    ROOT (Type: ROOT)
    !
    +-- E2EDL20004 (Type: E1EDL20)
    !
    +-- E2EDL22001 (Type: E1EDL22)
    !
    +-- E2EDL21 (Type: E1EDL21)
    ! !
    ! +-- E2EDL23 (Type: E1EDL23)
  9. Some lines below you should find a line with a red or yellow background with your error
    Warning in XPI Inspector
    Warning in XPI Inspector
    [EXCEPTION]
    com.sap.aii.af.service.cpa.CPAObjectNotFoundException: Couldn't retrieve inbound binding for the given P/S/A values: FP=;TP=;FS=A22_001;TS=;AN=Z_DELV_IT.DELVRY07;ANS=urn:sap-com:document:sap:idoc:messages;
    at com.sap.aii.af.service.cpa.impl.lookup.CommonLookup.getInboundBinding(CommonLookup.java:211)
    at com.sap.aii.af.service.cpa.impl.lookup.CommonLookup.getInboundBinding(CommonLookup.java:175)
    at com.sap.aii.af.service.cpa.InboundRuntimeLookup.(InboundRuntimeLookup.java:88)
    at com.sap.aii.af.service.cpa.impl.lookup.AbstractLookupManager.getBinding(AbstractLookupManager.java:597)
    at com.sap.aii.af.idoc.inbound.IDocInboundProcessor.findBindingAndChannel(IDocInboundProcessor.java:792)
    at com.sap.aii.af.idoc.inbound.IDocInboundProcessor.initForIDocListProcessing(IDocInboundProcessor.java:998)
    at com.sap.aii.af.idoc.inbound.IDocInboundProcessor.process(IDocInboundProcessor.java:146)
    at com.sap.aii.af.idoc.inbound.IDocReceiverBean.onCommit(IDocReceiverBean.java:127)
    at sun.reflect.GeneratedMethodAccessor1393.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:47)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:50)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_MessageListenerType.invoke(Interceptors_MessageListenerType.java:86)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:191)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatelessInstanceGetter.invoke(Interceptors_StatelessInstanceGetter.java:23)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_SecurityCheck.invoke(Interceptors_SecurityCheck.java:25)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_ExceptionTracer.invoke(Interceptors_ExceptionTracer.java:17)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Lock.invoke(Interceptors_Lock.java:21)
    at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:179)
    at com.sap.engine.services.ejb3.runtime.impl.DefaultInvocationChainsManager.startChain(DefaultInvocationChainsManager.java:138)
    at com.sap.engine.services.ejb3.runtime.impl.DefaultEJBProxyInvocationHandler.invoke(DefaultEJBProxyInvocationHandler.java:172)
    at com.sap.engine.services.ejb3.runtime.impl.MDBProxyInvocationHandler.invoke(MDBProxyInvocationHandler.java:142)
    at com.sun.proxy.$Proxy3278.onCommit(Unknown Source)
    at com.sap.mw.jco.jra.JRA$ReaderThread.commit(JRA.java:8639)
    at com.sap.conn.jco.rt.DefaultServerWorker.onCommit(DefaultServerWorker.java:209)
    at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcServer.playbackTRfc(MiddlewareJavaRfc.java:3008)
    at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcServer.handletRfcRequest(MiddlewareJavaRfc.java:2875)
    at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcServer.listen(MiddlewareJavaRfc.java:2674)
    at com.sap.conn.jco.rt.DefaultServerWorker.dispatch(DefaultServerWorker.java:275)
    at com.sap.conn.jco.rt.DefaultServerWorker.loop(DefaultServerWorker.java:356)
    at com.sap.conn.jco.rt.DefaultServerWorker.run(DefaultServerWorker.java:232)
    at com.sap.mw.jco.jra.JRA$ReaderThread.run(JRA.java:8947)
    at com.sap.engine.services.connector.jca15.work.TaskImpl.run(TaskImpl.java:245)
    at com.sap.engine.core.thread.execution.Executable.run(Executable.java:122)
    at com.sap.engine.core.thread.execution.Executable.run(Executable.java:101)
    at com.sap.engine.core.thread.execution.CentralExecutor$SingleThread.run(CentralExecutor.java:328)

The error message

Couldn’t retrieve inbound binding for the given P/S/A values:

probably means that your ICO is not configured correctly. Check that you selected the right IDOC and sending system. Maybe you forgot to transport the configuration? Also, it could be a cache refresh problem. You can edit the description, save the configuration and activate it again to refresh the cache.