Table of Contents
Learning Objective:-
This unit describes:-
- How to pass raw data to a custom class (message creation) for processing?
1. How to pass raw data to a custom class (Message Creation) for processing? #
Our Skyvva Tool supports XML, CSV, and JSON file formats by default. However, if you have complex XML, JSON, or other raw data structures that our tool cannot read in your payload, you will need to use a custom class to build your logic and read your raw data structure to create the SKYVVA Message yourself.
Here is a sample payload in a data format that our standard cannot read: #
--- status: success code: '200' message: completed data: - Id: ba228042-793a-4289-b0cb-57a661c11ff5 Name: Jamie Conn Fax: "(646) 029 4240" BillingCity: Saint Helier BillingCountry: Jersey Type: Direct Solutions Supervisor Website: https://frieda.com Description: Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/3.0) Contact: - Id: f062cfad-a38c-4a4c-b8b0-788a8ae5910e FirstName: Jamie LastName: Conn Email: Jamie97@yahoo.com Title: Regional Security Technician Description: Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/3.0; .NET CLR 4.6.90034.5) Asset: - Id: 250c739a-4ab8-4ba8-997b-a184bec568d7 Name: Intelligent Frozen Sausages Quantity: 954 City: Nā‘ūr Country: Jordan Description: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.9) Gecko/20100101 Firefox/8.9.0 Case: - Id: 91282b68-0894-4439-bb56-c27df3cf8cf1 Status: ATS Subject: BMW Description: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 5.3; Trident/7.1) - Id: e03fxb30-c925-4c63-9e6c-e2b974c3fe39 Name: Ouu MeyNeang Fax: "(431) 476 31545" BillingCity: Mao Sen Tong BillingCountry: China Type: Lead SKYVVA Consultant Website: https://apsara-consulting.com Description: testing record - Id: e03fcc30-c925-4c63-9e3c-e2b974c3fe38 Name: Cesar Murazik Fax: "(431) 476 3151" BillingCity: Mao BillingCountry: Chad Type: Lead Tactics Consultant Website: https://alene.org Description: Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko Contact: - Id: 30e65a2e-2a0e-4a53-893e-01d30b725204 FirstName: Cesar LastName: Murazik Email: Cesar41@hotmail.com Title: National Marketing Orchestrator Description: Mozilla/5.0 (Windows; U; Windows NT 6.3) AppleWebKit/535.1.2 (KHTML, like Gecko) Chrome/14.0.886.0 Safari/535.1.2 Asset: - Id: 5a948bfb-7441-4d63-9d47-a38ab611d2fa Name: Incredible Plastic Pizza Quantity: 4534 City: La Estrella Country: Panama Description: Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.1) Case: - Id: 93e3b363-0e08-425d-b659-7122ef3c9e34 Status: Wrangler Subject: Jaguar Description: Mozilla/5.0 (Windows NT 6.2; Trident/7.0; rv:11.0) like Gecko
2. The procedure to pass raw data to a custom class (Message Creation) for processing with custom code:- #
The procedure is given below with an example:-
2.1. Create MetaData, Repository and Message Type:- #
2.2. Create Integration:- #
2.3. Create custom class : #
- The custom code is given below to pass raw data (create the message):-
public with sharing class RawDataCustomProcessing extends AbstractIntegrationV3 { List<String> lines{get;set;} Map<String,IMessage__c> mapParentIntfMsg = new Map<String,IMessage__c>(); public override IServicesUtil.IMessageResult createMessage(AbstractIntegrationV3.DtoRequestBody dtoRequestBody, AbstractIntegrationV3.DtoStructure dtoStr){ AbstractIntegrationV3.DtoInterface dtoIntfStructure = getInterfaceStructure(); // custom transaction if(String.isBlank(dtoRequestBody.transactionId))dtoRequestBody.transactionId='YAML-Data-'+System.now().getTime(); // parse yaml payload to map// here using your own logic Map<String,Object> dataAsMap = doParse(dtoRequestBody.payload); System.debug('>>dataAsMap: '+dataAsMap); // i know exactly my data contain data node as array //{"NodeX":[{},{}]} List<Object> rootData = (List<Object>)dataAsMap.get(dtoIntfStructure.sourceObject); for (Object nodeRoot : rootData) { // create mesage from root createMsg((Map<String,Object>)nodeRoot,dtoIntfStructure,true,1,dtoRequestBody.transactionId,null); } return super.msgResult; } // overide create message logic public override IMessage__c invokeNewMessage( String rootId, String parentId, String transId, Boolean hasChild, Integer lv, String hPath, Boolean isRoot, Interfaces__c mInft, Map<String,Object> idata ){ // just using skyvva default message setting IMessage__c msg=super.invokeNewMessage(rootId,parentId,transId,hasChild,lv,hPath,isRoot,mInft,idata); msg.Name='IM#YAML-Data-'+System.now().getTime()+'---'+indexMsg; return msg; } // hierarchy message creation void createMsg(Map<String,Object> objectX,AbstractIntegrationV3.DtoInterface dtoIntfStructure,Boolean isRoot,Integer level,String transactionId,IMessage__c rootMsg){ Map<String,String> idata = new Map<String,String>(); for (String field : objectX.keySet()) { Object valueX=objectX.get(field); // ignore array or object, ingore childen datas if(valueX instanceof List<Object> || valueX instanceof Map<String,Object>)continue; idata.put(field,valueX+''); //string,string } // System.debug('>>createMsg>idata: '+JSON.serializePretty(idata)); // get parent message if current creation is child IMessage__c parentMsg=mapParentIntfMsg.get(dtoIntfStructure.parentIntfId); // current message, invoke create message setting IMessage__c msg = invokeNewMessage(rootMsg?.External_Id2__c,parentMsg?.External_Id2__c,transactionId,false,level,null,isRoot,super.mIntf.get(dtoIntfStructure.intfId),idata); // save parent interface to message mapParentIntfMsg.put(dtoIntfStructure.intfId,msg); // if current is root levelt then set it to children if(isRoot)rootMsg=msg; else { // mark parent and grand parent as has child rootMsg.HasChild__c=true; parentMsg.HasChild__c=true; } // create children message for(AbstractIntegrationV3.DtoInterface tmp : dtoIntfStructure.child){ // System.debug('>>createMsg>tmp.sourceObject: '+tmp.sourceObject); Object obj = objectX.get(tmp.sourceObject); if(obj==null){ // ingore case for (String field : objectX.keySet()) { // find child node if(tmp.sourceObject.equalsIgnoreCase(field)){ obj = objectX.get(field); } } } // System.debug('>>createMsg>obj: '+obj); // child message if(obj instanceof Map<String,Object>){ createMsg((Map<String,Object>)obj,tmp,false,level+1,transactionId,rootMsg); } // child message array else if(obj instanceof List<Object>){ List<Object> lstObj = (List<Object>) obj; for(Object obj1 : lstObj){ createMsg((Map<String,Object>)obj1,tmp,false,level+1,transactionId,rootMsg); } } } } // logic parsing raw data --------------satrt Map<String,Object> doParse(String yamlString){ Map<String,Object> yamlMap = new Map<String,Object>(); lines=yamlString.split('\n'); while (!lines.isEmpty()){ readByLine(lines.remove(0),yamlMap); } return yamlMap; } void readByLine(String line,Map<String,Object> result){ if (String.isBlank(line.trim()))return; if(!line.contains(':'))return; String[] parts = line.split(':',2); String name = parts[0].trim(); name=name.removeStart('- '); String value = parts[1].trim(); if (String.isNotBlank(value)) { result.put(name.removeStart('- '), value); } else if(!lines.isEmpty() && isElement(lines.get(0))) { Integer indexOfNextLevel=getIndexOfElement(lines.get(0)); List<Map<String,Object>> children=new List<Map<String,Object>>(); Map<String,Object> child; // read children Integer nextLvl=indexOfNextLevel; while(!lines.isEmpty() && getIndexOfElement(lines.get(0))==nextLvl){ if(isElement(lines.get(0))){ child=new Map<String,Object>(); children.add(child); } readByLine(lines.remove(0),child); } result.put(name,children); } } Boolean isElement(String nextLine){ return String.isNotBlank(nextLine) && nextLine.trim().startsWith('-'); } Integer getIndexOfElement(String nextLine){ Integer level = 0; while (nextLine.substring(level,level+1) == ' ' || nextLine.substring(level,level+1)=='-') { level += 1; } return level; } // logic parsing raw data --------------end---------------- }
- Copy and paste this code into the custom class. This example code will enable the reading of the data structure.
2.4. Create Interface: #
- In the Runtime Configuration Section of the Interface page we need to select two things which are shown in the picture given below:-
- To enable custom processing, check the ‘Custom Processing’ option. Once you have checked this option, you will be able to use a custom class for this interface. A custom Apex class is required to handle the specific processing for this interface.
- You also need to enter the custom processing class that you have created with the logic mentioned above.
- In the Custom Processing section, you need to select the block that you want to custom
- Select ‘Message Creation’ on “Custom Block to replace the SKYVVA Block”. This is the block that you need to customize.
2.5. Do Mapping: #
2.6. Call via V4/integrate #
- After calling V4/integrate, it will read raw data and create the message.