在 ColdFusion 中传递 Java 对象

Passing Java Object in ColdFusion

这是这个问题的延续:WCF and ColdFusion

因此,我设法使用 Metro 和导入 WSDL 获得了一个 JAR。我的主要 class 具有以下功能:getVersion() 和我的实现 myVersion()cancelOrder()myCancel(),最后是 placeOrdermyOrder().

对于前两种方法(getVersioncancelOrder),我能够传递正确的信息并从 Web 服务获得响应:

比如在myVersion方法中调用webservice,输出版本号加上传入的字符串:

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

使用相同的模板,我还可以在 myOrder 方法中传递所有其他参数,除了类型为 org.tempuri.ArrayOfSmartOrderLineRequest.

的最后一个参数

这是我不自信的地方,可能需要指导:

在浏览文档和生成的 classes 时,我会将文档中的内容放在块引号中以及我对它们的理解。

myOrder 应该获取通过 ColdFusion 传入的所有参数并将其放入 request 对象中。

<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)
)>

最后一行 JavaCast("org.tempuri.ArrayOfSmartOrderLineRequest", orderItems) 是我的问题。我得到一个

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.

错误,有道理。如果我将其设为 null,则不会向 SoapMessage 传递任何内容。

我的问题是:如何传递最后一个参数?

orderItems 是一个 CF 变量,我相信它引用了一个 Java 对象。

<!---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)>

逆向计算,ArrayOfSmartOrderLineRequest.java 有一个方法 getSmartOrderLineRequest。根据生成的 java 文件中的注释:

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);

我认为这意味着我必须创建一个 newItem 对象并将其传递给 getSmartOrderLineRequestadd 方法,对吗?因此,在构建 newItem 对象时,我创建了 myItem 变量,它具有三个属性:PLUPluSalesProgramIdQuantity.

在我的脑海中,我正在CF中创建一个myItem对象,它被保存在Java中,然后告诉Java方法getSmartOrderLineRequest"Hey, ADD myItem to your array."

如有任何帮助,我们将不胜感激。我觉得我快到了,但我不知道我应该朝哪个方向前进。

编辑 1: 对 Leigh 评论的回应。

当我单独传递对象时会发生什么,这不是一个愚蠢的问题。我重新创建了以下步骤,但出现了一个奇怪的错误:起初,我尝试了以下操作:

<!---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 --->

我试过下面的代码,没有报错:

<!---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 --->

我使用以下方式传递它:

<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 --->

下面是ArrayOfSmartOrderLineRequest.java的shell:

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;
    }
}

以下是 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>

编辑 2: 采纳 Leigh 的建议

以Psuedo-Code为模板,一步一个脚印

1) 创建需要传递的项目。

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

myItem 的 cfdump 揭示了以下方法:

根据文档,参数的顺序是PluSalesProgramIdPLUQuantity

2) 将信息添加到项目中。

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

跳过这一步。 * 3) 将项目添加到 CF 数组。

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

itemArray的转储如下:

到目前为止一切顺利。

4) 接下来,将对 myItem 的引用添加到 ArrayOfSmartOrderLineRequest.

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

5) 最后,orderItemsmyOrder方法:

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

耶!成功了!我必须检查代码以确保一切都正确完成,但查看日志,看起来 SOAP 消息已正确发送,并且返回了 PLU not found 的预期错误。

Leigh,如果你把一个东西作为答案,我回到办公室后会接受它作为答案。

(评论摘要)

尽管名称为 ArrayOf,但我怀疑 ArrayOfSmartOrderLineRequest class 更像是数组的包装器(或 java.util.List), similar to ArrayOfString。可以您 post a) class 的基本 shell(变量等)和 b) 如果可能,从 WSDL 定义该对象?

更新 1:

所以项目 class,即 SmartOrderLineRequest,具有三 (3) 个主要值:PluSalesProgramId、PLU 和数量?你应该能够

  1. 创建一个常规 CF 数组并将 SmartOrderLineRequest 的实例附加到它
  2. 将 CF 数组传递到包装器 class 即 ArrayOfSmartOrderLineRequest替换 底层 List
  3. 最后,将包装器对象即 ArrayOfSmartOrderLineRequest(不是基础列表)传递到适当的方法中。

显然完全未经测试,但像这样:

<!--- 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 )>

更新二:

上面应该可以工作,但如果由于某种原因它不工作,..您也可以完全跳过 CF 数组并将单个 item(s) 添加到底层列出来。然后将包装器对象即 ArrayOfSmartOrderLineRequest 实例传递给所需的方法。

<!--- 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 )>