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()
.
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:
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:
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.
(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
SmartOrderLineRequest
to itArrayOfSmartOrderLineRequest
, replacing the underlying List
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 )>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With