Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Java Object in ColdFusion

This is a continuation of this question: WCF and ColdFusion

So I managed to get a JAR working using Metro and importing the WSDL. My main class has the following functions: getVersion() and my implementation myVersion(), cancelOrder() and myCancel() and, finally, placeOrder and myOrder().

the various methods

I'm able to pass the correct information and get a response back from the webservices for the first 2 methods (getVersion and cancelOrder):

For example, in the myVersion method, it calls the webservice and outputs the version number plus the passed string:

<cfset var.myVersion = createObject("java", "com.USOrlando").myVersion(
    javaCast("string", "Batman")
)>
<!---Output is [version number] + "I'm Batman" --->

Using the same template, I can also pass all of the other parameters in the myOrder method except the last parameter of type org.tempuri.ArrayOfSmartOrderLineRequest.

This is where I'm not confident and may need guidance:

In going through documentation and the generated classes, I'll put what is in documentation in block quotes and how I understand them underneath.

myOrder is supposed to take all of the parameters passed in through ColdFusion and put it into a request object.

<cfset var.01_00_myOrder = createObject("java", "com.USOrlando").myOrder(
    JavaCast("String", ExternalOrderId),
    JavaCast("int", CustomerID),
    .
    .
    .
    JavaCast("String", Phone),
    JavaCast("String", Email),
    JavaCast("org.tempuri.ArrayOfSmartOrderLineRequest", orderItems)
)>

That last line, JavaCast("org.tempuri.ArrayOfSmartOrderLineRequest", orderItems) is my issue. I get a

JavaCast type org.tempuri.ArrayOfSmartOrderLineRequest must be one of the following types: byte, char, short, int, long, float, double, boolean, string, bigdecimal, their corresponding array representation (eg : int[]), or null.

error, which makes sense. If I make it into null, nothing gets passed into the SoapMessage.

My question is this: How do I pass that final parameter?

orderItems is a CF variable, which is, I believe, referenced to a Java Object.

<!---Create Items --->
<cfset myItem = createObject("java", "org.tempuri.SmartOrderLineRequest")>
    <cfset myItem.PluSalesProgramId = myItem.setPLU(1)>
    <cfset myItem.PLU = myItem.setPLU("123456")>
    <cfset myItem.Quantity = myItem.setPLU(1)>
<!---Add Item --->
<cfset orderItems = createObject("java", "org.tempuri.ArrayOfSmartOrderLineRequest").getSmartOrderLineRequest().add(myItem)>

Working backwards, ArrayOfSmartOrderLineRequest.java has a single method getSmartOrderLineRequest. According to the notes in the generated java file:

This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make to the returned list will be present inside the JAXB object. This is why there is not a set method for the smartOrderLineRequest property. It continues on to: For example, to add a new item, do as follows: getSmartOrderLineRequest().add(newItem);

I take this to mean that I have to create a newItem object and pass that into the add method of getSmartOrderLineRequest, correct? So, in building the newItem object, I created the myItem variable, which has three properties: PLU, PluSalesProgramId and Quantity.

In my head, I am creating a myItem object in CF, which is being held in Java, then telling the Java method getSmartOrderLineRequest "Hey, ADD myItem to your array."

Any help would be greatly appreciated. I feel like I'm almost there, but I don't know in which direction I should head.

Edit 1: Response to Leigh's comments.

Not a silly question as to what happens when I just passed the object by itself. I recreated the following steps and I'm getting a weird error: At first, I tried the following:

<!---Create Items --->
<cfset myItem = createObject("java", "org.tempuri.SmartOrderLineRequest")>
    <cfset myItem.PluSalesProgramId = myItem.PluSalesProgramId(JavaCast("int", "1"))>
    <cfset myItem.PLU = myItem.setPLU(JavaCast("string", "123456"))>
    <cfset myItem.Quantity = myItem.setPLU(JavaCast("int", "1"))>
<!---Add Item --->
<cfset orderItems = createObject("java", "org.tempuri.ArrayOfSmartOrderLineRequest").getSmartOrderLineRequest().add(myItem)>
<!---Errors out on myItem.Quantity --->

I tried with the following code, and it didn't error:

<!---Create Items --->
<cfset myItem = createObject("java", "org.tempuri.SmartOrderLineRequest")>
    <cfset myItem.PLU = myItem.setPLU(JavaCast("string", "123456"))>
<!---Add Item --->
<cfset orderItems = createObject("java", "org.tempuri.ArrayOfSmartOrderLineRequest").getSmartOrderLineRequest().add(myItem)>
<!---Errors out on myItem.Quantity --->

I passed it along using:

<cfset var.01_00_myOrder = createObject("java", "com.USOrlando").myOrder(
    JavaCast("String", ExternalOrderId),
    JavaCast("int", CustomerID),
    .
    .
    .
    JavaCast("String", Phone),
    JavaCast("String", Email),
    orderItems
)>
<!---Returned Method Not Found error --->

Below is the shell of the ArrayOfSmartOrderLineRequest.java:

public class ArrayOfSmartOrderLineRequest {
    @XmlElement(name = "SmartOrderLineRequest", nillable = true)
    protected List<SmartOrderLineRequest> smartOrderLineRequest;

    public List<SmartOrderLineRequest> getSmartOrderLineRequest() {
        if (smartOrderLineRequest == null) {
            smartOrderLineRequest = new ArrayList<SmartOrderLineRequest>();
        }
        return this.smartOrderLineRequest;
    }
}

Below is the definition of the object from the WSDL:

<xs:complexType name="ArrayOfSmartOrderLineRequest">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" name="SmartOrderLineRequest" nillable="true" type="tns:SmartOrderLineRequest"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="SmartOrderLineRequest">
    <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" name="PluSalesProgramId" nillable="true" type="xs:int"/>
        <xs:element minOccurs="0" maxOccurs="1" name="PLU" type="xs:string"/>
        <xs:element minOccurs="1" maxOccurs="1" name="Quantity" type="xs:int"/>
    </xs:sequence>
</xs:complexType>

Edit 2: Taking Leigh's advice

Using the Psuedo-Code as a template, I took it one step at a time.

1) Create the items that will need to be passed.

<cfset myItem = createObject("java", "org.tempuri.SmartOrderLineRequest")>

A cfdump of myItem reveals the following methods:

cfdump of myItem

According to the documentation, the order of the parameters are PluSalesProgramId, PLU, Quantity.

2) Add the information to the items.

<cfset myItem.setPluSalesProgramId(JavaCast("int", "1"))>
<cfset myItem.setPLU(JavaCast("string", "123456"))>
<cfset myItem.setQuantity(JavaCast("int", "1"))>

Skipped this step. * 3) Add items to a CF array.

<cfset itemArray = newArray(1)>
<cfset arrayAppend(itemArray, myItem)>

The dump of itemArray is as follows: itemArray dump

So far so good.

4) Next, add reference to myItem to ArrayOfSmartOrderLineRequest.

<cfset orderItems = createObject("java", "org.tempuri.ArrayOfSmartOrderLineRequest")>
<cfset orderItems.getSmartOrderLineRequest().add(myItem)>

5) Finally, orderItems to the myOrder method:

<cfset var.01_00_myOrder = createObject("java", "com.USOrlando").myOrder(
    JavaCast("String", ExternalOrderId),
    JavaCast("int", CustomerID),
    .
    .
    .
    JavaCast("String", Phone),
    JavaCast("String", Email),
    orderItems
)>

Yay! That worked! I'll have to go through the code to make sure everything was done properly, but looking through the logs, it looks like the SOAP message was sent out properly and and expected error of PLU not found was returned.

Leigh, if you put a something in as an answer, I'll accept it as the answer when I get back into the office.

like image 763
Chester Avatar asked Oct 31 '22 14:10

Chester


1 Answers

(Summary from comments)

Despite the name ArrayOf, I suspect the ArrayOfSmartOrderLineRequest class is more like a wrapper of an array (or java.util.List), similar to ArrayOfString. Can you post a) the basic shell of that class (variables, etcetera) and b) if possible, the definition of that object from the WSDL?

Update 1:

So the item class, ie SmartOrderLineRequest, has three (3) main values: PluSalesProgramId, PLU and Quantity? You should be able to

  1. Create a regular CF array and append instances of SmartOrderLineRequest to it
  2. Pass the CF array into the wrapper class ie ArrayOfSmartOrderLineRequest, replacing the underlying List
  3. Finally, pass the wrapper object ie ArrayOfSmartOrderLineRequest (NOT the underlying list) into the appropriate method.

Totally untested obviously, but something like this:

<!--- UNTESTED PSUEDO-CODE.... --->
<!--- create one or more items .... --->
<cfset myItem = createObject("java", "org.tempuri.SmartOrderLineRequest")>
<cfset myItem.setPLU( JavaCast("string", "123456") )>
<cfset myItem.setPluSalesProgramId( JavaCast("int", 111) )>
<cfset myItem.setQuantity( JavaCast("int", 25) )>

<!--- append items to array --->
<cfset itemArray = []>
<cfset arrayAppend(itemArray, myItem)>


<!--- pass array into wrapper object --->
<cfset wrapper = createObject("java", "org.tempuri.ArrayOfSmartOrderLineRequest")>
<!--- either using syntax 1 --->
<cfset wrapper.setSmartOrderLineRequest( itemArray )>
<!--- ... or possibly syntax 2 --->
<cfset wrapper.SmartOrderLineRequest = itemArray >


<!--- finally, pass wrapper object to appropriate method --->
<cfset orderObject = createObject("java", "com.USOrlando").myOrder(
             ....
             , wrapper )>

Update 2:

The above should work, but if for some reason it does not, .. you could also skip the CF array entirely and add the individual item(s) to the underlying List instead. Then pass the wrapper object ie ArrayOfSmartOrderLineRequest instance into the desired method.

<!--- create one or more items .... --->
<cfset myItem = createObject("java", "org.tempuri.SmartOrderLineRequest")>
<cfset myItem.setPLU( JavaCast("string", "123456") )>
<cfset myItem.setPluSalesProgramId( JavaCast("int", 111) )>
<cfset myItem.setQuantity( JavaCast("int", 25) )>

<!--- append items directly to wrapper  object --->
<cfset wrapper = createObject("java", "org.tempuri.ArrayOfSmartOrderLineRequest")>
<cfset wrapper.getSmartOrderLineRequest().add( itemArray )>     
....

<!--- finally, pass wrapper object to appropriate method --->
<cfset orderObject = createObject("java", "com.USOrlando").myOrder(
             ....
             , wrapper )>
like image 108
Leigh Avatar answered Nov 11 '22 01:11

Leigh