cancel
Showing results for 
Search instead for 
Did you mean: 

How to use Custom Java Objects in Message Property?

0 Kudos
656

Hi,

I have custom jar that is added to iflow as a resource. In the iflow, in one of the script component we are creating instance of custom java class and then setting custom java object to the message property. Further in iflow I am trying to retrieve the message property to make use of the custom java object that was stored previously. Syntax wise everything looks good, no errors but at runtime it is failing due to below error,

Why is it trying to cast an object of the same type to it's type, and then failing to do so?

It seem below error is related to classloader, can you please help how we can resolve this error.

Your solution will help to make use of custom java objects in CPI to set/get from message property especially when you want to hold complex data structure where using of standard collection objects like Map and List is not sufficient.

Message processing failed.

Processing Time: 77 ms Error Details javax.script.ScriptException: java.lang.Exception: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.custom.test.EmployeeDetails1095C@5f4488f1' with class 'com.custom.test.EmployeeDetails1095C' to class 'com.custom.test.EmployeeDetails1095C'@ line 16 in TestReadCustomJavaObjects.groovy, cause: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.custom.test.EmployeeDetails1095C@5f4488f1' with class 'com.custom.test.EmployeeDetails1095C' to class 'com.custom.test.EmployeeDetails1095C'

Thanks

-Anand R Hungund

Accepted Solutions (0)

Answers (2)

Answers (2)

MortenWittrock
Active Contributor

Hi Anand

You can definitely store an object of a custom class in a property and then retrieve it in a later step. I can't really comment on the specific error without seeing the code, but for starters you can try running it without the cast. It's not required in Groovy, so you can just go:

def myCustomObject = message.getProperty("NameOfYourProperty")
myCustomObject.myCustomMethod() // <- Works without the cast

Regards,

Morten

0 Kudos

Thanks Morten for the reply. Below is the code and infact I am not casting it in my code as I have used generics. It is groovy that is attempting to do casting by its own when I have variable type defined same as the object type returned by map.

Error is from below bold line of Script No.3

import com.sap.sdc.mck.cobra.EmployeeDetails1095C

.

.

.

EmployeeDetails1095C empDetails = null
StringBuffer strBuffr = new StringBuffer()

codeMatrixAsMap.each{
empDetails = it.value

.

.

.

Below are the scripts I have used in the iflow and I am getting error from 3rd script at runtime.

TestInitializeHashMaps.groovy
-------------------------------------------
import com.sap.gateway.ip.core.customdev.util.Message
import com.sap.sdc.mck.cobra.EmployeeDetails1095C

def Message processData(Message message) {

def messageLog = messageLogFactory.getMessageLog(message)
def body = message.getBody(java.lang.String)
propertyMap = message.getProperties();

HashMap<String,EmployeeDetails1095C> codeMatrixAsMap = new HashMap<String,EmployeeDetails1095C>();
message.setProperty("CODE_MATRIX", codeMatrixAsMap);

return message
}

TestStoreCustomJavaObjects.groovy
----------------------------------------------------------
import com.sap.gateway.ip.core.customdev.util.Message
import com.sap.sdc.mck.cobra.EmployeeDetails1095C

def Message processData(Message message) {

def messageLog = messageLogFactory.getMessageLog(message)
def body = message.getBody(java.lang.String)
propertyMap = message.getProperties();

HashMap<String,EmployeeDetails1095C> codeMatrixAsMap = propertyMap.get("CODE_MATRIX")

int empId = 0
EmployeeDetails1095C empDetails = null

int dummyEmpId = 2387
for(int i=0; i<6 ; i++){

empId = dummyEmpId + i

empDetails = new EmployeeDetails1095C(""+empId, ""+empId)
codeMatrixAsMap.put(""+empId, empDetails)
}

return message
}

TestReadCustomJavaObjects.groovy
---------------------------------------------------------
import com.sap.gateway.ip.core.customdev.util.Message
import com.sap.sdc.mck.cobra.EmployeeDetails1095C

def Message processData(Message message) {

def messageLog = messageLogFactory.getMessageLog(message)
def body = message.getBody(java.lang.String)
propertyMap = message.getProperties();

HashMap<String,EmployeeDetails1095C> codeMatrixAsMap = propertyMap.get("CODE_MATRIX")

EmployeeDetails1095C empDetails = null
StringBuffer strBuffr = new StringBuffer()

codeMatrixAsMap.each{
empDetails = it.value
strBuffr.append(it.key + "-->")
strBuffr.append(empDetails.getPersonIdExternal() + "-")
strBuffr.append(empDetails.getWorkerId() + "-")
strBuffr.append(empDetails.getMonthlyCodeMatrix().toString() + "-")

empDetails.getMonthlyCodeMatrix().each{
strBuffr.append(empDetails.getMonthFullName() + "*")
}

strBuffr.append("\n")
}

messageLog.addAttachmentAsString("Read Custom Java Object", strBuffr.toString(), "text/xml");

return message

}

Below is the Error,

javax.script.ScriptException: java.lang.Exception: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.sap.sdc.mck.cobra.EmployeeDetails1095C@422d62b9' with class 'com.sap.sdc.mck.cobra.EmployeeDetails1095C' to class 'com.sap.sdc.mck.cobra.EmployeeDetails1095C'@ line 16 in TestReadCustomJavaObjects.groovy, cause: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.sap.sdc.mck.cobra.EmployeeDetails1095C@422d62b9' with class 'com.sap.sdc.mck.cobra.EmployeeDetails1095C' to class 'com.sap.sdc.mck.cobra.EmployeeDetails1095C'

Below is how the property looks like from trace,

CODE_MATRIX{2389=com.sap.sdc.mck.cobra.EmployeeDetails1095C@422d62b9, 2388=com.sap.sdc.mck.cobra.EmployeeDetails1095C@61c2e11e, 2387=com.sap.sdc.mck.cobra.EmployeeDetails1095C@725882f8, 2392=com.sap.sdc.mck.cobra.EmployeeDetails1095C@4fd18742, 2391=com.sap.sdc.mck.cobra.EmployeeDetails1095C@66401cab, 2390=com.sap.sdc.mck.cobra.EmployeeDetails1095C@10fcdb6c}
MortenWittrock
Active Contributor
0 Kudos

Hi anand.hungund

There is still a cast, because message.getProperties returns a Map<String,Object> map, which you then cast to your specific map type.

In your TestReadCustomJavaObjects.groovy script, try changing:

HashMap<String,EmployeeDetails1095C> codeMatrixAsMap = propertyMap.get("CODE_MATRIX")
EmployeeDetails1095C empDetails = null

to:

def codeMatrixAsMap = propertyMap.get("CODE_MATRIX")
def empDetails = null

The casting-related error is weird, but this way you should avoid the cast. Try it out and let me know.

Regards,

Morten

0 Kudos

Hi Morten,

I tried changing code as per your suggestion but this time different error and also I tried

empDetails = (EmployeeDetails1095C)it.value

even above also didn't work, infact above will take to the old error.

Error:

Message processing failed.Processing Time: 110 msError Detailsorg.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-vsa10726915-1667648704642-467-1], cause: java.lang.AbstractMethodError: Receiver class com.sap.sdc.mck.cobra.EmployeeDetails1095C does not define or inherit an implementation of the resolved method abstract invokeMethod(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; of interface groovy.lang.GroovyObject.
import com.sap.gateway.ip.core.customdev.util.Message
import com.sap.sdc.mck.cobra.EmployeeDetails1095C

def Message processData(Message message) {

    def messageLog = messageLogFactory.getMessageLog(message)
    def body = message.getBody(java.lang.String)
    propertyMap = message.getProperties();

    def codeMatrixAsMap = propertyMap.get("CODE_MATRIX")

    def empDetails = null
    StringBuffer strBuffr = new StringBuffer()

    codeMatrixAsMap.each{
        empDetails = it.value
        strBuffr.append(it.key + "-->")
        strBuffr.append(empDetails.getPersonIdExternal() + "-")
        strBuffr.append(empDetails.getWorkerId() + "-")
        strBuffr.append(empDetails.getMonthlyCodeMatrix().toString() + "-")
        
        empDetails.getMonthlyCodeMatrix().each{
            strBuffr.append(empDetails.getMonthFullName() + "*")
        }
        
        strBuffr.append("\n")
    }
    
    messageLog.addAttachmentAsString("Read Custom Java Object", strBuffr.toString(), "text/xml");
    
	return message
}
VijayKonam
Active Contributor
0 Kudos

Would there be any dependency on your custom jar, if it was built in Java and is being used in Groovy runtime? Should you try java script rather than groovy? Just a thought.

VijayKonam
Active Contributor
0 Kudos

Did you try the property type to be a Java Object and explicitly convert it with in the script? I am assuming, you must have defined the peroperty type as your custom class. We did use the Property to store java Maps and Lists but never a custom object. I do not know for sure if there is any limitation on the CPI Properties to be able to store other java objects.

0 Kudos

Thanks Vijay for the reply, yes I have used generics in my code.

I have taken care of variable type and returned object type are same. I have added code above to Morten comment, please check. Use of Maps and List work fine for simple data but we are trying to use complex data structure so decide to use custom Java Object instead of using multiple nested maps in the property.