cancel
Showing results for 
Search instead for 
Did you mean: 

CPI Groovy Script Failure

07-25-2023 12:36 AM
rohit131086 Explorer
4462 views 5 comments
0 Likes
SAP Managed Tags
Subscribe

Hello Experts,


Facing a unique error in one of the CPI artifacts we have been working on. Please find the error description below:

com.sap.it.rt.adapter.http.api.exception.HttpResponseException: An internal server error occured: No signature of method: AvgCostKafka__Script$_processData_closure7$_closure12.doCall() is applicable for argument types: (groovy.json.internal.LazyMap) values: [[MaterialGroup: , CompanyCode: , CurrencyRole: , PriceDeterminationControl: , ...]]

Hiding the actual values for the fields Material Group, Company Code, Currency Role and Price Determination Control.

Somehow whenever I am getting this specific combination of values the Groovy script is failing.

Possible solutions: doCall(java.lang.Object, java.lang.Object), findAll(), findAll(), isCase(java.lang.Object), isCase(java.lang.Object).

Let me know if you need any more information. Thanks.

Let me also share the Avg Cost Kafka Script here for your reference.

Thanks,

Rohit Sinha

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.*;
import groovy.xml.*;
import groovy.util.*

def Message processData(Message message) {
    //Body 
    def body = message.getBody(String.class);
    
    if (body.charAt(0) != '[') {
        body = "[" + body + "]";
    }

   def mapArray = new JsonSlurper().parseText(body);

//Key and value schemas
    def keySchema = [   type: "string"]; 
    
    def keySchemaValue = JsonOutput.toJson(keySchema);
    def keySchemaJson = JsonOutput.toJson([key_schema: keySchemaValue]);
    
    keySchemaJson = keySchemaJson.substring(0,keySchemaJson.length()-1) + ",";
		            
	def header = 	[
		             [name: "PartNumber", type: "string"],
                     [name: "MaterialDescription", type: ["string", "null"]],
                    ];

    def items =     [ name: "WarehouseAverageCosts",
         type: [
             type: "array",
             items: [
                 name: "WarehouseAverageCost",
                 type: "record",
                 fields: [
                                [name: "MaterialGroup", type: ["string", "null"]],
                                [name: "CompanyCode", type: ["string", "null"]],
                                [name: "CurrencyRole", type: ["string", "null"]],
                                [name: "PriceDeterminationControl", type: ["string", "null"]],
                                [name: "Plant", type: "string"],
                                [name: "MaterialPriceUnitQty", type: "int"],
                                [name: "MovingAveragePrice", type: "double"],
                                [name: "BaseUnit", type: "string"],
                                [name: "Currency", type: "string"],
                                [name: "TotalValuatedStockQty", type: "double"],
                                [name: "WarehouseCode", type: "string"]
                            ]
             ]
        ]   
    ] 

    def fields = header;
    fields.add(items);

    def valueSchema = [ type: "record", name: "AverageCostDetails", fields: fields ];
    def valueSchemaValuePart = JsonOutput.toJson(valueSchema);
    def valueSchemaJson = JsonOutput.toJson([value_schema: valueSchemaValuePart])
    valueSchemaJson = valueSchemaJson.substring(1, valueSchemaJson.length()-1) + "," ; 
    def avroMap = [:];
    def itemList = mapArray.WarehouseAverageCosts;

    def fieldTypes = header.collectEntries { [it.name, it.type] } ;

    def mapsize = 0;
    itemList.each { item-> 
      item.each { 
         mapsize++;
      }
    }
  
    items.type.items.fields.collectEntries { [it.name, it.type] }.each { key, value ->
    fieldTypes.put(key, value);   
    }
    // println bodyMap;
    // println body;
        mapArray.each {record ->
          record.each { key, val ->
        if(key != "WarehouseAverageCosts") {
            if(fieldTypes[key] instanceof List){
                avroMap.put(key, [(fieldTypes[key].get(0)) :  val]);
            } else avroMap.put(key, val) 
        }
          }
    };

      def tempMap = [:];
      def tempList = [];
      
       if ( mapsize != 11 )   {            
        itemList.each {item-> 
           item.each { record->
            record.each { key, val ->
           if(fieldTypes[key] instanceof List){
                if (val != "" && val != "000") {
                    println val
                    tempMap.put(key, [(fieldTypes[key].get(0)) : (convertValue(fieldTypes[key].get(1), val))]);
                } else {
                    tempMap.put(key, null);
                }
            } else tempMap.put(key, toDouble(fieldTypes[key],val)) 
        
           }
        tempList.add(tempMap.clone());
           }
    } } 
    else {
          itemList.each { record->
            record.each { key, val ->
           if(fieldTypes[key] instanceof List){
                if (val != "" && val != "000") {
                    println val
                    tempMap.put(key, [(fieldTypes[key].get(0)) : (convertValue(fieldTypes[key].get(1), val))]);
                } else {
                    tempMap.put(key, null);
                }
            } else tempMap.put(key, toDouble(fieldTypes[key],val)) 
        
           }
        tempList.add(tempMap.clone());
           }
    } ;
     
    avroMap.put("WarehouseAverageCosts", tempList)

    def keyval = mapArray.PartNumber.join(', ');
    def records = [[key: keyval, value: avroMap ]];
    def kafkaPayload = [records: records];
    def output = JsonOutput.toJson(kafkaPayload);
  
    def messageOutput = JsonOutput.toJson(kafkaPayload);
    messageOutput = messageOutput.substring(1,messageOutput.length()-1);

    def finaloutput = keySchemaJson + valueSchemaJson + messageOutput + "}"; 
    
    message.setBody(finaloutput);

	return message;

}
def convertValue (type, value) {
    switch(type) {
        case "int":
            if (value instanceof Integer) {
                return value  
            } else 
                return convertToInt(value)
        case "string":
            if (value instanceof String) {
                return value 
            } else 
                return value.toString()
        case "boolean":
            return convertToBoolean(value)
        case "double":
            if (value instanceof String){
                return  convertToDouble(value) 
            } else
                return value
        default:
            return value
    }
}

def convertToInt(String input) {
    int output = (int) input.toDouble() ;//input.toInteger();
    return output;
}

def convertToDouble(String input) {
    Double output = input.toDouble();
    return output;
}

def convertToBoolean(String input) {
    Boolean output = input.toBoolean();
    return output;
}

def convertToNull(String input) {
    if(input != ""){
        return input
    } else
        return null;
}

def toDouble( type, val) {
    if (type=="double") {
        return Double.parseDouble(val); 
    } else if( type=="int") {
        return convertToInt(val)
    } else
        return val
}
0 Likes

Accepted Solutions (0)

Answers (5)

Answers (5)

rohit131086
Explorer
0 Likes

value-combination.jpg

This specific combination of values keep failing.

Not able to put a finger on what's going wrong.

More importantly does this look like a configuration issue or a groovy script error or a data error to you.

Lazy map denotes data issue but can you share more light on that.

Thanks,

Rohit Sinha

rohit131086
Explorer
0 Likes

average-cost-artifact.jpg

average-cost-error.jpg

Let me know Jwan Let me know if you need any more information.

Thanks,

Rohit Sinha

rohit131086
Explorer
0 Likes

Also attaching the groovy script for group delete groovy script.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.Object.*;
def Message processData(Message message) {
    
    def body = message.getBody(java.lang.String);
    body = body.substring(body.indexOf('\n')+9);
  
    def json_to_str=body.substring(1,body.length()- 1);  
    message.setBody(json_to_str);
    
    return message;
}
rohit131086
Explorer
0 Likes

Hello Jwan,

Will share the artifact flow and the error log information in subsequent note.

Putting the XSLT code for Group by Part Number

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" indent="yes"/>
	<xsl:key name="PartNo" match="root" use="PartNumber"/>
	<xsl:template match="/record">
		<record>
			<xsl:for-each select="//root[generate-id() = generate-id(key('PartNo', PartNumber)[1])]">
				<group>
					<xsl:copy-of select="PartNumber"/>
					<xsl:copy-of select="MaterialDescription"/>
					<xsl:for-each select="key('PartNo', PartNumber)">
						<WarehouseAverageCosts>
							<xsl:copy-of select="MaterialGroup"/>
							<xsl:copy-of select="CompanyCode"/>
							<xsl:copy-of select="CurrencyRole"/>
							<xsl:copy-of select="PriceDeterminationControl"/>
							<xsl:copy-of select="Plant"/>
							<xsl:copy-of select="MaterialPriceUnitQty"/>
							<xsl:copy-of select="MovingAveragePrice"/>
							<xsl:copy-of select="BaseUnit"/>
							<xsl:copy-of select="Currency"/>
							<xsl:copy-of select="TotalValuatedStockQty"/>
							<xsl:copy-of select="WarehouseCode"/>
						</WarehouseAverageCosts>
					</xsl:for-each>
				</group>
			</xsl:for-each>
		</record>
	</xsl:template>
</xsl:stylesheet>
Pls find the code for Set header part number.
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.*;
import groovy.xml.*;
import groovy.util.*

def Message processData(Message message) {

    def body = message.getBody(String.class);
     
	def root = new XmlSlurper().parseText(body);
    def PartNumber = root.group.PartNumber.text();
	
	message.setHeaders([:]);
    message.setHeader("PartNumber", PartNumber);
    
    return message;
}
Jwan_24
Participant
0 Likes

Based on the error message and the script provided, it's not immediately clear where the problem lies without additional context and information about how this script is being used and integrated with other components.

It's also essential to examine the input data that is being processed by the script. The error message mentions groovy.json.internal.LazyMap, which suggests that there might be an issue with the data format or how the data is being passed to the script.

If you can provide more context, such as the specific code segment where the error occurs or any other relevant information about the input data and how the script is being called, it would be easier to pinpoint the exact cause of the error and provide a more accurate solution.