A new approach: Multi-mapping Dynamic Configuration using a generic custom module
1/20/2015: Updated with an example multi-map Payload
Multi-mapping dynamic configuration has been a frequent requirement and there are many open questions in SAP PI space, since multi-mapping doesn’t support dynamic configuration i.e., a separate dynamic configuration for each child message. Some time back I wrote a blog Multi-mapping: Assigning ASMA’s for Child Messages using Custom Adapter Module and FM but unfortunately that solution can’t be used for PI/PO single java stack systems
In this blog, I would like to share my new solution using a simple generic custom adapter module. The module can be used for any J2EE technical adapter by just configuring it in the respective communication channel. The module is applicable for all pi versions except few changes to import statements and few methods due to changes in module API. Highlighted the required changes as a comment in the attached module source code
Steps
- Enhance each target message structure i.e., data type/external definition to have custom dynamic configuration header which will reflect in multi-mapping program as shown in the below snap shot. We enhance target structure mainly due to two reasons i. to utilize in the custom module to set dynamic headers for each child message ii. to easily remove the enhanced structure via module configuration and of course after step i
- Now you can map required dynamic header values (DC technical name, DC namespace and it’s value) either from source structure (or) via some lookup (or) some complex calculation using UDF based on your requirement. Please note that, DCRecord node occurrence is unbounded in nature and hence you can duplicate this structure how many ever times you want to utilize it for other DC technical attributes
- The attached custom module expects two xpath parameters as input,
- DCXPATH – to evaluate dynamic headers from the child payload e.g., for the above defined structure it will be /MT_Receiver/DCHeader/DCRecord
- DCXPATHDEL – to delete the enhanced structure which is obviously not required by target system e.g., for the above defined structure it will be /MT_Receiver/DCHeader
- Deploy the custom module and use it in the required channel with the above mentioned parameters
Transformed Example Multi-Map Payload from Mapping:-
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
<ns0:Message1>
<ns1:MT_Receiver xmlns:ns1="http://pg.com/multimap">
<!-- ENHANCED DCHeader STRUCTURE for Dynamic Configuration -->
<DCHeader>
<DCRecord>
<DCValue DCNameSpace="http://sap.com/xi/XI/System/File" DCTechnicalName="FileName">Data1.xml</DCValue>
</DCRecord>
<DCRecord>
<DCValue DCNameSpace="http://sap.com/xi/XI/System/File" DCTechnicalName="Directory">./PI_OUT/Files/</DCValue>
</DCRecord>
</DCHeader>
<!-- ACTUAL TARGET STRUCTURE -->
<Name>Praveen1</Name>
<EmpID>1234</EmpID>
<Project>ABC</Project>
</ns1:MT_Receiver>
<ns1:MT_Receiver xmlns:ns1="http://pg.com/multimap">
<!-- ENHANCED DCHeader STRUCTURE for Dynamic Configuration -->
<DCHeader>
<DCRecord>
<DCValue DCNameSpace="http://sap.com/xi/XI/System/File" DCTechnicalName="FileName">Data2.xml</DCValue>
</DCRecord>
<DCRecord>
<DCValue DCNameSpace="http://sap.com/xi/XI/System/File" DCTechnicalName="Directory">./PI_OUT/Files/</DCValue>
</DCRecord>
</DCHeader>
<!-- ACTUAL TARGET STRUCTURE -->
<Name>Praveen2</Name>
<EmpID>4567</EmpID>
<Project>XYZ</Project>
</ns1:MT_Receiver>
</ns0:Message1>
</ns0:Messages>
That’s all. Hope this new solution is simple, efficient and can be useful for your projects. Please share your feedback to improve the code. Thanks..
Hello Praveen Gujjeti - thanks for this great material.
I'm trying to understand how this would work in practical terms.
Once we enhanced the target structure with DC Header (after having the custom module deployed) and DC XPath/Del parameters maintained in module configuration, what else is required to see the results?
e.g: my requirement is to set file name dynamically with multi mapping (
).Would you have any practical example?
Thanks in advance!
Hello Praveen Gujjeti
I tried to deploy the EAR file in NWDS but it returned a warning:
S U M M A R Y
~~~~~~~~~~~~~~~~~~~
Successfully deployed: 0
Deployed with warnings: 1
Failed deployments: 0
~~~~~~~~~~~~~~~~~~~
1. File:C:\Users\rafael.silva\Downloads\EAR\PckgDCMultiMap_EAR.ear\DCMultiMap_EAR.ear
Name:DCMultiMap_EAR
Vendor:sap.com
Location:localhost
Version:2014.03.05.21.55.53
Deploy status:Warning
Version:NEW
Description:
1. Warning occurred on server 1199350 during deploy of sap.com/DCMultiMap_EAR : EJB Model Builder: ASJ.ejb.004096 The session bean class "com.dc.multimap.DCMultiMapBean" cannot be found in the search path. (Location:META-INF/ejb-jar.xml)[message resource bundle missing], file: DCMultiMap_EJB.jar#DCMultiMap_EJB.jar, severity: warning
Warning occurred on server 1199350 during deploy of sap.com/DCMultiMap_EAR : EJB Model Builder: Bean class com.dc.multimap.DCMultiMapBean is not available in the ejb module archive file.[message resource bundle missing], file: DCMultiMap_EJB.jar#DCMultiMap_EJB.jar, severity: warning
CSN component of deployment item is not available
2. Exception has been returned while the [sap.com/DCMultiMap_EAR] was starting. Warning/Exception :[
][ASJ.dpl_ds.006153 Error occurred while starting application [sap.com/DCMultiMap_EAR]: It is not started successfully on server nodes [1199350]. In order to bring the server in consistent state stop operation will be performed.
Error occurred on server 1199350 during startApp of sap.com/DCMultiMap_EAR : com.sap.engine.services.deploy.container.DeploymentException: Cannot load bean class com.dc.multimap.DCMultiMapBean for component sap.com/DCMultiMap_EAR*xml|DCMultiMap_EJB.jar*xml|DCMultiMap
at com.sap.engine.services.ejb3.container.ContainerInterfaceImpl$Actions.perform(ContainerInterfaceImpl.java:1139)
at com.sap.engine.services.ejb3.container.ContainerInterfaceImpl.prepareStart(ContainerInterfaceImpl.java:575)
at com.sap.engine.services.deploy.server.utils.container.ContainerWrapper.prepareStart(ContainerWrapper.java:509)
at com.sap.engine.services.deploy.server.application.StartTransaction.prepareCommon(StartTransaction.java:403)
at com.sap.engine.services.deploy.server.application.StartTransaction.prepare(StartTransaction.java:324)
at com.sap.engine.services.deploy.server.application.ApplicationTransaction.makeAllPhasesOnOneServer(ApplicationTransaction.java:430)
at com.sap.engine.services.deploy.server.application.ApplicationTransaction.makeAllPhases(ApplicationTransaction.java:473)
at com.sap.engine.services.deploy.server.application.ParallelAdapter.makeAllPhasesSequentially(ParallelAdapter.java:324)
at com.sap.engine.services.deploy.server.application.StartTransaction.makeAllPhases(StartTransaction.java:693)
at com.sap.engine.services.deploy.server.DeployServiceImpl.makeGlobalTransaction(DeployServiceImpl.java:1985)
at com.sap.engine.services.deploy.server.DeployServiceImpl.startApplicationAndWait(DeployServiceImpl.java:2635)
at com.sap.engine.services.deploy.server.DeployServiceImpl.startApplicationOnInstanceWait(DeployServiceImpl.java:2887)
at com.sap.engine.services.deploy.server.DeployServiceImpl.startApplicationOnInstanceAndWaitAuth(DeployServiceImpl.java:3036)
at com.sap.engine.services.deploy.server.DeployServiceImpl.startApplicationAndWait(DeployServiceImpl.java:2588)
at com.sap.engine.services.dc.lcm.impl.J2EELCMProcessor.doStart(J2EELCMProcessor.java:109)
at com.sap.engine.services.dc.lcm.impl.LifeCycleManagerImpl.start(LifeCycleManagerImpl.java:80)
at com.sap.engine.services.dc.cm.deploy.impl.LifeCycleManagerStartVisitor.visit(LifeCycleManagerStartVisitor.java:48)
at com.sap.engine.services.dc.cm.deploy.impl.DeploymentItemImpl.accept(DeploymentItemImpl.java:84)
at com.sap.engine.services.dc.cm.deploy.impl.DefaultDeployPostProcessor.postProcessLCMDeplItem(DefaultDeployPostProcessor.java:111)
at com.sap.engine.services.dc.cm.deploy.impl.DefaultDeployPostProcessor.postProcess(DefaultDeployPostProcessor.java:73)
at com.sap.engine.services.dc.cm.deploy.impl.DeployerImpl.doPostProcessing(DeployerImpl.java:1135)
at com.sap.engine.services.dc.cm.deploy.impl.DeployerImpl.performDeploy(DeployerImpl.java:1024)
at com.sap.engine.services.dc.cm.deploy.impl.DeployerImpl.doDeploy(DeployerImpl.java:819)
at com.sap.engine.services.dc.cm.deploy.impl.DeployerImpl.deployInternal(DeployerImpl.java:454)
at com.sap.engine.services.dc.cm.deploy.impl.DeployerImpl.deploy(DeployerImpl.java:228)
at com.sap.engine.services.dc.cm.deploy.impl.DeployerImplp4_Skel.dispatch(DeployerImplp4_Skel.java:910)
at com.sap.engine.services.rmi_p4.DispatchImpl._runInternal(DispatchImpl.java:483)
at com.sap.engine.services.rmi_p4.server.ServerDispatchImpl.run(ServerDispatchImpl.java:83)
at com.sap.engine.services.rmi_p4.P4Message.process(P4Message.java:72)
at com.sap.engine.services.rmi_p4.P4Message.execute(P4Message.java:43)
at com.sap.engine.services.cross.fca.FCAConnectorImpl.executeRequest(FCAConnectorImpl.java:1055)
at com.sap.engine.services.rmi_p4.P4Message.process(P4Message.java:59)
at com.sap.engine.services.cross.fca.MessageReader.run(MessageReader.java:55)
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)
Caused by: com.sap.engine.services.ejb3.container.ActionException: Cannot load bean class com.dc.multimap.DCMultiMapBean for component sap.com/DCMultiMap_EAR*xml|DCMultiMap_EJB.jar*xml|DCMultiMap
at com.sap.engine.services.ejb3.runtime.impl.Actions_BeanClassesInitialization.loadApplicationClass(Actions_BeanClassesInitialization.java:56)
at com.sap.engine.services.ejb3.runtime.impl.Actions_BeanClassesInitialization.loadApplicationClasses(Actions_BeanClassesInitialization.java:41)
at com.sap.engine.services.ejb3.runtime.impl.Actions_ComponentInterfacesProviderClassesInitialization.loadApplicationClasses(Actions_ComponentInterfacesProviderClassesInitialization.java:20)
at com.sap.engine.services.ejb3.runtime.impl.Actions_SessionBeanClassesInitialization.loadApplicationClasses(Actions_SessionBeanClassesInitialization.java:20)
at com.sap.engine.services.ejb3.runtime.impl.Actions_StatelessBeanClassesInitialization.loadApplicationClasses(Actions_StatelessBeanClassesInitialization.java:18)
at com.sap.engine.services.ejb3.runtime.impl.Actions_BeanClassesInitialization.perform(Actions_BeanClassesInitialization.java:27)
at com.sap.engine.services.ejb3.container.CompositeAction.perform(CompositeAction.java:84)
at com.sap.engine.services.ejb3.container.ApplicationStarter.perform(ApplicationStarter.java:213)
at com.sap.engine.services.ejb3.container.ContainerInterfaceImpl$Actions.perform(ContainerInterfaceImpl.java:1133)
... 35 more
Caused by: java.lang.ClassNotFoundException: com.dc.multimap.DCMultiMapBean
------------------------- Loader Info -------------------------
ClassLoader name: [sap.com/DCMultiMap_EAR]
Loader hash code: 21d414ef
Living status: alive
Direct parent loaders:
[system:Frame]
[interface:webservices]
[interface:cross]
[interface:security]
[interface:transactionext]
[library:webservices_lib]
[library:opensql]
[library:jms]
[library:ejb20]
[service:p4]
[service:ejb]
[service:servlet_jsp]
[service:engine.security.facade]
[library:engine.j2ee14.facade]
[interface:com.sap.aii.af.ifc.facade]
[service:com.sap.aii.af.svc]
[library:com.sap.aii.af.lib.facade]
[service:com.sap.aii.af.svc.facade]
[service:com.sap.aii.adapter.xi.svc]
Resources:
C:\usr\sap\PID\J00\j2ee\cluster\apps\sap.com\DCMultiMap_EAR\EJBContainer\applicationjars\DCMultiMap_EJB.jar
---------------------------------------------------------------
at com.sap.engine.boot.loader.MultiParentClassLoader.loadClass(MultiParentClassLoader.java:280)
at com.sap.engine.boot.loader.MultiParentClassLoader.loadClass(MultiParentClassLoader.java:249)
at com.sap.engine.services.ejb3.runtime.impl.Actions_BeanClassesInitialization.loadApplicationClass(Actions_BeanClassesInitialization.java:54)
... 43 more
]
Result
Status:Warning
Would you have something to suggest?
Hi Rafael,
The EAR file is missing Bean class file. I have now uploaded new EAR file
Try deploying it again
Br,
Praveen
Hi Praveen,
Deploy finished successfully this time! Tks a lot!
However, I'm still seeing error com.sap.engine.interfaces.messaging.api.exception.MessagingException: com.sap.engine.services.jndi.persistent.exceptions720.NameNotFoundException: Object not found in lookup of DCMultiMap.
Am I referencing module name wrongly in channel config?
Or what am I doing wrong here?
This is how JNDI shows the deployed EAR:
And this is how I'm setting up my receiver file channel:
I also tried with localejbs/DCMultiMap, but getting same error message.
Thanks!
Hi Praveen,
Could you please share the generic custom module code for this dynamic configuration.
Thanks,
Ezhil.
Hi Ezhil,
try this link: https://app.box.com/s/txy5s014pgshywvyw3oz
It seems blog content has changed after upgrade from SCN
Br,
Praveen
Hi Praveen
The deploy failed with the same warning as Rafael Vieira (please see his comments above).
Any chance you could email me the latest ear file please ?
Many thanks in advance.