Quantcast
Channel: SCN : Blog List - Process Integration (PI) & SOA Middleware
Viewing all 676 articles
Browse latest View live

Michal's PO tips: How to send messages directly to AEX (ICO) - adapter independent - SOAPUI version

$
0
0

In one of the latest articlesHowTo - Send Test Messages to the Adapter Engine (to an Integrated Configuration)  Karsten Möhwald has shown an amazing idea on how we can send a message from RWB to any ICO (does not matter what kind of adapter is being used in the ICO).


Where can we use this idea?


a) if we need to test an ICO but we don't have a working connection with the existing adapter (for example JMS, JDBC, IDOC, etc.)

b) if we want to design regression testing tool which will skip the sender adapter and will always post the data in the same way to PI (via SOAP)

 

But how can we do the same trick without RWB?

 

If you have a look at the configuration in Karsten's blog you will see that in RWB we're using the URL:


http://<server_host>:<j2ee_port>/XISOAPAdapter/MessageServlet?channel=<party>:<service>:<channel>


to the dummy SOAP channel but where to put the information in case we'd like to do the same with SOAPUI or any other SOAP testing tool ?

 

If you think that we can try the second standard way of creating the URL for sender soap adapter:

 

http://<server_host>:<j2ee_port>/XISOAPAdapter/MessageServlet?senderParty=

&senderService=BC_Michal_Krawczyk&receiverParty=&receiverService=

&interface=SI_Michal_Out&interfaceNamespace=urn:michal.krawczyk.com

 

then this is not going to work as PO will let us know that it's not possible to use non SOAP channels (for example JDBC) like shown on the screenshot below:


 

michal_krawczyk_error_info_ICO.png

 

 

 

 

What do we need to do then? It turns out that we need to create a whole envelope for PO message (with XI header) where we need put:

 

- sender system

- interface & namespace

but also:

- message ID, timestamp, queueid, etc.



SOAPUI message data

 

 

<SOAP:Envelope xmlns:SOAP='http://schemas.xmlsoap.org/soap/envelope/'>

<SOAP:Header>

<sap:Main xmlns:sap='http://sap.com/xi/XI/Message/30' versionMajor='3' versionMinor='1' SOAP:mustUnderstand='1'>

<sap:MessageClass>ApplicationMessage</sap:MessageClass>

<sap:ProcessingMode>asynchronous</sap:ProcessingMode>

<sap:MessageId>30afd515-99b6-11e3-c37d-000000aecb5b</sap:MessageId>

<sap:TimeSent>2014-02-19T22:35:53Z</sap:TimeSent>

<sap:Sender><sap:Party agency='http://sap.com/xi/XI' scheme='XIParty'>

</sap:Party><sap:Service>BC_Michal_Krawczyk</sap:Service></sap:Sender>

<sap:Interface namespace='urn:krawczyk.com'>SI_Michal_Out</sap:Interface></sap:Main>

<sap:ReliableMessaging xmlns:sap='http://sap.com/xi/XI/Message/30' SOAP:mustUnderstand='1'>

<sap:QualityOfService>ExactlyOnce</sap:QualityOfService>

<sap:QueueId>55555</sap:QueueId></sap:ReliableMessaging>

</SOAP:Header><SOAP:Body>


<ns:MT_data xmlns:ns="http://michal.krawczyk.com/SDN">

  <row>

  <name>Michal</name>

  <surname>Krawczyk</surname>

  </row>

</ns:MT_resultset>


</SOAP:Body>

</SOAP:Envelope>


 

 

and then if we send it to the dummy SOAP channel like

http://<server_host>:<j2ee_port>/XISOAPAdapter/MessageServlet?channel=<party>:<service>:<channel>

the message will go to the correct service as per the information from the XI header.

 

 

If you know any other easier way to do the same thing, please do let me know,


Installing NWDS on Citrix : Steps for Basis / Citrix Administrator

$
0
0

NWDS Installation Steps on Citrix

 

Trying to put the steps together at one place, hope its useful.

Prerequisite
SAP NetWeaver Developer Studio has the following hardware and software requirements:
Hardware (minimal requirements)
3 GB free disk space
2 GB RAM
Software
Operating system
Supported operating systems are:
Windows XP 32-bit
Windows Vista 32-bit
Windows Server 2008 64-bit
Windows 7 32-bit
Windows 7 64-bit

JDK version
Supported Java Development Kit (JDK) are from SAP AG or Oracle. Note that the JDK you use must be the 32-bit version. You can either use:
JDK provided with the SAP JVM 6 "Windows Server on IA32 32-bit".
https://nwds.sap.com/swdc/downloads/updates/netweaver/nwds/nw/731/doc/files/sapjvm6.msi
OR
JDK from Oracle.
You need JDK version 1.6.0_7 or higher, 32-bit.
http://java.sun.com/javase/downloads.


* Hardware and software details are as provided on the SMP in NWDS installation guide.

Installation Procedure :
1.Copy the distribution archive (zip) downloaded from the sap market place.
2.Open the archive and extract its content in a folder on the file system.
3.Open the folder and start SapNetweaverDeveloperStudio.exe.
4.When the Developer Studio start, in the window that opens enter a location for the Workspace folder, you can choose a default folder or have a /workspace folder created.
5.If the Developer Studio detects a JRE or unsupported JDK, a window opens and allows you to select a javaw.exe file of a supported JDK version.
If you do not have a supported JDK version, you can install it while this window is open and then, choose the JDK source.
When you enter a valid javaw.exe file, the Developer Studio stores the settings and exits. Open the installation folder and start SapNetweaverDeveloperStudio.exe again.
6. We will need the link /shortcut for SapNetweaverDeveloperStudio.exe on citrix.

You need to setup the NWDS shortcut as below , so that the user specific workspace is selected.
<path to your IDE>\eclipse\SapIde.exe -vm "<JAVA_HOME>\bin\javaw.exe" -data "<workspace folder of a given user>"
<workspace folder of a given user> should be replaced by a variable which points to the users profile.
eg.D:\NWDS\SapIde.exe -vm "D:\j2sdk1.4.2_09\bin\javaw.exe" -data "D:\workspace\<userid>"
"D:\workspace\<userid>" we need to make it dynamic by replacing it by variable.

 


External Collection of Message Processing Statistics from Advanced Adapter Engine of PI

$
0
0

Intro

SAP PI system is already shipped with extensive toolset of monitoring applications that can provide aggregated statistics on messages that have been processed in Advanced Adapter Engine (from message overview and performance perspectives). In addition to built-in tools, the one can employ functionality of Solution Manager for centralized monitoring of the PI system in general and statistics of message processing in particular. But there are some cases, when these tools are not sufficient and it is necessary to retrieve statistics of message processing in Advanced Adapter Engine of the SAP PI system for external usage – e.g. in case the consumer of this data is the external monitoring application.

 

To achieve this requirement, it is possible to query two standard servlets of Advanced Adapter Engine that can provide necessary information via HTTP (thus, accessing PI host via J2EE HTTP port - by default, 5<instance number>00). In this blog, I will provide an outlook at their functionality and use cases. The discussed servlets are:

  • MessageOverviewQueryServlet
  • PerformanceDataQueryServlet

 

Both servlets are exposed by Message Display Tool application of Advanced Adapter Engine:

 

servlets.png

 

Requests for these servlets are constructed using input parameters (passed as GET parameters in the URL) and responses are rendered in a form of XML document that can be traversed and analyzed conveniently by the caller application. XSD schemas of responses of the mentioned servlets are accessible via URI /mdt/monitor/<servlet name>.xsd.

 

 

MessageOverviewQueryServlet

The servlet is used to access message processing overview data externally. In PIMON, this is data displayed in Message Monitor -> Message Status Overview.

 

The servlet is accessible via URI:

/mdt/messageoverviewqueryservlet

 

XSD schema of servlet response is accessible via URI:

/mdt/monitor/MessageOverviewQuery.xsd

 

Semantics of the constructed URI for querying servlet is:

/mdt/messageoverviewqueryservlet?component=<XIComponentName>&view=<ViewNameKey>&begin=<IntervalBeginTime>&end=<IntervalEndTime>[&detailedStatus=<true|false>]

 

When querying the servlet, following parameters can be used:

 

ParameterDescriptionValue format / Possible values
componentPI component. Components can be checked in Component Monitor. Examples are central Adapter Engine and non-central Adapter Engine, central Integration Engine and local Integration Engines (proxy runtimes of connected application systems)
viewView key. The view defines a set of retrieved attributes and sorting principles for queried message overview statistics

R_ENTRY_VIEW_XPI

S_ENTRY_VIEW_XPI

SR_ENTRY_OVERVIEW_XPI

SR_ENTRY_VIEW_XPI

beginTime period begin time stampYYYY-MM-DD hh:mm:ss.0
endTime period end time stampYYYY-MM-DD hh:mm:ss.0
detailedStatusIndicator for showing status groups / detailed status values

true

false

 

If the servlet is called without parameters, the response will contain a list of components that can be queried.

If the servlet is called and a valid value for the component is passed, the response will contain a list of view keys and time periods per period type for which message overview data is available for the specified component. Following period types are supported:

  • HOURLY: message overview data for last 12 hours, aggregated per 1 hour;
  • DAILY: message overview data for last 7 days, aggregated per 1 day;
  • WEEKLY: message overview data for last month, aggregated per 1 week;
  • MONTHLY: message overview data for last 12 months, aggregated per 1 month;
  • ANNUALLY: message overview data for several years, aggregated per 1 year.

 

If the servlet is called and valid values for component, view and time period are passed, the response will contain message overview data for processed messages - namely:

  • Scenario attributes (scenario identifier, sender and receiver communication components, interface);
  • Message counter per message status (for example, for statuses 'System error', 'Waiting', 'To be delivered', 'Delivering', 'Holding', 'Successful', 'Canceled with errors' for Advanced Adapter Engine).

 

Example request (URI part):

/mdt/messageoverviewqueryservlet?component=af.po1.nced60229921a&view=SR_ENTRY_VIEW_XPI&begin=2014-02-24 01:00:00.0&end=2014-02-25 01:00:00.0&detailedStatus=true

 

Response (extract depicting two message overview data set entries):

 

message overview - response.png

 

Names of respective entry elements of data rows are provided at the beginning of the servlet response XML document:

 

message overview - columns.png

 

The servlet usage is described in the SAP Note 1400785. The servlet is available as of PI release 7.0. Please consult the SAP Note for minimum SP/PL level requirements for the particular PI release.

 

 

PerformanceDataQueryServlet

The servlet is used to access message processing performance data externally. In PIMON, this is data displayed in Performance Monitor.

 

The servlet is accessible via URI:

/mdt/performancedataqueryservlet

 

XSD schema of servlet response is accessible via URI:

/mdt/monitor/PerformanceDataQuery.xsd

 

Semantics of the constructed URI for querying servlet is:

/mdt/performancedataqueryservlet?component=<XIComponentName>&begin=<IntervalBeginTime>&end=<IntervalEndTime>

 

When querying the servlet, following parameters can be used:

 

ParameterDescriptionValue format / Possible values
componentComponent of Advanced Adapter Engine. Components can be checked in Component Monitor or in SLD, in registered CIM instances of class SAP_XIAdapterFramework). Examples are central Adapter Engine and non-central Adapter Engine
beginTime period begin time stampYYYY-MM-DD hh:mm:ss.0
endTime period end time stampYYYY-MM-DD hh:mm:ss.0

 

If the servlet is called without parameters, the response will contain a list of components that can be queried.

If the servlet is called and a valid value for the component is passed, the response will contain a list of time periods per period type for which performance data is available for the specified component. Following period types are supported:

  • MINUTE: performance data for last 1 hour, aggregated per 15 minutes;
  • HOURLY: performance data for last 24 hours, aggregated per 1 hour;
  • DAILY: performance data for last 7 days, aggregated per 1 day.

 

If the servlet is called and valid values for component and time period are passed, the response will contain performance data for processed messages – namely:

  • Scenario attributes (scenario identifier, sender and receiver communication parties, components, communication channels, interface, direction, delivery semantics, etc.);
  • Server node that processed messages for the scenario;
  • Message counter;
  • Important key figures reflecting performance data (maximum, minimum and average message size and retry attempts);
  • Measuring points data (for each measuring point, maximum, minimum and average values in microseconds are provided).

 

Example request (URI part):

/mdt/performancedataqueryservlet?component=af.po1.nced60229921a&begin=2014-02-24 01:00:00.0&end=2014-02-25 01:00:00.0

 

Response (extract depicting a single performance data set entry):

 

performance - response.png

 

Names of respective entry elements of data rows are provided at the beginning of the servlet response XML document:

 

performance - columns.png

 

The servlet usage is described in the SAP Note 1790113. The servlet is available as of PI release 7.31. Please consult the SAP Note for minimum SP/PL level requirements for the particular PI release.

 

 

Outro

You can also check the blog "Michal's PI tips: How to get RWB message overview data to an external system?" written by Michal Krawczyk that discusses usage of MessageOverviewQueryServlet: Michal's PI tips: How to get RWB message overview data to an external system? .

 

It should be noted that described servlets are not the only possibility to access message overview and performance data in Advanced Adapter Engine. On lower level, both servlets are calling ProfileProcessor - a component of Adapter Framework that is used for querying message statistics. Apart from discussed servlets, there are also several other tools that are working as proxies over ProfileProcessor - for example, the web service named ProfileProcessorVi. Consumer of this web service can retrieve message overview and performance data using web service operation getWSData() and passing corresponding application, profile and view keys together with time period and period type.


WS Navigator - service.png


WS Navigator - operations.png


Overview table of message overview and performance applications as well as profiles and views that are supported by the web service is provided below:

 

Retrieved dataApplication keyProfile keyView key
Message overview datasap - XPI_STATISTIC - http://sap.com/xi/XI/Message/30XPI

R_ENTRY_VIEW_XPI

S_ENTRY_VIEW_XPI

SR_ENTRY_OVERVIEW_XPI

SR_ENTRY_VIEW_XPI

Performance datasap - XPI_PERFORMANCE_STATISTIC - http://sap.com/xi/XI/Message/30XPI_PERFORMANCEENTRY_VIEW_XPI_PERFORMANCE

 

The web service ProfileProcessorVi is used by some SAP standard applications that are querying PI message statistics - for example, some applications of Solution Manager are actively using this web service. But consumption of this web service is more complicated in comparison to described servlets - just some reasons for this are listed below:

  • More complex structure of the request that needs to be constructed and sent to the web service;
  • More complex structure of the response that needs to be traversed (for example, actual statistics data is put in a hash form that requires further processing efforts);
  • Additional operations that are required for correct completion of work with the ProfileProcessor after message statistics data is retrieved - namely, release of lock that have to be addressed in extra calls to the web service (by invocation of its operation processAction()).

 

Taking all these concerns into consideration, the web service ProfileProcessorVi can be considered as an alternative for servlets MessageOverviewQueryServlet and PerformanceDataQueryServlet, but is not really exposed officially for external usage in custom solutions and thus is not in scope of this blog.

Warning: PI 7.31 SP9 changed runtime

$
0
0

We was upgrading to SP 9 to make sure the system was as updated as possible. We did have one BIG issue on how the runtime works, compared to how we are working as developers. We did not find the issue in development since we did not thing that there could be an issue with it. But a test in QA reviled the problem.

Update: it was in SP9 the change was introduced and not SP10


Update 24 feb 2014. We have spoken with SAP Labs and have found that the issue is only when dealing with constants and variables in duplicated element, so it is only in few instances. SAP is working on a fix for this. I'll update when the bug is fixed.


I do apologize for the confusion for that this caused. We had tried to make a simple case to show the issue, which contained constants had caused the problem. Most often the pattern will contain field mapping and not constants it is less likely to cause problems.


Comment from Mauri Frandsen, who also help look at the issue. This blog was written because we had some concerns on our project that the problems we faced during our 7.31 SP10 upgrade were widespread and would affect a lot of customers. To us it initially seemed that the problem was due to a change of behavior regarding validation of duplicated mandatory elements. SAP gave us some information about a bug fix from SP09 onwards that led us to believe that this was the reason for the mapping problems we experienced during SP10 testing. It seems not to be correct or at least not the full truth. SAP has informed us that the problem is tied into the use/behavior of constants and is currently doing analysis of the problem. We will await the final outcome of this work and look forward to seeing the solution which will then be announced in an update or comment to the blog.


Update: 22 feb 2014. We have now identified that the mapping pattern is used by many customers. I have got confirmation from Udo Paltzer that SAP development is looking into the issue. And I have a call with Development on monday. I'll update when we get a solution on the issue.  So no need for more comments about that you also may have the problem.

 

The issue is in a common pattern that I often use to simplify the mapping. It when you want to make different mappings for some instances with createIf. So map the first element if something is true otherwise map the duplicated instance. The second mandatory element is then a dublicate subtree. Notice the second element does not have any occurrences.

2014-02-14 12_43_25-Enterprise Services Builder (grusapx11_X11_30).png

 

Using this pattern can in many situations make it clear what is in each field for the different.

A good example could be mapping the partner informations. I have situations where I’ll map the buyer partner different depending on if they provide a customer number or just an address.

 

If we run the same mapping on the old SP6 version we don’t have an issue. It seems like it is a new feature with SP 10 and the corresponding PI 7.4 SP.

 

We have created an OSS message for the case, but without any luck. The issue is that there have been some updates to the SAX parser or the way it is used. The solution is to find all mappings using createIf and determinate if it is an issue. You the query http://PISERVER/rep/support/private/MappingReport.jsp?searchString=createIf

 

The resolution is to update the mappings. We have around 70 mappings where createIf is used. So it can be a big problem to find and  update all of the mappings. My guess is that we will have to spend 20-40 hours updating the mappings to handle the problem.

 

There are some solutions, but the only one that is easy to implement is the first.

  • Update the schema to change the minimum occurrence to 0 and save the mapping.
  • Remove the createIf on the first element and combine the values for it. In some of my mappings this can be a big issue.
  • Create an always on dummy element on the first element. And then remove current mapping to lower levels. It can take some time.

 

Last time SAP made changes to the If functions and BigDecimal it was optional to use it. Because it did have a huge impact on how PI was run. This evaluation is in my perspective also something that users should be explicit if they want to use.

 

Are you also using this pattern please comment on the blog, so SAP can see how big the issue are. If it just us who is doing this we can probably get over it. But it is more common that it is something we must have changed.

 

Thanks Mikael Mauri Frandsen and Hans Hougaard for helping with identify and comment on the problem.

Digest: Dynamic username and password in soap receiver adapter

$
0
0

Hello,

 

this is just a short summary on how to use dynamic username and password with soap adapter.

 

Generally the feature is documented in sap help, see https://help.sap.com/saphelp_nw73/helpdata/en/48/327519a3af58d8e10000000a421937/frameset.htm under "Define Adapter-Specific Message Properties" and "Enter and Display Authentication Keys".


You basically use the feature of dynamic header attributes. So first of all you have to set these attributes. You can do so for example with a user defined function in your mapping:


  DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/SOAP", "TAuthKey");

  DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

  conf.put (key, "SAP_PI_APPL_USER");

This means you are setting the dynamic attribute TAuthKey. The value will be the actual username that shall be used in communication. The same way you can also set all the other attributes like url, proxy user, proxy as documented in the help.

 

The password however is not set as header attribute (for security reasons) but must be configured explicitly in the integration directory. Check "Use Adapter-Specific Message Attributes", "Variable Transport Binding" and "View Authorization Keys". Enter username/password pairs. Note that the key will be the username (SAP_PI_APPL_USER in our example). :

26.02.png

The unfortunate thing is that you can enter only up to ten different users. I really have no idea why SAP put that restriction on the feature. It would be so easy to provide a table entry here. Anyway I found that the documentation was insufficient on the matter and I hope this may be helpful.

Reading a delimeter separated file whoose columns may jumble

$
0
0

Hi,

 

Recently we have a requirement of reading a .csv file from third party file server whose columns may jumble .I want to share my knowledge on this because I have recently seen some questions posted in forum asking a query how to handle a scenario when standard FCC is not fulfilling their requirement.

 

 

In sender communication channel use the below FCC .

 

FCC1.JPG

 

  I have used two mappings for achieving this requirement .

 

  Mapping 1:Splitting each record and passing the values to target structure without checking whether it belongs to that respective field or not .

 

Map1.JPG

 

 

I have used below udf for splitting each record and passing the values to target structure blindly.In case if any of the field is missing in any of the record this mapping gets failed and throws custom error notifying in which record the field is missing.

 

public void SplitbyComma(String[] BodyVal, ResultList Records, ResultList AcctEntryId, ResultList ValueDate, ResultList Entity, ResultList Folder, ResultList DenomCcy, ResultList FunctCcy, ResultList TradeId, ResultList TradeVersion, ResultList TradeType, ResultList LinkId, ResultList LinkVersion, ResultList Counterparty, ResultList AcctProcess, ResultList CashAccount, ResultList AcctEntryDescr, ResultList ReversesAcctEntryId, ResultList AcctEntrySubSysId, ResultList DenomCcyAmount, ResultList FunctCcyAmount, ResultList AcctRule, ResultList AcctChartAcctNumber, ResultList AcctChartDescr, ResultList AcctChartAlternateId, ResultList AcctCategory, ResultList IsParentAcct, ResultList ParentAcctChartAcctNumber, ResultList ParentAcctChartDescr, ResultList AcctChartType, ResultList EntityAltId1, ResultList EntityAltId2, ResultList EntityAltId3, ResultList EntityAltId4, ResultList EntityAltId5, ResultList CptyAltId1, ResultList CptyAltId2, ResultList CptyAltId3, ResultList CptyAltId4, ResultList CptyAltId5, ResultList FolderAltId1, ResultList FolderAltId2, ResultList FolderAltId3, ResultList FolderAltId4, ResultList FolderAltId5, ResultList TradeGroup, ResultList TradeAcctCode, ResultList TradeAcctCode2, ResultList CounterpartyTradeId, ResultList AlternateTradeId, ResultList TradeGroupAltId, ResultList TradeAcctCodeAltId, ResultList LinkGroup, ResultList LinkAcctCode, ResultList LinkAcctCode2, ResultList LinkGroupAltId, ResultList LinkAcctCodeAltId, ResultList AcctChartAltId1, ResultList AcctChartAltId2, ResultList AcctChartAltId3, ResultList AcctChartAltId4, ResultList AcctChartAltId5, ResultList ParentAcctChartAltId1, ResultList ParentAcctChartAltId2, ResultList ParentAcctChartAltId3, ResultList ParentAcctChartAltId4, ResultList ParentAcctChartAltId5, ResultList CashAccountAltID1, ResultList CashAccountAltID2, ResultList CashAccountAltID3, ResultList CashAccountAltID4, ResultList CashAccountAltID5, ResultList OriginalValueDate, ResultList ProductType, ResultList ProductSubType, ResultList AlternateLinkId, ResultList NoOfColumns, ResultList NoofRecords, Container container) throws StreamTransformationException{
AbstractTrace trace = container.getTrace(); //Trace container declaration
String[] ColNames =BodyVal[0].split(",");
int NoofCols =ColNames.length; //Calculating number of columns in file
int NoofRec = BodyVal.length; //Calculating number of records in file
NoOfColumns.addValue(Integer.toString(NoofCols));
NoofRecords.addValue(Integer.toString(NoofRec));
trace.addInfo("No of coloums : "+NoofCols);
trace.addInfo("No of records : "+NoofRecords);
for(int i=0,j=0 ;j< NoofRec ; j++) //By using string tokeniser ,splitting each body record and passing to target structure blindly without bothering about are we passing to apt fields
{
Records.addValue("1"); //Opening Records node for each record
String[] Rec = BodyVal[j].split(",");
trace.addInfo("Rec length  : "+Rec.length);
if (Rec.length == NoofCols )
{
AcctEntryId.addValue(Rec[i++]);
ValueDate.addValue(Rec[i++]);
Entity.addValue(Rec[i++]);
Folder.addValue(Rec[i++]);
DenomCcy.addValue(Rec[i++]);
FunctCcy.addValue(Rec[i++]);
TradeId.addValue(Rec[i++]);
TradeVersion.addValue(Rec[i++]);
TradeType.addValue(Rec[i++]);
LinkId.addValue(Rec[i++]);
LinkVersion.addValue(Rec[i++]);
Counterparty.addValue(Rec[i++]);
AcctProcess.addValue(Rec[i++]);
CashAccount.addValue(Rec[i++]);
AcctEntryDescr.addValue(Rec[i++]);
ReversesAcctEntryId.addValue(Rec[i++]);
AcctEntrySubSysId.addValue(Rec[i++]);
DenomCcyAmount.addValue(Rec[i++]);
FunctCcyAmount.addValue(Rec[i++]);
AcctRule.addValue(Rec[i++]);
AcctChartAcctNumber.addValue(Rec[i++]);
AcctChartDescr.addValue(Rec[i++]);
AcctChartAlternateId.addValue(Rec[i++]);
AcctCategory.addValue(Rec[i++]);
IsParentAcct.addValue(Rec[i++]);
ParentAcctChartAcctNumber.addValue(Rec[i++]);
ParentAcctChartDescr.addValue(Rec[i++]);
AcctChartType.addValue(Rec[i++]);
EntityAltId1.addValue(Rec[i++]);
EntityAltId2.addValue(Rec[i++]);
EntityAltId3.addValue(Rec[i++]);
EntityAltId4.addValue(Rec[i++]);
EntityAltId5.addValue(Rec[i++]);
CptyAltId1.addValue(Rec[i++]);
CptyAltId2.addValue(Rec[i++]);
CptyAltId3.addValue(Rec[i++]);
CptyAltId4.addValue(Rec[i++]);
CptyAltId5.addValue(Rec[i++]);
FolderAltId1.addValue(Rec[i++]);
FolderAltId2.addValue(Rec[i++]);
FolderAltId3.addValue(Rec[i++]);
FolderAltId4.addValue(Rec[i++]);
FolderAltId5.addValue(Rec[i++]);
TradeGroup.addValue(Rec[i++]);
TradeAcctCode.addValue(Rec[i++]);
TradeAcctCode2.addValue(Rec[i++]);
CounterpartyTradeId.addValue(Rec[i++]);
AlternateTradeId.addValue(Rec[i++]);
TradeGroupAltId.addValue(Rec[i++]);
TradeAcctCodeAltId.addValue(Rec[i++]);
LinkGroup.addValue(Rec[i++]);
LinkAcctCode.addValue(Rec[i++]);
LinkAcctCode2.addValue(Rec[i++]);
LinkGroupAltId.addValue(Rec[i++]);
LinkAcctCodeAltId.addValue(Rec[i++]);
AcctChartAltId1.addValue(Rec[i++]);
AcctChartAltId2.addValue(Rec[i++]);
AcctChartAltId3.addValue(Rec[i++]);
AcctChartAltId4.addValue(Rec[i++]);
AcctChartAltId5.addValue(Rec[i++]);
ParentAcctChartAltId1.addValue(Rec[i++]);
ParentAcctChartAltId2.addValue(Rec[i++]);
ParentAcctChartAltId3.addValue(Rec[i++]);
ParentAcctChartAltId4.addValue(Rec[i++]);
ParentAcctChartAltId5.addValue(Rec[i++]);
CashAccountAltID1.addValue(Rec[i++]);
CashAccountAltID2.addValue(Rec[i++]);
CashAccountAltID3.addValue(Rec[i++]);
CashAccountAltID4.addValue(Rec[i++]);
CashAccountAltID5.addValue(Rec[i++]);
OriginalValueDate.addValue(Rec[i++]);
ProductType.addValue(Rec[i++]);
ProductSubType.addValue(Rec[i++]);
AlternateLinkId.addValue(Rec[i++]);
i=0 ;
}
//Making the mapping fail when any of the field is missing in any of the record
else {throw new StreamTransformationException( " No of fields in " +j + "th record is not match to No of coloums .Please check the input file");  }
Rec = new String[0];
}
}

Mapping 2:To pass the values to apt fields in target structure

 

Map2.JPG

 

I have used the below udf for passing the values to apt fields in the target structure.

public void SplitbyColoumnName(String[] NoOfCol, String[] NoofRec, String[] Inp1, String[] Inp2, String[] Inp3, String[] Inp4, String[] Inp5, String[] Inp6, String[] Inp7, String[] Inp8, String[] Inp9, String[] Inp10, String[] Inp11, String[] Inp12, String[] Inp13, String[] Inp14, String[] Inp15, String[] Inp16, String[] Inp17, String[] Inp18, String[] Inp19, String[] Inp20, String[] Inp21, String[] Inp22, String[] Inp23, String[] Inp24, String[] Inp25, String[] Inp26, String[] Inp27, String[] Inp28, String[] Inp29, String[] Inp30, String[] Inp31, String[] Inp32, String[] Inp33, String[] Inp34, String[] Inp35, String[] Inp36, String[] Inp37, String[] Inp38, String[] Inp39, String[] Inp40, String[] Inp41, String[] Inp42, String[] Inp43, String[] Inp44, String[] Inp45, String[] Inp46, String[] Inp47, String[] Inp48, String[] Inp49, String[] Inp50, String[] Inp51, String[] Inp52, String[] Inp53, String[] Inp54, String[] Inp55, String[] Inp56, String[] Inp57, String[] Inp58, String[] Inp59, String[] Inp60, String[] Inp61, String[] Inp62, String[] Inp63, String[] Inp64, String[] Inp65, String[] Inp66, String[] Inp67, String[] Inp68, String[] Inp69, String[] Inp70, String[] Inp71, String[] Inp72, String[] Inp73, String[] Inp74, ResultList AcctEntryId, ResultList ValueDate, ResultList Entity, ResultList Folder, ResultList DenomCcy, ResultList FunctCcy, ResultList TradeId, ResultList TradeVersion, ResultList TradeType, ResultList LinkId, ResultList LinkVersion, ResultList Counterparty, ResultList AcctProcess, ResultList CashAccount, ResultList AcctEntryDescr, ResultList ReversesAcctEntryId, ResultList AcctEntrySubSysId, ResultList DenomCcyAmount, ResultList FunctCcyAmount, ResultList AcctRule, ResultList AcctChartAcctNumber, ResultList AcctChartDescr, ResultList AcctChartAlternateId, ResultList AcctCategory, ResultList IsParentAcct, ResultList ParentAcctChartAcctNumber, ResultList ParentAcctChartDescr, ResultList AcctChartType, ResultList EntityAltId1, ResultList EntityAltId2, ResultList EntityAltId3, ResultList EntityAltId4, ResultList EntityAltId5, ResultList CptyAltId1, ResultList CptyAltId2, ResultList CptyAltId3, ResultList CptyAltId4, ResultList CptyAltId5, ResultList FolderAltId1, ResultList FolderAltId2, ResultList FolderAltId3, ResultList FolderAltId4, ResultList FolderAltId5, ResultList TradeGroup, ResultList TradeAcctCode, ResultList TradeAcctCode2, ResultList CounterpartyTradeId, ResultList AlternateTradeId, ResultList TradeGroupAltId, ResultList TradeAcctCodeAltId, ResultList LinkGroup, ResultList LinkAcctCode, ResultList LinkAcctCode2, ResultList LinkGroupAltId, ResultList LinkAcctCodeAltId, ResultList AcctChartAltId1, ResultList AcctChartAltId2, ResultList AcctChartAltId3, ResultList AcctChartAltId4, ResultList AcctChartAltId5, ResultList ParentAcctChartAltId1, ResultList ParentAcctChartAltId2, ResultList ParentAcctChartAltId3, ResultList ParentAcctChartAltId4, ResultList ParentAcctChartAltId5, ResultList CashAccountAltID1, ResultList CashAccountAltID2, ResultList CashAccountAltID3, ResultList CashAccountAltID4, ResultList CashAccountAltID5, ResultList OriginalValueDate, ResultList ProductType, ResultList ProductSubType, ResultList AlternateLinkId, Container container) throws StreamTransformationException{
String[][] temp ;
AbstractTrace trace = container.getTrace(); //Trace container declaration
int Noofcols = Integer.parseInt(NoOfCol[0]); //No of columns
int NoofRecords = Integer.parseInt(NoofRec[0]); //No of rows
int counter =0;
int count = Noofcols * NoofRecords ;
temp = new String[NoofRecords][count];
for (int i = 0; i < NoofRecords; i++) {
temp[i][counter++] =Inp1[i] ;
temp[i][counter++] =Inp2[i] ;
temp[i][counter++] =Inp3[i] ;
temp[i][counter++] =Inp4[i] ;
temp[i][counter++] =Inp5[i] ;
temp[i][counter++] =Inp6[i] ;
temp[i][counter++] =Inp7[i] ;
temp[i][counter++] =Inp8[i] ;
temp[i][counter++] =Inp9[i] ;
temp[i][counter++] =Inp10[i] ;
temp[i][counter++] =Inp11[i] ;
temp[i][counter++] =Inp12[i] ;
temp[i][counter++] =Inp13[i] ;
temp[i][counter++] =Inp14[i] ;
temp[i][counter++] =Inp15[i] ;
temp[i][counter++] =Inp16[i] ;
temp[i][counter++] =Inp17[i] ;
temp[i][counter++] =Inp18[i] ;
temp[i][counter++] =Inp19[i] ;
temp[i][counter++] =Inp20[i] ;
temp[i][counter++] =Inp21[i] ;
temp[i][counter++] =Inp22[i] ;
temp[i][counter++] =Inp23[i] ;
temp[i][counter++] =Inp24[i] ;
temp[i][counter++] =Inp25[i] ;
temp[i][counter++] =Inp26[i] ;
temp[i][counter++] =Inp27[i] ;
temp[i][counter++] =Inp28[i] ;
temp[i][counter++] =Inp29[i] ;
temp[i][counter++] =Inp30[i] ;
temp[i][counter++] =Inp31[i] ;
temp[i][counter++] =Inp32[i] ;
temp[i][counter++] =Inp33[i] ;
temp[i][counter++] =Inp34[i] ;
temp[i][counter++] =Inp35[i] ;
temp[i][counter++] =Inp36[i] ;
temp[i][counter++] =Inp37[i] ;
temp[i][counter++] =Inp38[i] ;
temp[i][counter++] =Inp39[i] ;
temp[i][counter++] =Inp40[i] ;
temp[i][counter++] =Inp41[i] ;
temp[i][counter++] =Inp42[i] ;
temp[i][counter++] =Inp43[i] ;
temp[i][counter++] =Inp44[i] ;
temp[i][counter++] =Inp45[i] ;
temp[i][counter++] =Inp46[i] ;
temp[i][counter++] =Inp47[i] ;
temp[i][counter++] =Inp48[i] ;
temp[i][counter++] =Inp49[i] ;
temp[i][counter++] =Inp50[i] ;
temp[i][counter++] =Inp51[i] ;
temp[i][counter++] =Inp52[i] ;
temp[i][counter++] =Inp53[i] ;
temp[i][counter++] =Inp54[i] ;
temp[i][counter++] =Inp55[i] ;
temp[i][counter++] =Inp56[i] ;
temp[i][counter++] =Inp57[i] ;
temp[i][counter++] =Inp58[i] ;
temp[i][counter++] =Inp59[i] ;
temp[i][counter++] =Inp60[i] ;
temp[i][counter++] =Inp61[i] ;
temp[i][counter++] =Inp62[i] ;
temp[i][counter++] =Inp63[i] ;
temp[i][counter++] =Inp64[i] ;
temp[i][counter++] =Inp65[i] ;
temp[i][counter++] =Inp66[i] ;
temp[i][counter++] =Inp67[i] ;
temp[i][counter++] =Inp68[i] ;
temp[i][counter++] =Inp69[i] ;
temp[i][counter++] =Inp70[i] ;
temp[i][counter++] =Inp71[i] ;
temp[i][counter++] =Inp72[i] ;
temp[i][counter++] =Inp73[i] ;
temp[i][counter++] =Inp74[i] ;
counter =0 ;
}
for (int k=0,l = 0; l < Noofcols; l++) {
if (temp[k][l].equalsIgnoreCase("AcctEntryId") ||temp[k][l].equalsIgnoreCase("ValueDate") ||temp[k][l].equalsIgnoreCase("Entity") ||temp[k][l].equalsIgnoreCase("Folder") ||temp[k][l].equalsIgnoreCase("DenomCcy") ||temp[k][l].equalsIgnoreCase("FunctCcy") ||temp[k][l].equalsIgnoreCase("TradeId") ||temp[k][l].equalsIgnoreCase("TradeVersion") ||temp[k][l].equalsIgnoreCase("TradeType") ||temp[k][l].equalsIgnoreCase("LinkId") ||temp[k][l].equalsIgnoreCase("LinkVersion") ||temp[k][l].equalsIgnoreCase("Counterparty") ||temp[k][l].equalsIgnoreCase("AcctProcess") ||temp[k][l].equalsIgnoreCase("CashAccount") ||temp[k][l].equalsIgnoreCase("AcctEntryDescr") ||temp[k][l].equalsIgnoreCase("ReversesAcctEntryId") ||temp[k][l].equalsIgnoreCase("AcctEntrySubSysId") ||temp[k][l].equalsIgnoreCase("DenomCcyAmount") ||temp[k][l].equalsIgnoreCase("FunctCcyAmount")  ||temp[k][l].equalsIgnoreCase("AcctRule") ||temp[k][l].equalsIgnoreCase("AcctChartAcctNumber") ||temp[k][l].equalsIgnoreCase("AcctChartDescr") ||temp[k][l].equalsIgnoreCase("AcctChartAlternateId") ||temp[k][l].equalsIgnoreCase("AcctCategory") ||temp[k][l].equalsIgnoreCase("IsParentAcct") ||temp[k][l].equalsIgnoreCase("ParentAcctChartAcctNumber") ||temp[k][l].equalsIgnoreCase("ParentAcctChartDescr") ||temp[k][l].equalsIgnoreCase("AcctChartType") ||temp[k][l].equalsIgnoreCase("EntityAltId1") ||temp[k][l].equalsIgnoreCase("EntityAltId2") ||temp[k][l].equalsIgnoreCase("EntityAltId3") ||temp[k][l].equalsIgnoreCase("EntityAltId4") ||temp[k][l].equalsIgnoreCase("EntityAltId5") ||temp[k][l].equalsIgnoreCase("CptyAltId1") ||temp[k][l].equalsIgnoreCase("CptyAltId2") ||temp[k][l].equalsIgnoreCase("CptyAltId3") ||temp[k][l].equalsIgnoreCase("CptyAltId4") ||temp[k][l].equalsIgnoreCase("CptyAltId5") ||temp[k][l].equalsIgnoreCase("FolderAltId1") ||temp[k][l].equalsIgnoreCase("FolderAltId2") ||temp[k][l].equalsIgnoreCase("FolderAltId3") ||temp[k][l].equalsIgnoreCase("FolderAltId4") ||temp[k][l].equalsIgnoreCase("FolderAltId5") ||temp[k][l].equalsIgnoreCase("TradeGroup") ||temp[k][l].equalsIgnoreCase("TradeAcctCode") ||temp[k][l].equalsIgnoreCase("TradeAcctCode2") ||temp[k][l].equalsIgnoreCase("CounterpartyTradeId") ||temp[k][l].equalsIgnoreCase("AlternateTradeId") ||temp[k][l].equalsIgnoreCase("TradeGroupAltId") ||temp[k][l].equalsIgnoreCase("TradeAcctCodeAltId") ||temp[k][l].equalsIgnoreCase("LinkGroup") ||temp[k][l].equalsIgnoreCase("LinkAcctCode") ||temp[k][l].equalsIgnoreCase("LinkAcctCode2") ||temp[k][l].equalsIgnoreCase("LinkGroupAltId") ||temp[k][l].equalsIgnoreCase("LinkAcctCodeAltId") ||temp[k][l].equalsIgnoreCase("AcctChartAltId1") ||temp[k][l].equalsIgnoreCase("AcctChartAltId2") ||temp[k][l].equalsIgnoreCase("AcctChartAltId3") ||temp[k][l].equalsIgnoreCase("AcctChartAltId4") ||temp[k][l].equalsIgnoreCase("AcctChartAltId5") ||temp[k][l].equalsIgnoreCase("ParentAcctChartAltId1") ||temp[k][l].equalsIgnoreCase("ParentAcctChartAltId2") ||temp[k][l].equalsIgnoreCase("ParentAcctChartAltId3") ||temp[k][l].equalsIgnoreCase("ParentAcctChartAltId4") ||temp[k][l].equalsIgnoreCase("ParentAcctChartAltId5") ||temp[k][l].equalsIgnoreCase("CashAccountAltID1") ||temp[k][l].equalsIgnoreCase("CashAccountAltID2") ||temp[k][l].equalsIgnoreCase("CashAccountAltID3") ||temp[k][l].equalsIgnoreCase("CashAccountAltID4") ||temp[k][l].equalsIgnoreCase("CashAccountAltID5") ||temp[k][l].equalsIgnoreCase("OriginalValueDate") ||temp[k][l].equalsIgnoreCase("ProductType") ||temp[k][l].equalsIgnoreCase("ProductSubType") ||temp[k][l].equalsIgnoreCase("AlternateLinkId"))
{
if (temp[k][l].equalsIgnoreCase("AcctEntryId")){for(int m1 = 1; m1 < NoofRecords; m1++){ AcctEntryId.addValue(temp[m1][l]);}}
else if(temp[k][l].equalsIgnoreCase("ValueDate")){for(int m2 = 1; m2 < NoofRecords; m2++){ ValueDate.addValue(temp[m2][l]);}}
else if(temp[k][l].equalsIgnoreCase("Entity") ){for(int m3 = 1; m3 < NoofRecords; m3++){ Entity.addValue(temp[m3][l]);}}
else if (temp[k][l].equalsIgnoreCase("Folder") ){for(int m4 = 1; m4 < NoofRecords; m4++){ Folder.addValue(temp[m4][l]);}}
else if (temp[k][l].equalsIgnoreCase("DenomCcy") ){for(int m5 = 1; m5 < NoofRecords; m5++){ DenomCcy.addValue(temp[m5][l]);}}
else if (temp[k][l].equalsIgnoreCase("FunctCcy") ){for(int m6 = 1; m6 < NoofRecords; m6++){ FunctCcy.addValue(temp[m6][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeId") ){for(int m7 = 1; m7 < NoofRecords; m7++){ TradeId.addValue(temp[m7][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeVersion") ){for(int m8 = 1; m8 < NoofRecords; m8++){ TradeVersion.addValue(temp[m8][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeType") ){for(int m9 = 1; m9 < NoofRecords; m9++){ TradeType.addValue(temp[m9][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkId") ){for(int m10 = 1; m10 < NoofRecords; m10++){ LinkId.addValue(temp[m10][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkVersion") ){for(int m11 = 1; m11 < NoofRecords; m11++){ LinkVersion.addValue(temp[m11][l]);}}
else if (temp[k][l].equalsIgnoreCase("Counterparty") ){for(int m74 = 1; m74 < NoofRecords; m74++){ Counterparty.addValue(temp[m74][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctProcess") ){for(int m12 = 1; m12 < NoofRecords; m12++){ AcctProcess.addValue(temp[m12][l]);}}
else if (temp[k][l].equalsIgnoreCase("CashAccount") ){for(int m13 = 1; m13 < NoofRecords; m13++){ CashAccount.addValue(temp[m13][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctEntryDescr") ){for(int m14 = 1; m14 < NoofRecords; m14++){ AcctEntryDescr.addValue(temp[m14][l]);}}
else if (temp[k][l].equalsIgnoreCase("ReversesAcctEntryId") ){for(int m15 = 1; m15 < NoofRecords; m15++){ ReversesAcctEntryId.addValue(temp[m15][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctEntrySubSysId") ){for(int m16 = 1; m16 < NoofRecords; m16++){ AcctEntrySubSysId.addValue(temp[m16][l]);}}
else if (temp[k][l].equalsIgnoreCase("DenomCcyAmount") ){for(int m17 = 1; m17 < NoofRecords; m17++){ DenomCcyAmount.addValue(temp[m17][l]);}}
else if (temp[k][l].equalsIgnoreCase("FunctCcyAmount")  ){for(int m18 = 1; m18 < NoofRecords; m18++){ FunctCcyAmount.addValue(temp[m18][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctRule") ){for(int m19 = 1; m19 < NoofRecords; m19++){ AcctRule.addValue(temp[m19][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAcctNumber") ){for(int m20 = 1; m20 < NoofRecords; m20++){ AcctChartAcctNumber.addValue(temp[m20][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartDescr") ){for(int m21 = 1; m21 < NoofRecords; m21++){ AcctChartDescr.addValue(temp[m21][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAlternateId") ){for(int m22 = 1; m22 < NoofRecords; m22++){ AcctChartAlternateId.addValue(temp[m22][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctCategory") ){for(int m23 = 1; m23 < NoofRecords; m23++){ AcctCategory.addValue(temp[m23][l]);}}
else if (temp[k][l].equalsIgnoreCase("IsParentAcct") ){for(int m24 = 1; m24 < NoofRecords; m24++){ IsParentAcct.addValue(temp[m24][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartAcctNumber") ){for(int m25 = 1; m25 < NoofRecords; m25++){ ParentAcctChartAcctNumber.addValue(temp[m25][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartDescr") ){for(int m26 = 1; m26 < NoofRecords; m26++){ ParentAcctChartDescr.addValue(temp[m26][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartType") ){for(int m27 = 1; m27 < NoofRecords; m27++){ AcctChartType.addValue(temp[m27][l]);}}
else if (temp[k][l].equalsIgnoreCase("EntityAltId1") ){for(int m28 = 1; m28 < NoofRecords; m28++){ EntityAltId1.addValue(temp[m28][l]);}}
else if (temp[k][l].equalsIgnoreCase("EntityAltId2") ){for(int m29 = 1; m29 < NoofRecords; m29++){ EntityAltId2.addValue(temp[m29][l]);}}
else if (temp[k][l].equalsIgnoreCase("EntityAltId3") ){for(int m30 = 1; m30 < NoofRecords; m30++){ EntityAltId3.addValue(temp[m30][l]);}}
else if (temp[k][l].equalsIgnoreCase("EntityAltId4") ){for(int m31 = 1; m31 < NoofRecords; m31++){ EntityAltId4.addValue(temp[m31][l]);}}
else if (temp[k][l].equalsIgnoreCase("EntityAltId5") ){for(int m32 = 1; m32 < NoofRecords; m32++){EntityAltId5.addValue(temp[m32][l]);}}
else if (temp[k][l].equalsIgnoreCase("CptyAltId1") ){for(int m33 = 1; m33 < NoofRecords; m33++){CptyAltId1.addValue(temp[m33][l]);}}
else if (temp[k][l].equalsIgnoreCase("CptyAltId2") ){for(int m34 = 1; m34 < NoofRecords; m34++){ CptyAltId2.addValue(temp[m34][l]);}}
else if (temp[k][l].equalsIgnoreCase("CptyAltId3") ){for(int m35 = 1; m35 < NoofRecords; m35++){ CptyAltId3.addValue(temp[m35][l]);}}
else if (temp[k][l].equalsIgnoreCase("CptyAltId4") ){for(int m36 = 1; m36 < NoofRecords; m36++){ CptyAltId4.addValue(temp[m36][l]);}}
else if (temp[k][l].equalsIgnoreCase("CptyAltId5") ){for(int m37 = 1; m37 < NoofRecords; m37++){ CptyAltId5.addValue(temp[m37][l]);}}
else if (temp[k][l].equalsIgnoreCase("FolderAltId1") ){for(int m38 = 1; m38 < NoofRecords; m38++){ FolderAltId1.addValue(temp[m38][l]);}}
else if (temp[k][l].equalsIgnoreCase("FolderAltId2") ){for(int m39 = 1; m39 < NoofRecords; m39++){FolderAltId2.addValue(temp[m39][l]);}}
else if (temp[k][l].equalsIgnoreCase("FolderAltId3") ){for(int m40 = 1; m40 < NoofRecords; m40++){ FolderAltId3.addValue(temp[m40][l]);}}
else if (temp[k][l].equalsIgnoreCase("FolderAltId4") ){for(int m41 = 1; m41 < NoofRecords; m41++){ FolderAltId4.addValue(temp[m41][l]);}}
else if (temp[k][l].equalsIgnoreCase("FolderAltId5") ){for(int m42 = 1; m42 < NoofRecords; m42++){ FolderAltId5.addValue(temp[m42][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeGroup") ){for(int m43 = 1; m43 < NoofRecords; m43++){ TradeGroup.addValue(temp[m43][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeAcctCode") ){for(int m44 = 1; m44 < NoofRecords; m44++){ TradeAcctCode.addValue(temp[m44][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeAcctCode2") ){for(int m45 = 1; m45 < NoofRecords; m45++){ TradeAcctCode2.addValue(temp[m45][l]);}}
else if (temp[k][l].equalsIgnoreCase("CounterpartyTradeId") ){for(int m46 = 1; m46 < NoofRecords; m46++){ CounterpartyTradeId.addValue(temp[m46][l]);}}
else if (temp[k][l].equalsIgnoreCase("AlternateTradeId") ){for(int m47 = 1; m47 < NoofRecords; m47++){ AlternateTradeId.addValue(temp[m47][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeGroupAltId") ){for(int m48 = 1; m48 < NoofRecords; m48++){ TradeGroupAltId.addValue(temp[m48][l]);}}
else if (temp[k][l].equalsIgnoreCase("TradeAcctCodeAltId") ){for(int m49 = 1; m49 < NoofRecords; m49++){ TradeAcctCodeAltId.addValue(temp[m49][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkGroup") ){for(int m50 = 1; m50 < NoofRecords; m50++){LinkGroup.addValue(temp[m50][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkAcctCode") ){for(int m51 = 1; m51 < NoofRecords; m51++){LinkAcctCode.addValue(temp[m51][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkAcctCode2") ){for(int m52 = 1; m52 < NoofRecords; m52++){LinkAcctCode2.addValue(temp[m52][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkGroupAltId") ){for(int m53 = 1; m53 < NoofRecords; m53++){ LinkGroupAltId.addValue(temp[m53][l]);}}
else if (temp[k][l].equalsIgnoreCase("LinkAcctCodeAltId") ){for(int m54 = 1; m54 < NoofRecords; m54++){ LinkAcctCodeAltId.addValue(temp[m54][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAltId1") ){for(int m55 = 1; m55 < NoofRecords; m55++){AcctChartAltId1.addValue(temp[m55][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAltId2") ){for(int m56 = 1; m56< NoofRecords; m56++){ AcctChartAltId2.addValue(temp[m56][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAltId3") ){for(int m57 = 1; m57 < NoofRecords; m57++){ AcctChartAltId3.addValue(temp[m57][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAltId4") ){for(int m58 = 1; m58 < NoofRecords; m58++){AcctChartAltId4.addValue(temp[m58][l]);}}
else if (temp[k][l].equalsIgnoreCase("AcctChartAltId5") ){for(int m59 = 1; m59 < NoofRecords; m59++){AcctChartAltId5.addValue(temp[m59][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartAltId1") ){for(int m60 = 1; m60 < NoofRecords; m60++){ ParentAcctChartAltId1.addValue(temp[m60][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartAltId2") ){for(int m61 = 1; m61 < NoofRecords; m61++){ ParentAcctChartAltId2.addValue(temp[m61][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartAltId3") ){for(int m62= 1; m62 < NoofRecords; m62++){ ParentAcctChartAltId3.addValue(temp[m62][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartAltId4") ){for(int m63 = 1; m63 < NoofRecords; m63++){ ParentAcctChartAltId4.addValue(temp[m63][l]);}}
else if (temp[k][l].equalsIgnoreCase("ParentAcctChartAltId5") ){for(int m64 = 1; m64 < NoofRecords; m64++){ParentAcctChartAltId5.addValue(temp[m64][l]);}}
else if (temp[k][l].equalsIgnoreCase("CashAccountAltID1") ){for(int m65 = 1; m65 < NoofRecords; m65++){ CashAccountAltID1.addValue(temp[m65][l]);}}
else if (temp[k][l].equalsIgnoreCase("CashAccountAltID2") ){for(int m66 = 1; m66 < NoofRecords; m66++){CashAccountAltID2.addValue(temp[m66][l]);}}
else if (temp[k][l].equalsIgnoreCase("CashAccountAltID3") ){for(int m67 = 1; m67 < NoofRecords; m67++){ CashAccountAltID3.addValue(temp[m67][l]);}}
else if (temp[k][l].equalsIgnoreCase("CashAccountAltID4") ){for(int m68 = 1; m68 < NoofRecords; m68++){CashAccountAltID4.addValue(temp[m68][l]);}}
else if (temp[k][l].equalsIgnoreCase("CashAccountAltID5") ){for(int m69 = 1; m69 < NoofRecords; m69++){ CashAccountAltID5.addValue(temp[m69][l]);}}
else if (temp[k][l].equalsIgnoreCase("OriginalValueDate") ){for(int m70 = 1; m70 < NoofRecords; m70++){ OriginalValueDate.addValue(temp[m70][l]);}}
else if (temp[k][l].equalsIgnoreCase("ProductType") ){for(int m71 = 1; m71 < NoofRecords; m71++){ ProductType.addValue(temp[m71][l]);}}
else if (temp[k][l].equalsIgnoreCase("ProductSubType") ){for(int m72 = 1; m72 < NoofRecords; m72++){ ProductSubType.addValue(temp[m72][l]);}}
else {for(int m73 = 1; m73 < NoofRecords; m73++){ AlternateLinkId.addValue(temp[m73][l]);}}
}
else{
throw new StreamTransformationException( " Column name " + temp[k][l] + " in the file is not matching with our column names");
}
}//close brace for for loop
}

For better understanding and readability I'm providing testcases in Part2

Reading a delimeter separated file whoose columns may jumble (Test Cases)

$
0
0

Here I'm going to cover Test cases.

 

Case1:Here I'm taking .csv file (Without jumbling of columns)

 

   XML payload after applying FCC in sender file channel.

 

Test1.JPG

 

    Output xml payload after execution of Mapping1

 

Test2.JPG

 

   XML input payload of Mapping2:(Mapping1 output payload will be input to this mapping)

 

Test3.JPG

   Output xml payload after execution of Mapping2

 

  Test4.JPG

 

Case2:Here I'm taking .csv file (Columns jumbled)


   XML payload after applying FCC in sender file channel.

 

Test11.JPG

 

Output xml payload after execution of Mapping1

 

Test22.JPG

 

   XML input payload of Mapping2:(Mapping1 output payload will be input to this mapping)

Test33.JPG

   Output xml payload after execution of Mapping2

Test44.JPG

 

Here is the link for navigation to Part1

 

Regards

Venkat

Message Comparison in SAP PI/PO Integration Cockpit

$
0
0

     In Today's business world transactions via EDI (Electronic Data Interchange) messages have become a popular choice. As EDI provides paper-less transmission, it is quite a common way for companies to exchange their Data. Traditionally you would either need to buy an additional adapter or you could use the File Adapter in collaboration with a tool called ItemField Conversion Agent to handle the EDI messages, However, with the release of new B2B Add On, SAP has bridged the gap of working with EDI messages efficiently and easily.

 

     There are various EDI messages for different business use. To learn more on EDI please check the link EDI-ELECTRONIC DATA INTERCHANGE - Process Integration - SCN Wiki

 

     The B2B integration cockpit is a central application that allows you to monitor and access business-to-business add-on from SAP NW PI environment.

 

           With this webblog we will understand how to compare various versions of EDI. After reading this blog you will be able to compare EDIFACT, EANCOM ANSI X12, ODETTE, TRADACOMS, VDA and PLAIN messages.

      Now let us see how we can do this:

 

  • Log on to Integration Cockpit.  Path: “http:<localhost:port>/b2bic” (http://<localhost:port>/webdynpro/dispatcher/sap.con/b2b~home/B2BHome)
  • Click on “EDI Content Manager

     pic1.png

  • Click on “Compare messages” on the right hand top corner.

pic2.png

And you will be directed to the page

 

pic3.png

Provide the Format, Control Key, Version and Message for the two messages you want to compare.

 

  • You can either show the complete message or show only the differences. Select as need and select “Compare"

pic4.png

 

  • You will now see the difference between the two messages you have selected.

 

Highlights:

  • Compare two message definitions
  • Different colors represent similarities and differences
  • Optionally include detailed segment level comparison
  • Currently available for EDIFACT, X12 and EANCOM

 

Further references:

 

December 2013 Spotlight: SAP NetWeaver Process Orchestration PI | B2B | BPM | BRM

To crete and test custom EDI message version : 

B2B scenario - creating and testing custom EDI message version- ANSI X12 855v2000

 

Regards,

Lakshmi Naik


Simple Steps to build an Adapter Module using EJB,EAR template

$
0
0

To build an adapter module in SAP XI/PI/PO there are many standard step by step SAP documents, blogs etc.. available on SAP SDN.

 

How this blog is different?


Well, this blog indirectly covers all those common steps but in the form of a EJB, EAR project template to simplify development effort in Netweaver Developer Studio (NWDS)

 

How to make use of EJB,EAR template?

 

Quite easy Download the EJB,EAR template zip file from https://app.box.com/s/n2amg8rcts8vc9a0csfk. (Also attached to this blog now) In NWDS, File menu -> Import option wizard (General -> Existing Projects into Workspace) and load the downloaded zip file into your NWDS workspace as EJB, EAR projects

 

What all changes required to the imported projects?

 

  1. Right click on both the imported EJB and EAR projects together (use CTRL key) and then in the context menu click validate to see if any errors
  2. Right click on the imported EJB project to configure build path to the mandatory module API jars/external jars ( Beginners, please refer to steps 4.1, 4.2 and 4.7 for required jar files and detailed procedure http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/c0b39e65-981e-2b10-1c9c-fc3f8e6747fa?QuickLink=index&overridelayout=true)
  3. Rename (Refactor option in the context menu of right click on EJB project) YourAdapterModule_EJB to desired name as per your project requirement e.g., for this demo I am using ForSDNDemo_EJB
  4. Expand ForSDNDemo_EJB project and then refactor the current java package “yourpackagename” according to your project requirement e.g., for this demo I am using “com.sapsdn.demo” as package for module development. Ignore any errors during this step and continue
  5. Similarly refactor “YourAdapterModuleBean” java file to your own java file. E.g., ForSDNDemoBean. Click Next -> and then Finish. ** Amend the java code according to your requirement with your code
  6. Optional step but it is a good practice: Open ForSDNDemoBean.java file, and then find (CTRL+F) “YourAdapterModuleBean.java” and replace with ForSDNDemoBean.java (import extra packages and add your own java code according to your requirement) and also replace yourpackagename with your project package i.e., in this demo com/sapsdn/demo
  7. ** Expand META-INF folder and then open ejb-j2ee-engine.xml -> go to source tab, then change <ejb-name> tag value to ForSDNDemo (same as your EJB project name)from YourAdapterModule. Also, the most important <jndi-name> tag value to your specific jndi-name, for this demo I used  ForSDNDemoJNDI as jndi name in place of YourAdapterModuleJNDI
  8. Similary, change <ejb-name> tag value of ejb-jar.xml to ForSDNDemo (same as your EJB project name)  from YourAdapterModule
  9. Build your EJB project from its context menu when you are done with above steps
  10. Finally rename YourAdapterModule_EAR project to ForSDNDemo _EAR and then export project as SAP EAR File for deployment into XI system by BASIS team (or) directly deploy to XI server from EAR project context menu Run AS -> Run on Server. For direct deployment option please refer 4.11 and 4.12 sections of above step1 reference SAP document

 

Hope the above procedure is clear and helps you to build your custom module requirement easily. Appreciate your feedback and comments to improvise this blog content

 

Few important snap shots for above procedure,

 

1)ImportProjectWizard.jpg

2)OpenProject.jpg

3)Finish.jpg

4)RefactorEJBProject.jpg

5)RefactorJavaPackage.jpg

6)RefactorModuleBeanJavaFile.jpg

 

Best Regards,

Praveen Gujjeti

Using XPath expression to check existence of a leaf node in a repeated parent strucutre node

$
0
0

I  write this short blog just to share how to use an XPath expression in the expression editor to check a message in receiver determination, if a leaf node exists in every repeated parent structure node. This is not so trivial at first thought.

 

The inbound message contains a structure DELVRY03/IDOC/E1EDL20/E1EDL24/KDMAT, where KDMAT is a leaf node which doesn't contain any sub structure more. Only messages, where KDMAT exists in every E1EDL24 node, are passed by to defined receiver, otherwise it will be ignored.

 

For this requirement we can't simply use a expression like DELVRY03/IDOC/E1EDL20/E1EDL24[KDMAT] with operator "EX" and the option Multiline checked. Because if a message has multi E1EDL24, and some E1EDl24 has KDMAT, some doesn't have KDMAT. It still will be processed. And expression like:

DELVRY03/IDOC/E1EDL20/E1EDL24/KDMAT != '' or

DELVRY03/IDOC/E1EDL20/E1EDL24/KDMAT CP * (KDMAT contains pattern of any string)

will also not work, because if one E1EDL24 doesn't have  KDMAT, then the message will also be processed.

 

According to the SAP help documentation for expression editor:

Note that XPath expressions created with the expression editor can only return items of type node (node, node set). For technical reasons, other types (such as Boolean value) are not permitted.

So we can't use a XPath expression which return a boolean value like:

count(DELVRY03/IDOC/E1EDL20/E1EDL24) = count(DELVRY03/IDOC/E1EDL20/E1EDL24[KDMAT])


After some thought I came to this expression, which solved my problem:

left operand: DELVRY03/IDOC/E1EDL20[not(E1EDL24[not(KDMAT)])]

operator: EX

Multilin option: enabled


It means there is no E1EDL24 without KDMAT. The trick part is, it has double negations. In other word it means, every E1EDL24 has child node KDMAT, and that is exactly what I want.

 

I hope someone else can also find this helpful for similar case.

Dynamic Routing in SAP PI 7.31

$
0
0

Introduction:
This article will describe the steps to dynamically determine the receiver of
incoming message in PI and the use of Parameter in Operation Mapping and NWDS
in PI 7.31.

 

Requirement: Sometimes determining the receiver using the simple static routing rules for the incoming messages is not straight forward. In this scenario, the receiver is determined based on qualifiers of the incoming message and to configure runtime behavior to ensure that the names of the receivers are determined at runtime by a mapping program.

 

Aim:This blog explains the solution in which an operation mapping is used to dynamically determine the receiver of the incoming message. It also explains the use of a parameter in Operation mapping. A parameter (like a variable in ABAP) can be defined in the  mapping and the value can be assigned in NWDS. Parameter can be used if the receiver system is different based on the environments like SAP system. This value can be replaced with the current SAP system (Dev, QA and Prod).In any project, this dynamic routing can be used by creating a separate message mapping and operation mapping program to determine the receivers and use the same in Integration Directory.

 

Steps:

 

 

     ESR

 

 

  1. Define a separate Mapping for dynamic Receiver
    determination. In this mapping the source is the incoming message and the
    target is the Message type Receivers. This message type is provided by SAP
    under the software component of SAP BASIS and namespace of
    http://sap.com/xi/XI/System. The receiver system based on the routing logic is mapped to SERVICE of the Receivers as shown below.

 

      1.JPG

 

 

 

  2. The parameter that we want to use in the
      mapping above needs to be defined in Signature tab of the message mapping and then
      can be used in the mapping as constants.

 

 

 

2.JPG

3.JPG

 

  3. Define an Operation Mapping for dynamic routing.
                    In this operation mapping the sender interface is your usual sender interface but the receiver interface is Receiver        Determination which is again available in the same software component as that of Receivers and the mapping used is the one created above for determining the receivers. Once the mapping is selected, create the binding for the message mapping parameter and the operation mapping parameters.

 

 

4.JPG

 

4. The testing of the mapping can be done in the
     usual way – except for the value for the parameter can be given in ‘Parameters’
     tab of Test.

 

 

5.JPG

 

 

NWDS

 

 

5. Configure the interface in NWDS as dynamic message router.

 

 

6.JPG

 

 

6. Now the same Operation Mapping is to be configured in NWDS using the dynamic routing. The Parameter that we have
defined in ESR automatically appears once the Operation Mapping is selected.The value for the Parameter can be given here in each system to determine the receiver dynamically.

 

 

 

7.JPG

 

 

 

Summary: This completes the requirement and the steps to achieve the same. To recall,
this method is used to determine the receivers at runtime by a mapping program
using the parameter. And to achieve this, a dynamic operation mapping is
defined and a parameter is declared for a receiver, binding for the same needs
to be done in ESR. Finally this is configured in the NWDS to make this
interface work.

 

 

Reference: https://help.sap.com/saphelp_nw73/helpdata/en/3c/68a82e9ed8424cb53f61c7e26c1ae0/content.htm

SAP PI 7.1 Mapping Enhancements Series: Parameterized Message Mappings

 

 

 

Michal's PI tips: How to trigger an alert for Component Based Message Alerts (CBMA) via "API" ?

$
0
0

With ABAP stack alerting it was possible to generate an alert using a function module which could be called from many different places (message mapping - RFC lookup, adapter module, abap proxy etc.). like shown in other blogs:

How to raise alerts from ABAP Proxy

For Component Based Message Alerts we currently don't have an API which would allow trigerring alerts. Does not mean however that we cannot easily create it on our own. In this article I will try to show a concept which shows how to create a simple "API" for generating custom alerts in CBMA.

 

General idea:

 

Create HTTP callable integration flow which will server as an alert service.

 

Implementation:

 

a) create an integration configuration (ICO) flow which will always fail (for example wrong condition in receiver determination)

 

b) use a XML structure which will hold all the information details which you want to see in the alert monitoring for example:

 

<MessageID>

<InterfaceID>

<Priority> 

 

c) as we want to be able to call this "API" from many different places use SOAP (HTTP) as an outbound adapter (this way we can call it from majority of the applications)

 

d) create an alert rule where you add the ICO created above as an object to be monitored and make sure you select the field "Payload in alert" is set to enabled

 

api_pic1.png

 

e) create user defined message search on the outbound service interface for all important fields which need to be monitored

 

api_pic_2.png

 

 

Testing:

 

a) call the your ICO via HTTP from any kind of tool (like soapui) and populate the xml with the alert related info.


<MessageID>123114214</MessageID>

<InterfaceID>MICHAL_KRAWCZYK_TEST_API</InterfaceID>

<Priority>HIGH</Priority>

 

b) inside the Message Monitor you should be able to see all relevant details as shown below

 

api_pic3.png

 

c) when you receive the alert it should also contain all the important information (as user defined attributes) which you wanted to pass to the alert

 

api_pic4.png

 

 

Conclusion:

 

This is the alternative way to be able to receive all kinds of alerts with alert specific information.

 

Drawback : Clean up jobs.

 

If you use this approach you need to remember to take care of the failed messages (cancel them) as in standard failed messages will not get archived.


Reference:


How to use CMBA - Michal's PI tips: Component-Based Message Alerting



A new approach: Multi-mapping Dynamic Configuration using a generic custom module

$
0
0

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

 

TargetStructure.png

  • 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,
    1. DCXPATH - to evaluate dynamic headers from the child payload e.g., for the above defined structure it will be /MT_Receiver/DCHeader/DCRecord
    2. 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



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..


 


Interface Transition Strategy – Legacy system as preference/capability to change

$
0
0

Introduction :

This is a high level summary for the Interface Transition strategy using Legacy system as preference/capability to change.The Transition Period is the changeover period of time when between a legacy system and a new system.  During the Transition Period both systems may need to operate to sustain the business stability. In a nutshell one state or stage must change to another without impacting the business.

 

This has special implications for Middle ware/ Integration layer, such as Process Integration / Process Orchestration that may be required to ensure both systems are kept in synch.

 

The Transition period can be handled in different ways.  Here are three common ways to handle Transition Periods.

 

1) Business system as preference/capability to change

2) Legacy system as preference/capability to change

3) Middle ware/Integration as preference/capability to change

 

The combination and hybrid of above three also can be implemented to achieve the Transition Strategy.

 

               Legacy system as preference/capability to change Interface Transition Strategy

 

If the legacy system is the preference or capability to change in the Interface Transition Strategy, the following points should be considered.

 

 

  1. The customer prefers not to change the existing code/ connection of their business system/ third party system
  2. The business system, as per the existing state, will interact with the legacy system during transition period
  3. The legacy system will interact with Middle ware. The required data is updated /transformed in the middle ware  to feed the new system during the transition period
  4. Data synchronisation is required between legacy and new system, to synchronise the master data.
  5. The middle ware handles data transitions between the legacy and the new system.  To handle this, the middle ware might need to use a temporary code. It is a good idea to maintain the temporary code/s required for the transition period in middle ware, so that the customer can control, fix and monitor in the one place, as well as  it is easy in switching to the permanent interface

 

 

       Legacy system preference.PNG

 

 

 

Blue colour: No changes (using the existing code/ connection/ drivers)

Green colour: Minor changes (changes like driver/connection/ ftp change/ less than one day code changes, per interface)

Yellow colour: Medium changes (code changes – less than two days, per interface)

Brown colour: High changes (code changes – less than four days, per interface)

Red colour:  Very high changes (code changes – more than four days for one interface, custom and temporary code for transition)


 

Summary :

This is a high level summary for the Interface Transition strategy using Legacy system as preference/capability to change.

 

The goal of this blog is to help users to make aware of the Interface Transition Evaluation Guidelines using Legacy system.  These recommendations are based on my personal experience in SAP Implementation as an SAP employee and technical architect. The user can follow the suggestions provided by the blog and it should supplement with additional information. With any transition strategy proof of concept is a good way to minimise the risk and any unforeseen issues.

 

                  Interface Transition Strategy – Business system as preference/capability to change

Interface Transition Strategy – Business system as preference/capability to change

 

                  Interface Transition Strategy – Middle ware/Integration as preference/capability to change

Interface Transition Strategy – Middleware/Integration as preference/capability to change

 

Please note: These suggestions are high level suggestions, individual projects might require specific custom variations or another approach, based on the project requirement.

 

Reference :

http://scn.sap.com/community/pi-and-soa-middleware/blog/2013/08/29/interface-transition-evaluation-guide


Interface Transition Strategy – Middleware/Integration as preference/capability to change

$
0
0

Introduction :

This is a high level summary for the Interface Transition strategy using Middle ware /Integration system as capability to change.The Transition Period is the changeover period of time when between a legacy system and a new system.  During the Transition Period both systems may need to operate to sustain the business stability. In a nutshell one state or stage must change to another without impacting the business.

 

This has special implications for Middle ware/ Integration layer, such as Process Integration / Process Orchestration that may be required to ensure both systems are kept in synch.

 

The Transition period can be handled in different ways.  Here are three common ways to handle Transition Periods.

 

1) Business system as preference/capability to change

2) Legacy system as preference/capability to change

3) Middle ware/Integration as preference/capability to change

 

The combination and hybrid of above three also can be implemented to achieve the Transition Strategy.

 

               Interface Transition Strategy – Middle ware/Integration as preference/capability to change


If the Middle ware system is the first preference or capability to change in the Interface Transition Strategy, the following points should be considered

 

 

  1. The customer prefers to do more coding activity in middle ware than the business system/ legacy/ new system
  2. The business system will interact with the middle ware system. The middle ware system splits the data and updates the legacy and new system during the transition period
  3. Data synchronisation is required between the legacy system and new system, in order to synchronise the master data
  4. The middle ware handles data transition between the legacy system and the new system. To handle it, the middle ware might need a temporary code. It is a good idea to maintain the temporary code/s required for the transition period in middle ware, so that the customer can control, fix and monitor in the one place, as well as easily switching to the permanent interface

 

    Integration system preference.PNG

 

Blue colour: No changes (using the existing code/ connection/ drivers)

Green colour: Minor changes (changes like driver/connection/ ftp change/ less than one day code changes, per interface)

Yellow colour: Medium changes (code changes – less than two days, per interface)

Brown colour: High changes (code changes – less than four days, per interface)

Red colour:  Very high changes (code changes – more than four days for one interface, custom and temporary code for transition)


 

Summary :

This is a high level summary for the Interface Transition strategy using Middle ware system as preference/capability to change.

 

The goal of this blog is to help users to make aware of the Interface Transition Evaluation Guidelines using Middle ware system.  These recommendations are based on my personal experience in SAP Implementation as an SAP employee and technical architect. The user can follow the suggestions provided by the blog and it should supplement with additional information. With any transition strategy proof of concept is a good way to minimise the risk and any unforeseen issues.

 

                Interface Transition Strategy – Business system as preference/capability to change

Interface Transition Strategy – Business system as preference/capability to change

 

               Interface Transition Strategy – Legacy system as preference/capability to change

Interface Transition Strategy – Legacy system as preference/capability to change

 

Please note: These suggestions are high level suggestions, individual projects may require specific custom variations or another approach, based on the project requirement.

 

Reference :

http://scn.sap.com/community/pi-and-soa-middleware/blog/2013/08/29/interface-transition-evaluation-guide



Interface Transition Strategy – Business system as preference/capability to change

$
0
0

Introduction :

This is a high level summary for the Interface Transition strategy using Business system as preference/capability to change.

 

The Transition Period is the changeover period of time when between a legacy system and a new system.  During the Transition Period both systems may need to operate to sustain the business stability. In a nutshell one state or stage must change to another without impacting the business.

 

This has special implications for Middle ware/ Integration layer, such as Process Integration / Process Orchestration that may be required to ensure both systems are kept in synch.

 

The Transition period can be handled in different ways.  Here are three common ways to handle Transition Periods.

 

1) Business system as preference/capability to change

2) Legacy system as preference/capability to change

3) Middle ware/Integration as preference/capability to change

 

The combination and hybrid of above three also can be implemented to achieve the Transition Strategy.

 

               Business system as preference/capability to change  –  Interface Transition Strategy

 

If the Business system is the preference or capability to change in the Interface Transition Strategy, the following points should be considered.

 

  1. The customer’s preference is to change the existing code/connection of their business system / third party system
  2. If the business system is unable to the change its existing connections it will interact with the legacy system as it is (i.e. the current state)
  3. If the business system is willing to change its connection parameters, then it will interact with Middle ware as per the first option.  then the required data is split by the Middle ware to update the legacy system and new system during the transition period
  4. Data synchronisation is required between the legacy and the new system, to synchronise the master data.
  5. The middle ware handles data transitions between the legacy and the new system. To handle this, the middle ware might need a temporary code. It is good idea to maintain the temporary code/s required for transition period in the Middle ware, so that the customer can control, fix and monitor in the one place, as well as easily switching to the permanent interface

 

 

      Business system preference.PNG

 

 

Blue colour: No changes (using the existing code/ connection/ drivers)

Green colour: Minor changes (changes like driver/connection/ ftp change/ less than one day code changes, per interface)

Yellow colour: Medium changes (code changes – less than two days, per interface)

Brown colour: High changes (code changes – less than four days, per interface)

Red colour:  Very high changes (code changes – more than four days for one interface, custom and temporary code for transition)


 

Summary :

This is a high level summary for the Interface Transition strategy using Business system as preference/capability to change.

 

The goal of this blog is to help users to make aware of the Interface Transition Evaluation Guidelines using Legacy system.  These recommendations are based on my personal experience in SAP Implementation as an SAP employee and technical architect. The user can follow the suggestions provided by the blog and it should supplement with additional information. With any transition strategy proof of concept is a good way to minimise the risk and any unforeseen issues.

 

                     Interface Transition Strategy – Legacy system as preference/capability to change

Interface Transition Strategy – Legacy system as preference/capability to change

 

                     Interface Transition Strategy – Middle ware/Integration as preference/capability to change

Interface Transition Strategy – Middleware/Integration as preference/capability to change

 

Please note: These suggestions are high level suggestions, individual projects might require specific custom variations or another approach, based on the project requirement.

 

Reference :

http://scn.sap.com/community/pi-and-soa-middleware/blog/2013/08/29/interface-transition-evaluation-guide

SuccessFactors (SFSF) Adapter for SAP NetWeaver Process Integration

$
0
0

SAP has released a new adapter called the “SFSF Adapter” for SAP NetWeaver Process Integration (PI) on 17 Feb 2014. This adapter is now available as part of a release independent add-on “SAP NetWeaver Process Integration, connectivity add-on 1.0”.

 

The connectivity add-on runs on the SAP NetWeaver Process Integration Adapter Framework, based on the Java Connector Architecture (JCA). Accordingly, its capabilities are being used for enabling the common message delivery options (exactly-once, exactly-once-in-order), an automatic retry mechanism and information logging. The configuration of connectivity adapters, monitoring and operations is done in the same way as for other adapters of SAP NetWeaver Process Integration (PI). The connectivity add-on runs fully in the Java stack and supports all valid deployment options of SAP NetWeaver Process Integration (ABAP + Java, Java only).


This SAP NetWeaver Process Integration, connectivity add-on 1.0 is included in your SAP Process Integration license and you do not need any further license to use the adapter.


Overview

 

With increasing focus on cloud applications, customers are looking for options to integrate their existing on premise systems and applications with SuccessFactors. SFSFadapter provides this capability and can be used for on premise to SuccessFactors integration.

 

11.jpg

 

Some example scenarios for integration between SAP ERP HCM and SuccessFactors Employee Central and how they can be achieved using the SFSF adapter:

 

1. Employee Central Compound Employee to ERP HCM Employee Replication

 

12.jpg

2. ERP HCM Cost Center to Employee Central Cost Center

13.jpg


3. Employee Central Compound Employee to ERP HCM Employee Organizational Replication

14.jpg

Prerequisites


  1. SAP NetWeaver Process Integration (for supported SP’s refer the Compatibility Matrix below)
  2. Administrative access to the following:
    • System landscape directory (SLD)
    • SUM tool
    • Enterprise service tool
    • SAP NetWeaver Administrator (NWA)

 

Capabilities of the SFSF Adapter


  1. Login, Logout and Session Handling - The SFSF adapter uses basic authentication (user ID and password) for verifying the identity of the user. When you log in to the SuccessFactors system, it generates a session token that is required for transacting with the system. The SFSF adapter uses this token for session handling. The adapter internally takes care of login, logout and session handling.
  2. Query, Insert, Update and Upsert Operations - The SFSF adapter supports all standard SFAPI operations: Query, Insert, Update and Upsert. These operations help you to send and receive data from the SuccessFactors system.
  3. Simple and Compound SFAPI - The Simple SFAPI’s are flat structured entities whereas Compound SFAPI’s are nested entities. Both types of entities are supported by SFSF Adapter.  For more details on the Employee Central Entities, read the blog Employee Central Entities and Interfacing
  4. Auto XSD Generation for Mapping - The SFQL when modeled using the Operations Modeler generates an XSD file which can be used mapping purposes.
  5. Automatic Data Polling using Scheduler - The scheduler enables you to configure SFSF adapter as a Sender Channel to automatically poll data from the SuccessFactors system at a regular interval.
  6. Delta Sync - The delta sync features enables you to fetch only the records that were modified after the last successful data fetch from the SuccessFactors system. This increases the efficiency of the query operation.
  7. Dynamic query specification using payload - The Process Integration mappings can be used to dynamically specify query using PI payload as and when you execute it.
  8. Multiple SFSF calls and merge payloads - You can use the SFSF adapter to initiate multiple lines of communication to the SuccessFactors system multiple times.

 

Compatibility Matrix


SAP NetWeaver Process Integration, connectivity add-on 1.0 SP0 is compatible with:

  • SAP NW PI 711 >=SP12
  • SAP NW PI 730 >=SP10
  • SAP NW PI 731 >=SP09
  • SAP NW PI 740 >=SP04

 

Additional Resources


  1. Documentation:  SAP NetWeaver Process Integration, connectivity add-on 1.0
  2. Download Link: http://service.sap.com/swdc  > Software Downloads > Support Packages and Patches  > Browse our Download Catalog > SAP NetWeaver and complementary products > SAP NW PI CONNECTIVITY ADDON > PI CONNECTIVITY ADDON 1.0

 

 

Hope this blog helped you know the new SFSF adapter and its capabilities. Please send in your feedback via the comments section.

 

Stay tuned for the next blog: How-to configure the SFSF adapter for SAP NetWeaver Process Integration?

Adapter Module: AdapterModuleDCBypass

$
0
0

Adapter Module: AdapterModuleDCBypass


Use

Some adapters support specific message attributes, which contain additional information about messages. This information is not located in the payload of the message, but in additional message header fields called Dynamic Configuration. These attributes can be accessed in routing and mapping by using the attribute namespace and the technical name of the attribute.

 

Every time an adapter module is executed, message header is transferred from input to output message. However, when using Integrated Configuration Objects (ICOs), this header section is omitted on synchronous scenarios. The result is Dynamic Configuration section's missing.

 

You use AdapterModuleDCBypass module to prevent Dynamic Configuration attributes to be deleted after adapter module is executed. It uses Supplemental Data, a Module Data area, to store temporarily all Dynamic Configuration properties before adapter module execution. Afterwards, AdapterModuleDCBypass retrieve all the properties stored in Supplemental Data and writes them back to Dynamic Configuration section.



 

 

Deployment

Enterprise Java Bean Project: AdapterModuleDCBypass-ejb

Enterprise Java Bean Application: AdapterModuleDCBypass-ear

 

 

Integration

The module can be used in any Sender or Receiver Adapter.

 

Activities

This section describes all the activities that have to be carried out in order to configure the module.

 

Entries in processing sequence

Insert the module before and after the adapter module as shown in the picture below.

 

 

Entries in the module configuration


 

 

The table below shows the possible parameters and values of the adapter module.

 

ParameterTypePossible ValuesDescription
moderequiredDynamicConfiguration_to_ModuleData  | ModuleData_to_DynamicConfiguration

The mode parameter specifies the execution mode of the module.


When mode is [DynamicConfiguration_to_ModuleData] the module retrieves attributes from Dynamic Configuration and copies them to Module Data.


When mode is [ModuleData_to_DynamicConfiguration] the module retrieves attributes from Module Data and copies them to Dynamic Configuration.

 

 

Audit Log

The execution process can be followed in the audit log generated per message.



AdapterModuleDCBypassBean

 

package com.rav.integrations.modules;
import java.rmi.RemoteException;
import java.util.Enumeration;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import com.sap.aii.af.lib.mp.module.ModuleContext;
import com.sap.aii.af.lib.mp.module.ModuleData;
import com.sap.aii.af.lib.mp.module.ModuleException;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.engine.interfaces.messaging.api.Message;
import com.sap.engine.interfaces.messaging.api.MessageKey;
import com.sap.engine.interfaces.messaging.api.MessagePropertyKey;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
/**
* @author Roger Allué Vall
*
*/
public class AdapterModuleDCBypassBean implements SessionBean, TimedObject {    private static final long serialVersionUID = -1910739162843853923L;    private static final String C_MODE_DC2MD = "DynamicConfiguration_to_ModuleData";    private static final String C_MODE_MD2DC = "ModuleData_to_DynamicConfiguration";    private static final String C_PARAM_MODE = "mode";    private static final String C_KEY_SEPARATOR = "#";    private static MessageKey amk;    /*     * (non-Javadoc)     *     * @see javax.ejb.SessionBean#ejbActivate()     */    @Override    public void ejbActivate() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /*     * (non-Javadoc)     *     * @see javax.ejb.SessionBean#ejbPassivate()     */    @Override    public void ejbPassivate() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /*     * (non-Javadoc)     *     * @see javax.ejb.SessionBean#ejbRemove()     */    @Override    public void ejbRemove() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /*     * (non-Javadoc)     *     * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)     */    @Override    public void setSessionContext(SessionContext arg0) throws EJBException,            RemoteException {        // TODO Auto-generated method stub    }    /*     * (non-Javadoc)     *     * @see javax.ejb.TimedObject#ejbTimeout(javax.ejb.Timer)     */    @Override    public void ejbTimeout(Timer arg0) {        // TODO Auto-generated method stub    }    public void ejbCreate() throws javax.ejb.CreateException {    }    public ModuleData process(ModuleContext moduleContext,            ModuleData inputModuleData) throws ModuleException {        String mode = "";        Message msg;             try {            msg = (Message) inputModuleData.getPrincipalData();            amk               = new MessageKey(msg.getMessageId(), msg.getMessageDirection());            addInfo("AdapterModuleDCBypassBean begin...");            try {                mode = moduleContext.getContextData(C_PARAM_MODE);                if (mode != null && !mode.equals(C_MODE_DC2MD) && !mode.equals(C_MODE_MD2DC)) {                    mode = C_MODE_DC2MD;                }            } catch (Exception e) {                mode = C_MODE_DC2MD;            }            if (mode.equals(C_MODE_DC2MD)) {                     addInfo("AdapterModuleDCBypassBean: mode - " + C_MODE_DC2MD);                dcToMD(inputModuleData);                 } else if (mode.equals(C_MODE_MD2DC)) {                     addInfo("AdapterModuleDCBypassBean: mode - " + C_MODE_MD2DC);                     mdToDC(inputModuleData);                 }        } catch (Exception e) {            addInfo("AdapterModuleDCBypassBean: Exception found: " + e.getMessage());        }        addInfo("AdapterModuleDCBypassBean end...");        return inputModuleData;    }    @SuppressWarnings("unchecked")    private void mdToDC(ModuleData inputModuleData) throws ModuleException {        Message msg = null;        MessagePropertyKey key;        String propertyName = "";        String propertyNamespace = "";        String supplementalDataName;        String supplementalData;        String[] str;        try {            msg = (Message) inputModuleData.getPrincipalData();            Enumeration<String> supplementalDataNamesList = inputModuleData.getSupplementalDataNames();            while(supplementalDataNamesList.hasMoreElements()){                supplementalDataName = supplementalDataNamesList.nextElement();                supplementalData = (String) inputModuleData.getSupplementalData(supplementalDataName);                     str = supplementalDataName.split(C_KEY_SEPARATOR);                if (str.length > 1){                    propertyName = str[0];                    propertyNamespace = str[1];                             key = new MessagePropertyKey(propertyName,propertyNamespace);                    msg.setMessageProperty(key, supplementalData);                             }                 }            inputModuleData.setPrincipalData(msg);        } catch (Exception e) {            throw new ModuleException(e.getMessage(), e);        }    }    private void dcToMD(ModuleData inputModuleData) throws ModuleException {        Message msg = null;        String propertyName = "";        String propertyNamespace = "";        String supplementalDataName;        String supplementalData;        try {            msg = (Message) inputModuleData.getPrincipalData();            for (MessagePropertyKey key : msg.getMessagePropertyKeys()) {                propertyName = key.getPropertyName();                propertyNamespace = key.getPropertyNamespace();                supplementalDataName = propertyName + C_KEY_SEPARATOR + propertyNamespace;                supplementalData = msg.getMessageProperty(key);                 inputModuleData.setSupplementalData(supplementalDataName, supplementalData);            }        } catch (Exception e) {            throw new ModuleException(e.getMessage(), e);        }    }    private void addInfo(String msg) {        try {            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, msg);        } catch (Exception e) {            Audit.addAuditLogEntry(amk, AuditLogStatus.ERROR,                    "Error a l'obrir el fitxer!");        }    }    private void addWarning(String msg) {        try {            Audit.addAuditLogEntry(amk, AuditLogStatus.WARNING, msg);        } catch (Exception e) {            Audit.addAuditLogEntry(amk, AuditLogStatus.ERROR,                    "Error a l'obrir el fitxer!");        }    }    private void addError(String msg) {        try {            Audit.addAuditLogEntry(amk, AuditLogStatus.ERROR, msg);        } catch (Exception e) {            Audit.addAuditLogEntry(amk, AuditLogStatus.ERROR,                    "Error a l'obrir el fitxer!");        }    }
}

Adapter Module: AddTimeStamp

$
0
0

Use

 

AddTimeStamp module can be used to construct a new filename with a special timestamp format. The module sets a new value for the Dynamic Configuration key ["FileName",http://sap.com/xi/XI/System/File] according to the parameters FILENAME_PREFIX, FILENAME_SUFIX and TIMESTAMP_FORMAT.


The new filename is constructed as follows:

 

FILENAME = <PREFIX_TAG> + SYSTEM_TIMESTAMP(TS_FORMAT) + <SUFIX_TAG>

This module has been developed to simulate the functionality “Add Timestamp” of the Receiver File/FTP Adapter and allow user to customize the timestamp formatting to override the standard format yyyymmdd-HHMMDD-SSS.

 

Deployment

Enterprise Java Bean Project: AddTimeStamp_EJB

Enterprise Java Bean Application: AddTimeStamp_EAR

 

Integration

The module can be used in Sender and Receiver File/FTP Adapters.

 

 

Adapter specific option File Name has to be active.

 

 

 

 

Activities

This section describes all the activities that have to be carried out in order to configure the module.

 

Entries in processing sequence

Insert the module in front of the adapter module as shown in the picture below.

 

 

 

Entries in the module configuration


 

The table below shows the possible parameters and values of the adapter module.


 

ParameterTypePossible ValuesDescriptionExample
FILENAME_PREFIXOptional

Any alphanumeric character except: < > : " / \ | ? *

This parameter specifies the string to be placed before the timestamp.

exp_
TIMESTAMP_FORMATOptional

Any correct format for the class java.text.SimpleDateFormat.


Default value: yyyyMMdd-HHmmss

This parameter specifies the timestamp format according to the java class  java.text.SimpleDateFormat.

ddMMyyyyHHmmss
FILENAME_SUFIXOptional

Any alphanumeric character except: < > : " / \ | ? *

This parameter specifies the string to be placed after the timestamp.

.txt



 

Example


FILENAME_PREFIX = MeterReadings_

FILENAME_SUFIX = .xml

TIMESTAMP_FORMAT = ddMMyyyyHHmmss

 

Dynamic configuration after execution:


["FileName",http://sap.com/xi/XI/System/File] --> MeterReadings_01082010210013.xml


Audit Log


The execution process can be followed in the audit log generated per message.


 

AddTimeStampBean

 

/**
*
*/
package com.rav.integrations.modules;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import com.sap.aii.af.lib.mp.module.ModuleContext;
import com.sap.aii.af.lib.mp.module.ModuleData;
import com.sap.aii.af.lib.mp.module.ModuleException;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.engine.interfaces.messaging.api.Message;
import com.sap.engine.interfaces.messaging.api.MessageKey;
import com.sap.engine.interfaces.messaging.api.MessagePropertyKey;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
/**
* @author Roger Allué Vall
*
*/
public class AddTimeStampBean implements SessionBean, TimedObject {    /**     *     */    private static final long serialVersionUID = 8087133996851499898L;    private static final String C_FILENAME_PREFIX_TAG         = "FILENAME_PREFIX";    private static final String C_FILENAME_SUFIX_TAG          = "FILENAME_SUFIX";     private static final String C_TIMESTAMP_FORMAT_TAG    = "TIMESTAMP_FORMAT";    private static MessageKey amk;    /* (non-Javadoc)     * @see javax.ejb.SessionBean#ejbActivate()     */    public void ejbActivate() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.SessionBean#ejbPassivate()     */    public void ejbPassivate() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.SessionBean#ejbRemove()     */    public void ejbRemove() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)     */    public void setSessionContext(SessionContext arg0) throws EJBException,            RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.TimedObject#ejbTimeout(javax.ejb.Timer)     */    public void ejbTimeout(Timer arg0) {        // TODO Auto-generated method stub    }    public void ejbCreate() throws javax.ejb.CreateException {         }    private void addInfo (String msg){        if (amk != null){          Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,msg);        }        else{          System.out.println(msg);         }    }    public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData)    throws ModuleException {               String fileNamePrefix   = moduleContext.getContextData(C_FILENAME_PREFIX_TAG);         String fileNameSufix    = moduleContext.getContextData(C_FILENAME_SUFIX_TAG);         String timeStampFormat  = moduleContext.getContextData(C_TIMESTAMP_FORMAT_TAG);               String timeStamp;         String fileName;         Message msg;         MessagePropertyKey key;               try{                        msg = (Message) inputModuleData.getPrincipalData();             amk               = new MessageKey(msg.getMessageId(), msg.getMessageDirection());                       addInfo("--> Start AddTimeStamp Module");                         if ( fileNamePrefix == null ){                 fileNamePrefix = "";            }                     if ( fileNameSufix == null){                 fileNameSufix = "";            }                  if (timeStampFormat == null) {                 timeStampFormat = "yyyyMMdd-HHmmss";             }                       addInfo("--> " + C_FILENAME_PREFIX_TAG    + " = " + fileNamePrefix);             addInfo("--> " + C_FILENAME_SUFIX_TAG     + " = " + fileNameSufix);             addInfo("--> " + C_TIMESTAMP_FORMAT_TAG   + " = " + timeStampFormat);                       try{                 timeStamp = new java.text.SimpleDateFormat(timeStampFormat).format(new java.util.Date ());                           }                       catch( Exception e){                 addInfo("--> TimeStamp could not be generated.");                 timeStamp = "19000101-000000-" + Math.random();             }                       addInfo("--> TimeStamp = " + timeStamp);                                 fileName = fileNamePrefix + timeStamp + fileNameSufix;                       addInfo("--> FileName = " + fileName);                       key = new MessagePropertyKey("FileName","http://sap.com/xi/XI/System/File");            msg.removeMessageProperty(key);            msg.setMessageProperty(key,fileName);                      addInfo("--> Finish AddTimeStamp Module");           }        catch (Exception e) {            addInfo ("Exception: " + e.getMessage());            StackTraceElement[] stack = e.getStackTrace();            for ( int i=0; i<stack.length; i++){                addInfo (stack[i].toString());            }                 throw new ModuleException(e.getMessage(),e);        }                  return inputModuleData;    }
}

Adapter Module: RenameFile

$
0
0

Use


RenameFile module is used to replace strings within the value of Dynamic Configuration key ["FileName",http://sap.com/xi/XI/System/File]. It can be used to modify a part of the file name of the message before it gets in PI and also before it gets out.  The module obtains a pair of string : <OldString>;<NewString> as parameter. Reads the Dynamic Configuration key ["FileName",http://sap.com/xi/XI/System/File] of the message. Then it searches <OldString> within the  filename and replace each occurrence with <NewString>. Finally it updates the key with the new value and the original message is returned.


The module accepts multiple string pairs to allow multiple replacements in one execution.



Deployment

Enterprise Java Bean Project: RenameFile_EJB

Enterprise Java Bean Application: RenameFile_EAR

 

Integration

The module can be used in any Sender or Receiver File/FTP Adapter.

 

Activities

This section describes all the activities that have to be carried out in order to configure the module.

 

Entries in processing sequence

Insert the module in front of the adapter module as shown in the picture below.

 

 

 

Entries in the module configuration


 

 

The table below shows the possible parameters and values of the adapter module.

 

ParameterTypePossible ValuesDescriptionExample
separatorOptional

Any alphanumeric character.

Default value: ‘|’
This parameter configures the character that separates a pair of strings.separator = ‘;’
param(*)Mandatory

Pair of strings separated by

“separator” character.

 

<OldString><separator>[<NewString>,blankString,emptyString].

 

  Default value: none.
This parameter is used to obtain Old string to be replaced by the New string in the message. The pair is separated by “separator”. As Adapter module tab in PI trims strings by the right side, if it’s needed to replace OldString by a blank string or an empty string, the values  blankString or emptyString have to be used.

param1=str1;str2

param2=str1;blankString

  param3=str1;emptyString

 

(*) The parameter name can be any string: param1, parameter, aaa, etc.

 

Example


Adapter Type:

File/Ftp Sender


Dynamic Configuration before execution:

 

Module parameters:

separator = ‘;’

param1 = .GENERATED;emptyString

 

Dynamic Configuration after execution:

 

Audit Log

The execution process can be followed in the audit log generated per message.

 

 

 

RenameFileBean

 

package com.rav.integrations.modules;
import java.rmi.RemoteException;
import java.util.Enumeration;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import com.sap.aii.af.lib.mp.module.ModuleContext;
import com.sap.aii.af.lib.mp.module.ModuleData;
import com.sap.aii.af.lib.mp.module.ModuleException;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.engine.interfaces.messaging.api.Message;
import com.sap.engine.interfaces.messaging.api.MessageKey;
import com.sap.engine.interfaces.messaging.api.MessagePropertyKey;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
/**
* @author Roger Allué Vall
*
*/
public class RenameFileBean implements SessionBean, TimedObject {       private static final long serialVersionUID = 1L;    private static final String C_SEPARATOR_STRING = "separator";    private static final String C_AUX_SEPARATOR = "|";    private static final String C_MODULEKEY_STRING = "module.key";    private static final String C_BLANK_STRING = "blankString";    private static final String C_EMPTY_STRING = "emptyString";    /* (non-Javadoc)     * @see javax.ejb.SessionBean#ejbActivate()     */    public void ejbActivate() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.SessionBean#ejbPassivate()     */    public void ejbPassivate() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.SessionBean#ejbRemove()     */    public void ejbRemove() throws EJBException, RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)     */    public void setSessionContext(SessionContext arg0) throws EJBException,            RemoteException {        // TODO Auto-generated method stub    }    /* (non-Javadoc)     * @see javax.ejb.TimedObject#ejbTimeout(javax.ejb.Timer)     */    public void ejbTimeout(Timer arg0) {        // TODO Auto-generated method stub    }    public void ejbCreate() throws javax.ejb.CreateException {           }       public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData)    throws ModuleException {        Message msg;        Enumeration<String> paramList;        String sep, paramKey,param, strArray[];                       try {             msg = (Message) inputModuleData.getPrincipalData();             MessageKey amk = new MessageKey(msg.getMessageId(), msg.getMessageDirection());             MessagePropertyKey FileKey = new MessagePropertyKey("FileName","http://sap.com/xi/XI/System/File");                         String fileName = msg.getMessageProperty(FileKey);                            sep = moduleContext.getContextData(C_SEPARATOR_STRING);                    if ( sep == null ) {                sep = C_AUX_SEPARATOR;                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Default separator used: " + sep);             }             else {                Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Separator found: " + sep);             }                                     paramList = moduleContext.getContextDataKeys();               while( paramList.hasMoreElements()) {                    paramKey = paramList.nextElement();                 param =  (String) moduleContext.getContextData(paramKey);                                 if ( ! paramKey.equals(C_SEPARATOR_STRING) && ! paramKey.equals(C_MODULEKEY_STRING) ){                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"ParamKey: " + paramKey);                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitució Param: " + param);                    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitució sep: " + sep);                                       strArray = param.split(sep);                                       if (strArray != null){                          if ((! strArray[0].equals(null)) && (! strArray[1].equals(null))){                        if ( strArray[1].equals(C_BLANK_STRING)){                            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Blank String");                            strArray[1]=" ";                                                   }                        else if (strArray[1].equals(C_EMPTY_STRING)){                            strArray[1]="";                            Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Empty String");                        }                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution array strArray[0]: " + strArray[0]);                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution array strArray[1]: " + strArray[1]);                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution array fileNameA : " + fileName);                                   fileName = fileName.replaceAll(strArray[0],strArray[1]);                        Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Substitution fileNameB : " + fileName);                        }                    }                 }             }                    msg.removeMessageProperty(FileKey);             msg.setMessageProperty(FileKey,fileName);               }        catch(Exception e) {            ModuleException me = new ModuleException(e);            throw me;        }             return inputModuleData;    }
}
Viewing all 676 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>