Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
0 Kudos
556
Inside of the aBPM Framework exists a lot of features and functionalities that helps to realize a custom scenario very quickly, but in some aBPM custom scenarios a JMS Queue is necessary to store trigger messages before an aBPM process instance was persist or an aBPM/BPM process was started. Inside of the following blog you will find a solution for using JMS queues inside of an aBPM Scenario.

Use case:

The aBPM/BPM process could not be started successfully, e.g. in case of an exception or relevant data could not be read before the aBPM/BPM process could be persist or started. In such cases the initial start trigger would be swollow or get lost with no trace of an aBPM process or BPM process with the exception of a log entry inside the default trace. To prevent this behaviour the initial start trigger can be stored into a JMS queue and can be consumed by a message driven bean (MDB).

Hint: There are a lot of technical backgrounds available on help.sap.com about Using Java Message Service inside the SAP Netweaver AS Java. Please take a look into this reference before you continue with this blog.

aBPM solution environment:

The aBPM szenario of this blog is an "inquiry process" that will be started via a web service call from an external system. The implementation of this web service is a generated stateless session bean from a WSDL file that was created inside Enterprise Service Repository (ESR).

The technical implementation of the inquiry process relevant prerequisites (read inquiry data, persist and start aBPM process, etc.) are encapsulated into a "start inquiry process provider" (not part of this blog) that returns a boolean value (true/false). True if the user that should get the inquiry does not exist inside of the UME/user store otherwise false. In case of true an inquiry process cancel message will be triggered with a second JMS queue.

Solution:

The stateless session bean of the web service that receives the trigger to start the inquiry process was generated inside NWDS. A typical implementation of this EJB could look like this:
package <vendor>.inquiry.start;

import <...>

@WebService(portName = "StartInquiryProcessAbs_Port", serviceName = "StartInquiryProcessAbs_Service", endpointInterface = "<vendor>.inquiry.start.StartInquiryProcessAbsLocal", targetNamespace = "http://<vendor>/inquiry/inquiryprocess", wsdlLocation = "META-INF/wsdl/<vendor>/inquiry/start/StartInquiryProcessAbs/StartInquiryProcessAbs.wsdl")
@Stateless
public class StartInquiryProcessAbs implements StartInquiryProcessAbsLocal {

private static final com.sap.tc.logging.Location logger = com.sap.tc.logging.Location.getLocation(StartInquiryProcessAbs.class);

@Resource
private SessionContext ctx;

public void startInquiryProcessAbs(<vendor>.inquiry.start.StartInquiryProcessRequest startInquiryProcessRequestMessage) {
StartInquiryProcessProvider startInquiryProcessProvider = new StartInquiryProcessProvider();
startInquiryProcessProvider.startInquiryProcess(startInquiryProcessRequestMessage, ctx.getCallerPrincipal().getName());
}
}

In this implementation the start provider could run into an exception and the original trigger message will be lost. To prevent this issue a JMS message can be stored into a JMS queue.

There are 2 options to get a reference to the JMS queue:

  1. via resource injection (@Resource)
    or

  2. via JNDI lookup


Option 1 can only be used in case one JMS Queue will be used inside an EJB. In this blog two JMS queues will be used (1. to store the initial start trigger, 2. to store the process cancel trigger in case the inquiry user does not exists). That is the reason for the approach of JNDI lookups inside the following source code:
package <vendor>.inquiry.start;

import <...>

@WebService(portName = "StartInquiryProcessAbs_Port", serviceName = "StartInquiryProcessAbs_Service", endpointInterface = "<vendor>.inquiry.start.StartInquiryProcessAbsLocal", targetNamespace = "http://<vendor>/inquiry/inquiryprocess", wsdlLocation = "META-INF/wsdl/<vendor>/inquiry/start/StartInquiryProcessAbs/StartInquiryProcessAbs.wsdl")
@Stateless
public class StartInquiryProcessAbs implements StartInquiryProcessAbsLocal {

private static final com.sap.tc.logging.Location logger = com.sap.tc.logging.Location.getLocation(StartInquiryProcessAbs.class);

@Resource
private SessionContext ctx;

private static final com.sap.tc.logging.Location logger = com.sap.tc.logging.Location.getLocation(StartInquiryProcessAbs.class);

@Resource
private SessionContext ctx;
//JNDI lookup is used regarding @Resouce was not working inside the exception of startInquiryProcessAbs()
// @Resource(name = "<vendor>QueueConnectionFactory")
// private QueueConnectionFactory <vendor>QueueConnectionFactory;
// @Resource(name = "InquiryPrcQueue")
// private Queue inquiryPrcQueue;
// @Resource(name = "InquiryPrcCancelQueue")
// private Queue inquiryPrcCancelQueue;

public void startInquiryProcessAbs(<vendor>.inquiry.start.StartInquiryProcessRequest startInquiryProcessRequestMessage) {
try {
HashMap<String, String> requestParams = new HashMap<String, String>();
requestParams.put(StartInquiryProcessConstants.MASTERGUID, startInquiryProcessRequestMessage.getMasterGUID());
requestParams.put(StartInquiryProcessConstants.SENDERSID, startInquiryProcessRequestMessage.getSenderSID());
requestParams.put(StartInquiryProcessConstants.BUSINESSUNIT, startInquiryProcessRequestMessage.getBusinessUnit().value());
requestParams.put(StartInquiryProcessConstants.DOCUMENTTYPE, startInquiryProcessRequestMessage.getDocumentType().value());
requestParams.put(StartInquiryProcessConstants.COUNTRYCODE, startInquiryProcessRequestMessage.getCountryCode());
requestParams.put(StartInquiryProcessConstants.QUESTIONID, startInquiryProcessRequestMessage.getQuestionID());
requestParams.put(StartInquiryProcessConstants.INQUIRYUSERID, startInquiryProcessRequestMessage.getInquiryUserID());
StartInquiryProcessProvider startInquiryProcessProvider = new StartInquiryProcessProvider();
if (startInquiryProcessProvider.startInquiryProcess(requestParams, ctx.getCallerPrincipal().getName())) {
String cancelMessageId = this.sendMessageIntoInquiryPrcCancelQueue(requestParams);
logger.infoT("InquiryPrcCancelMessage was successfully stored into JMS queue \"InquiryPrcCancelQueue\" with message id " + cancelMessageId);
}
} catch (Exception e) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "aBPM inquiry process could not be started", e);
String messageId = this.sendMessageIntoInquiryPrcStartQueue(startInquiryProcessRequestMessage);
SimpleLogger.trace(Severity.ERROR, logger, "aBPM InquiryPrcStartMessage was successfully stored into JMS queue \"InquiryPrcQueue\" with message id " + messageId);
}
}

private String sendMessageIntoInquiryPrcStartQueue(<vendor>.inquiry.start.StartInquiryProcessRequest startInquiryProcessRequestMessage) {
QueueConnection queueConnection = null;
QueueSession queueSession = null;
QueueSender queueSender = null;
MapMessage message = null;
String messageId = null;
try {
InitialContext context = new InitialContext();
//JNDI lookup is used regarding @Resouce was not working inside the exception of startInquiryProcessAbs()
QueueConnectionFactory <vendor>QueueConnectionFactory = (QueueConnectionFactory) context.lookup("jmsfactory/<virtualprovider>/<vendor>QueueConnectionFactory");
queueConnection = <vendor>QueueConnectionFactory.createQueueConnection("<theJMSPrincipal>", "<theJMSCredential>");
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue inquiryPrcQueue = (Queue) context.lookup("jmsqueues/<virtualprovider>/InquiryPrcQueue");
queueSender = queueSession.createSender(inquiryPrcQueue);
message = queueSession.createMapMessage();
message.setString(StartInquiryProcessConstants.MASTERGUID, startInquiryProcessRequestMessage.getMasterGUID());
message.setString(StartInquiryProcessConstants.SENDERSID, startInquiryProcessRequestMessage.getSenderSID());
message.setString(StartInquiryProcessConstants.BUSINESSUNIT, startInquiryProcessRequestMessage.getBusinessUnit().value());
message.setString(StartInquiryProcessConstants.DOCUMENTTYPE, startInquiryProcessRequestMessage.getDocumentType().value());
message.setString(StartInquiryProcessConstants.COUNTRYCODE, startInquiryProcessRequestMessage.getCountryCode());
message.setString(StartInquiryProcessConstants.QUESTIONID, startInquiryProcessRequestMessage.getQuestionID());
message.setString(StartInquiryProcessConstants.INQUIRYUSERID, startInquiryProcessRequestMessage.getInquiryUserID());
message.setString(StartInquiryProcessConstants.CALLERPRINCIPALUSERID, ctx.getCallerPrincipal().getName());

JAXBElement<StartInquiryProcessRequest> jaxbEle = new ObjectFactory().createStartInquiryProcessRequestMessage(startInquiryProcessRequestMessage);
JAXBContext jaxbContext = JAXBContext.newInstance(StartInquiryProcessRequest.class);
Marshaller marshaller = jaxbContext.createMarshaller();
StringWriter strWriter = new StringWriter();
marshaller.marshal(jaxbEle, strWriter);
message.setString(StartInquiryProcessConstants.ORIGINALTRIGGERPAYLOAD, strWriter.toString());

queueSender.send(message);
messageId = message.getJMSMessageID();
} catch (JMSException jmsExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JMSException occurred inside sendMessageIntoInquiryPrcStartQueue()", jmsExc);
throw new RuntimeException(jmsExc);
} catch (JAXBException jaxbExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JAXBException occurred inside sendMessageIntoInquiryPrcStartQueue()", jaxbExc);
throw new RuntimeException(jaxbExc);
} catch (NamingException nameExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "NamingException occurred inside sendMessageIntoInquiryPrcStartQueue()", nameExc);
throw new RuntimeException(nameExc);
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException jmsExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JMSException occurred inside sendMessageIntoInquiryPrcStartQueue() by closing QueueConnection", jmsExc);
throw new RuntimeException(jmsExc);
}
}
}
return messageId;
}

private String sendMessageIntoInquiryPrcCancelQueue(HashMap<String, String> requestParams) {
QueueConnection queueConnection = null;
QueueSession queueSession = null;
QueueSender queueSender = null;
MapMessage message = null;
String messageId = null;
try {
String jmsPrincipal = "<theJMSPrincipal>";
InitialContext context = new InitialContext();
//JNDI lookup is used regarding @Resouce was not working inside the exception of startInquiryProcessAbs()
QueueConnectionFactory <vendor>QueueConnectionFactory = (QueueConnectionFactory) context.lookup("jmsfactory/<virtualprovider>/<vendor>QueueConnectionFactory");
queueConnection = <vendor>QueueConnectionFactory.createQueueConnection(jmsPrincipal, "<theJMSCredential>");
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue inquiryPrcCancelQueue = (Queue) context.lookup("jmsqueues/<virtualprovider>/InquiryPrcCancelQueue");
queueSender = queueSession.createSender(inquiryPrcCancelQueue);
message = queueSession.createMapMessage();
// correlation condition params inside process
// 1. MasterGUID
message.setString(TerminateInquiryProcessConstants.MASTERGUID, (String) requestParams.get(StartInquiryProcessConstants.MASTERGUID));
// 2. SenderSID
message.setString(TerminateInquiryProcessConstants.SENDERSID, (String) requestParams.get(StartInquiryProcessConstants.SENDERSID));
// 3. BusinessUnit
message.setString(TerminateInquiryProcessConstants.BUSINESSUNIT, (String) requestParams.get(StartInquiryProcessConstants.BUSINESSUNIT));
// params for protocol interface
// 1. Processor = JMSPrincipal
message.setString(TerminateInquiryProcessConstants.PROCESSOR, jmsPrincipal);
// 2. Reason = cancel reason
// IPO is a technical user = default language English, that means cancel reason will not be translated at the moment
message.setString(TerminateInquiryProcessConstants.REASON, MessageFormat.format(
"Automated inquiry process termination regarding the param InquiryUserID {0} could not be found inside ActiveDirectory/LDAP.", (String) requestParams
.get(StartInquiryProcessConstants.INQUIRYUSERID)));
queueSender.send(message);
messageId = message.getJMSMessageID();
} catch (JMSException jmsExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JMSException occurred inside sendMessageIntoInquiryPrcCancelQueue()", jmsExc);
throw new RuntimeException(jmsExc);
} catch (NamingException nameExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "NamingException occurred inside sendMessageIntoInquiryPrcCancelQueue()", nameExc);
throw new RuntimeException(nameExc);
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException jmsExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JMSException occurred inside sendMessageIntoInquiryPrcCancelQueue() by closing QueueConnection", jmsExc);
throw new RuntimeException(jmsExc);
}
}
}
return messageId;
}
}

In case of an exception inside the start inquiry process provider a JMS map message will be created and send into the InquiryPrcQueue. The JMS map message contains all releavant data for the start inquiry process provider plus the marshalled payload of the original trigger message for analytics.

In case of no exception and the user doesn't exists inside the user store another JMS map message will be created and send into the InquiryPrcCancelQueue. This JMS message contains all relevant data for a cancellation of the BPM process (values for the correlation condition).

The usage of constants inside of the map message keys is only to set and get the values in and from the map message in an elegant way.

The next step is to consume those JMS messages via a MDB. Exemplary the MDB for the InquiryPrcQueue will be shown as follows:
package <vendor>.inquiry.start;

import <...>

/**
* Message-Driven Bean implementation class for: StartInquiryProcessMDB
*
*/
@DeclareRoles(value={"BPMTriggerRole"})
@RunAs(value="BPMTriggerRole")
@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") }, mappedName = "InquiryPrcQueue")
public class StartInquiryProcessMDB implements MessageListener {

private static final com.sap.tc.logging.Location logger = com.sap.tc.logging.Location.getLocation(StartInquiryProcessMDB.class);

@Resource(name = "<vendor>QueueConnectionFactory")
private QueueConnectionFactory <vendor>QueueConnectionFactory;
@Resource(name = "InquiryPrcCancelQueue")
private Queue inquiryPrcCancelQueue;
@EJB
private PropertyProviderLocal propertyProvider;

public void onMessage(Message message) {
try {
if (message instanceof MapMessage) {
MapMessage mapMessage = (MapMessage) message;
HashMap<String, String> requestParams = new HashMap<String, String>();
requestParams.put(StartInquiryProcessConstants.MASTERGUID, mapMessage.getString(StartInquiryProcessConstants.MASTERGUID));
requestParams.put(StartInquiryProcessConstants.SENDERSID, mapMessage.getString(StartInquiryProcessConstants.SENDERSID));
requestParams.put(StartInquiryProcessConstants.BUSINESSUNIT, mapMessage.getString(StartInquiryProcessConstants.BUSINESSUNIT));
requestParams.put(StartInquiryProcessConstants.DOCUMENTTYPE, mapMessage.getString(StartInquiryProcessConstants.DOCUMENTTYPE));
requestParams.put(StartInquiryProcessConstants.COUNTRYCODE, mapMessage.getString(StartInquiryProcessConstants.COUNTRYCODE));
requestParams.put(StartInquiryProcessConstants.QUESTIONID, mapMessage.getString(StartInquiryProcessConstants.QUESTIONID));
requestParams.put(StartInquiryProcessConstants.INQUIRYUSERID, mapMessage.getString(StartInquiryProcessConstants.INQUIRYUSERID));
try {
StartInquiryProcessProvider startInquiryProcessProvider = new StartInquiryProcessProvider();
if (startInquiryProcessProvider.startInquiryProcess(requestParams, mapMessage.getString(StartInquiryProcessConstants.CALLERPRINCIPALUSERID))) {
String cancelMessageId = this.sendMessageIntoInquiryPrcCancelQueue(requestParams);
logger.infoT("InquiryPrcCancelMessage was successfully stored into JMS queue \"InquiryPrcCancelQueue\" with message id " + cancelMessageId);
}
} catch (Exception e) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "aBPM inquiry process could not be started", e);
throw new RuntimeException(e);
}
} else {
String errorMsg = "StartInquiryProcessMDB: Message is of wrong type: " + message.getClass().getName() + ", expected " + MapMessage.class.getName();
logger.errorT(errorMsg);
throw new RuntimeException(errorMsg);
}
} catch (JMSException e) {
String errorMsg = "StartInquiryProcessMDB: JMSException inside onMessage()";
logger.errorT(errorMsg);
throw new RuntimeException(errorMsg);
}
}

private String sendMessageIntoInquiryPrcCancelQueue(HashMap<String, String> requestParams) {
QueueConnection queueConnection = null;
QueueSession queueSession = null;
QueueSender queueSender = null;
MapMessage message = null;
String messageId = null;
try {
String jmsPrincipal = "<theJMSPrincipal>";
queueConnection = <vendor>QueueConnectionFactory.createQueueConnection(jmsPrincipal, "<theJMSCredential>");
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(inquiryPrcCancelQueue);
message = queueSession.createMapMessage();
// correlation condition params inside process
// 1. MasterGUID
message.setString(TerminateInquiryProcessConstants.MASTERGUID, (String) requestParams.get(StartInquiryProcessConstants.MASTERGUID));
// 2. SenderSID
message.setString(TerminateInquiryProcessConstants.SENDERSID, (String) requestParams.get(StartInquiryProcessConstants.SENDERSID));
// 3. BusinessUnit
message.setString(TerminateInquiryProcessConstants.BUSINESSUNIT, (String) requestParams.get(StartInquiryProcessConstants.BUSINESSUNIT));
// params for protocol interface
// 1. Processor = JMSPrincipal
message.setString(TerminateInquiryProcessConstants.PROCESSOR, jmsPrincipal);
// 2. Reason = cancel reason
// IPO is a technical user = default language English, that means cancel reason will not be translated at the moment
message.setString(TerminateInquiryProcessConstants.REASON, MessageFormat.format(
"Automated inquiry process termination regarding the param InquiryUserID {0} could not be found inside ActiveDirectory/LDAP.", (String) requestParams
.get(StartInquiryProcessConstants.INQUIRYUSERID)));
queueSender.send(message);
messageId = message.getJMSMessageID();
} catch (JMSException jmsExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JMSException occurred inside sendMessageIntoInquiryPrcCancelQueue()", jmsExc);
throw new RuntimeException(jmsExc);
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException jmsExc) {
SimpleLogger.traceThrowable(Severity.ERROR, logger, "JMSException occurred inside sendMessageIntoInquiryPrcCancelQueue() by closing QueueConnection", jmsExc);
throw new RuntimeException(jmsExc);
}
}
}
return messageId;
}
}

The default behaviour of a MDB is a listener pattern on the JMS queue to receive the JMS messages. Inside the onMessage() operation the received message will be consumed and the values of the map message will be used to execute the start inquiry process provider. In case of success the message will be automatically deleted/confirmed. In case of an exception a runtime exception will be thrown to inform the JMS server to increase the max delivery attempts counter of the JMS message. The MDB tries to consume the message after an interval again. In case the max delivery attempts limit is reached the message will automatically be moved into an error queue. Otherwise the same message with the same error will executed until the judgement day.

The implementation of the MDB is "nearly" the same like in the stateless session bean of the web service implementation to start the aBPM/BPM process. The only difference is that the web service implementation works on the original payload values of the trigger message during the MDB works an the JMS message values.

In the last steps of this blogs the snippets of the XML files of the EJB and the JMS deployment descriptor of the EAR file are shown.

ejb-j2ee-engins.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-j2ee-engine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ejb-j2ee-engine_3_0.xsd">
<security-permission>
<security-role-map>
<role-name>BPMTriggerRole</role-name>
<server-role-name>SAP_BPM_TRIGGER_EVENT</server-role-name>
</security-role-map>
</security-permission>
</ejb-j2ee-engine>

ejb-jar.xml:
<?xml version="1.0" encoding="ASCII"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0">
<assembly-descriptor>
<security-role>
<role-name>BPMTriggerRole</role-name>
</security-role>
</assembly-descriptor>
</ejb-jar>

jms-resources.xml (deployment descriptor of the EAR DC):
<?xml version="1.0" encoding="UTF-8"?>
<jms-resources xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="jms-resources.xsd">
<connection-factory>
<name>"<vendor>QueueConnectionFactory"</name>
<sap-local-factory-type>
<type>javax.jms.QueueConnectionFactory</type>
<virtual-provider>"<virtualprovider>"</virtual-provider>
</sap-local-factory-type>
</connection-factory>
<destination>
<name>InquiryPrcErrorQueue</name>
<type>javax.jms.Queue</type>
<sap-local-destination-type>
<virtual-provider>"<virtualprovider>"</virtual-provider>
<property>
<description>Error Destination</description>
<config-property-name>errorDestination</config-property-name>
<config-property-value> </config-property-value>
</property>
</sap-local-destination-type>
</destination>
<destination>
<name>InquiryPrcCancelErrorQueue</name>
<type>javax.jms.Queue</type>
<sap-local-destination-type>
<virtual-provider>"<virtualprovider>"</virtual-provider>
<property>
<description>Error Destination</description>
<config-property-name>errorDestination</config-property-name>
<config-property-value> </config-property-value>
</property>
</sap-local-destination-type>
</destination>
<destination>
<name>InquiryPrcQueue</name>
<type>javax.jms.Queue</type>
<sap-local-destination-type>
<virtual-provider>"<virtualprovider>"</virtual-provider>
<property>
<description>Message Delivery Attempts Limited</description>
<config-property-name>deliveryAttemptsLimited</config-property-name>
<config-property-value>true</config-property-value>
</property>
<property>
<description>Maximum Delivery Attempts</description>
<config-property-name>maxDeliveryAttempts</config-property-name>
<config-property-value>3</config-property-value>
</property>
<property>
<description>Delay in Milliseconds</description>
<config-property-name>deliveryDelayInterval</config-property-name>
<config-property-value>5000</config-property-value>
</property>
<property>
<description>Error Destination</description>
<config-property-name>errorDestination</config-property-name>
<config-property-value>InquiryPrcErrorQueue</config-property-value>
</property>
<property>
<description>Load Balance Behavior</description>
<config-property-name>loadBalanceBehavior</config-property-name>
<config-property-value>3</config-property-value>
</property>
</sap-local-destination-type>
</destination>
<destination>
<name>InquiryPrcCancelQueue</name>
<type>javax.jms.Queue</type>
<sap-local-destination-type>
<virtual-provider>"<virtualprovider>"</virtual-provider>
<property>
<description>Message Delivery Attempts Limited</description>
<config-property-name>deliveryAttemptsLimited</config-property-name>
<config-property-value>true</config-property-value>
</property>
<property>
<description>Maximum Delivery Attempts</description>
<config-property-name>maxDeliveryAttempts</config-property-name>
<config-property-value>3</config-property-value>
</property>
<property>
<description>Delay in Milliseconds</description>
<config-property-name>deliveryDelayInterval</config-property-name>
<config-property-value>5000</config-property-value>
</property>
<property>
<description>Error Destination</description>
<config-property-name>errorDestination</config-property-name>
<config-property-value>InquiryPrcCancelErrorQueue</config-property-value>
</property>
<property>
<description>Load Balance Behavior</description>
<config-property-name>loadBalanceBehavior</config-property-name>
<config-property-value>3</config-property-value>
</property>
</sap-local-destination-type>
</destination>
<virtual-provider-properties>
<name>"<virtualprovider>"</name>
<property>
<description>runningMode</description>
<config-property-name>runningMode</config-property-name>
<config-property-value>GLOBAL</config-property-value>
</property>
</virtual-provider-properties>
</jms-resources>

After build and deployment the behaviour to lose the start trigger message of the aBPM/BPM process before the aBPM/BPM process are persist or started should now be eliminated.