10 Replies Latest reply on May 6, 2016 4:51 AM by athanasiusrc

    Change to javacast or json in CF2016?

    athanasiusrc Level 1

      We were running CF8 and the following code worked.

       

      <cfset attributes.email = "manual2016@2016.com">
      <cfset attributes.bday = "05-04">
      <cfset attributes.name = "test">
      <!--- <cfparam name="attributes.email" default="#form.email#">
      <cfparam name="attributes.bday" default="#form.month#-#form.year#-1900">
      <cfparam name="attributes.name" default="#form.name#"> --->

       

       

      <cfset attributes.sdk.addContactStruct = structNew()/>
      <cfset attributes.sdk.addContactStruct["Email"] = JavaCast("string", "#attributes.email#") />
      <cfset attributes.sdk.addContactStruct["Birthday"] = JavaCast("string", "#attributes.bday#") />
      <cfset attributes.sdk.addContactStruct["FirstName"] = JavaCast("string", "#attributes.name#") />
      <cfset variables.optinreason = JavaCast("string", "Store newsletter form") />

       

       

      <cfset contactId = application.sdk.addWithDupCheck(attributes.sdk.addContactStruct, "Email", variables.optinreason) />

       

       

      <cfset TagcontactId = application.sdk.addToGroup(contactId, 178)/>

       

       

      We did an upgrade to CF2016 and part of this code no longer works. Specifically:

       

      <cfset TagcontactId = application.sdk.addToGroup(contactId, 178)/>

       

      Did something in the newer versions of CF change how we need to cast variables like this when they are being past to Java?

       

      I've tried to get error messages with CFTRY back but only get

      Diagnostics: null null
      The error occurred on line -1.

        • 1. Re: Change to javacast or json in CF2016?
          Carl Von Stetten Adobe Community Professional & MVP

          What, specifically is application.sdk.addToGroup()?  Is that a Java object method?

           

          If so, is that Java object compatible with the JVM version that ColdFusion 2016 runs on (Java 8)?  ColdFusion 8 ran on a much older version of Java and the object may not be compatible with Java 8.

          • 2. Re: Change to javacast or json in CF2016?
            BKBK Adobe Community Professional & MVP

            I would dump or log contactId and take a look.

            • 3. Re: Change to javacast or json in CF2016?
              athanasiusrc Level 1

              The first part of the code still works where a call to Infusionsoft creates a contact and generates an id.

               

              The problem is this second piece that sends back the contactID and an integer representing a category tag.

               

              sdk.addtogroup is a function

               

              <cfargument name="contactId" required="true" type="numeric" />

              <cfargument name="groupId" required="true" type="numeric" />

              <cfset var loc = StructNew() />

              <cfset loc.array = ArrayNew(1) />

              <cfset ArrayAppend(loc.array, JavaCast("int", arguments.contactId)) />

              <cfset ArrayAppend(loc.array, JavaCast("int", arguments.groupId)) />

              <cfreturn this.call("ContactService.addToGroup", loc.array) />

               

               

              <cffunction name="addToGroup" output="false" access="public" returntype="boolean" hint="http://developers.infusionsoft.com/classes/contact/##addToGroup"> <cfargument name="contactId" required="true" type="numeric" /> <cfargument name="groupId" required="true" type="numeric" /> <cfset var loc = StructNew() /> <cfset loc.array = ArrayNew(1) /> <cfset ArrayAppend(loc.array, JavaCast("int", arguments.contactId)) /> <cfset ArrayAppend(loc.array, JavaCast("int", arguments.groupId)) /> <cfreturn this.call("ContactService.addToGroup", loc.array) /> </cffunction>

              • 4. Re: Change to javacast or json in CF2016?
                athanasiusrc Level 1

                These are the java objects created:

                 

                <cfscript>
                this.setApiKey(arguments.apiKey);
                try
                {
                variables.url = CreateObject("java", "java.net.URL").init("https://#arguments.subdomain#.infusionsoft.com/api/xmlrpc");
                variables.configImpl = CreateObject("java", "org.apache.xmlrpc.client.XmlRpcClientConfigImpl");
                variables.configImpl.setServerURL(variables.url);
                variables.configImpl.setConnectionTimeout(arguments.timeout * 1000);
                // create the client object
                variables.client = CreateObject("java", "org.apache.xmlrpc.client.XmlRpcClient");
                variables.client.setConfig(variables.configImpl);
                variables.client.setTransportFactory(CreateObject("java", "org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory").init(variables.client));
                }
                catch (any e)
                {
                variables.javaLib = false;
                variables.client = CreateObject("component", "com.liquifusion.xmlrpc.Client").init(ssl=true, host=arguments.subdomain & ".infusionsoft.com", path="/api/xmlrpc", timeout=arguments.timeout);
                variables.transform = CreateObject("component", "com.liquifusion.xmlrpc.Transform").init();
                }
                return this;
                </cfscript>
                • 5. Re: Change to javacast or json in CF2016?
                  Carl Von Stetten Adobe Community Professional & MVP

                  Once again, is that Java object compatible with Java 8?  Just because one or more methods in the object work on Java 8 doesn't mean all of them will.  You can't see the Java dependencies that are inside the Java classes, so you don't know if they are relying on an older dependency class signature or a deprecated/removed class.  And the limited error message you are getting seems to indicate the problem is with Java, not ColdFusion.

                  • 6. Re: Change to javacast or json in CF2016?
                    BKBK Adobe Community Professional & MVP

                    athanasiusrc wrote:

                    <cfreturn this.call("ContactService.addToGroup", loc.array) />

                     

                    That line raises questions:

                     

                    1) What is ContactService.addToGroup?

                    2) If, as you say, addToGroup is a function, then what is the string "ContactService.addToGroup" doing there as argument of a function?

                    3) Assuming you can justify the use of "ContactService.addToGroup", then why not just <cfreturn call("ContactService.addToGroup", loc.array)>?

                    • 7. Re: Change to javacast or json in CF2016?
                      athanasiusrc Level 1

                      I was able to get a more useful error message.

                       

                      Diagnostics: java.lang.Long cannot be cast to java.lang.String null

                       

                       

                      Here's the code sequence where the error is occurring:

                       

                      This takes an integer contactid (confirmed that it gets created):

                       

                      <cfset TagcontactId = application.sdk.addToGroup(contactID, 202)/>

                       

                       

                      Which calls this:

                       

                      <cffunction name="addToGroup" output="false" access="public" returntype="boolean" hint="http://developers.infusionsoft.com/classes/contact/##addToGroup">
                      <cfargument name="contactId" required="true" type="numeric" />
                      <cfargument name="groupId" required="true" type="numeric" />
                      <cfset var loc = StructNew() />
                      <cfset loc.array = ArrayNew(1) />
                      <cfset ArrayAppend(loc.array, JavaCast("int", arguments.contactId)) />
                      <cfset ArrayAppend(loc.array, JavaCast("int", arguments.groupId)) />
                      <cfreturn this.call("ContactService.addToGroup", loc.array) />
                      </cffunction>

                       

                      this.call breaks here:

                       

                      <cfset loc.requestXml = variables.transform.cfmlToXmlRpcRequest(arguments.method, loc.parameters) />

                       

                      because something goes wrong in this string of functions:

                       

                      <cffunction name="cfmlToXmlRpcRequest" access="public" returntype="string" output="false" hint="I create the XML necessary to make an XML-RPC call.">
                      <cfargument name="method" required="true" type="string" />
                      <cfargument name="parameters" required="true" type="array" />
                      <cfset var loc = StructNew() />
                      <cfset loc.loopCounter = 0 />
                      <cfset loc.method = arguments.method />
                      <cfset loc.parameters = arguments.parameters />
                      <cfset loc.parameterXml = "<param>{value}</param>" />
                      <cfset loc.parameterString = "" />
                      <cfsavecontent variable="loc.xml">
                      <methodCall>
                      <methodName>{method}</methodName>
                        <params>
                      {parameters}
                      </params>
                      </methodCall>
                      </cfsavecontent>
                      <cfset loc.xml = Replace(loc.xml, "{method}", loc.method) />
                      <cfloop index="loc.loopCounter" from="1" to="#ArrayLen(loc.parameters)#">
                      <cfset loc.parameterString = loc.parameterString & Replace(loc.parameterXml, "{value}", this.serialize(loc.parameters[loc.loopCounter])) />
                      </cfloop>
                      <cfset loc.xml = Replace(loc.xml, "{parameters}", loc.parameterString) />
                      <cfreturn loc.xml />
                      </cffunction>

                       

                      <cffunction name="serialize" access="public" output="false">
                      <cfargument name="branch" required="true" type="any" />
                      <cfset var loc = StructNew() />
                      <cfset loc.results = "" />
                      <cfset loc.temp = "" />
                      <cfset loc.arrayWrapper  = "<value><array><data>{items}</data></array></value>" />
                      <cfset loc.structWrapper = "<value><struct>{items}</struct></value>" />
                      <cfset loc.structMember  = "<member>{name}{value}</member>" />
                      <cfset loc.structKey     = "<name>{key}</name>" />
                      <cfset loc.branch = arguments.branch />
                      <cfset loc.loopCounter = 0 />
                      <cfif IsStruct(loc.branch)>
                      <cfloop item="loc.loopCounter" collection="#loc.branch#">
                      <cfset loc.temp = Replace(loc.structKey, "{key}", loc.loopCounter) />
                      <cfset loc.temp = Replace(loc.structMember, "{name}", loc.temp) />
                      <cfset loc.results = loc.results & Replace(loc.temp, "{value}", this.serialize(loc.branch[loc.loopCounter])) />
                      </cfloop>
                      <cfset loc.results = Replace(loc.structWrapper, "{items}", loc.results) />
                      <cfelseif IsBinary(loc.branch)>
                      <cfset loc.results = variables.toXml(ToBase64(loc.branch), "base64") />
                      <cfelseif IsArray(loc.branch)>
                      <cfloop index="loc.loopCounter" from="1" to="#ArrayLen(loc.branch)#">
                      <cfset loc.results = loc.results & this.serialize(loc.branch[loc.loopCounter]) />
                      </cfloop>
                      <cfset loc.results = Replace(loc.arrayWrapper, "{items}", loc.results) />
                      <cfelseif IsDate(loc.branch)>
                      <cfset loc.results = variables.toXml(variables.formatDateTime(loc.branch), "dateTime.iso8601") />
                      <cfelseif loc.branch.getClass().isInstance(variables.instance.integer)>
                      <!---
                      Note: in order to be CF7 compatible, we cannot use IsInstanceOf()
                      <cfelseif IsInstanceOf(loc.branch, "java.lang.Integer")>
                      --->
                      <cfset loc.results = variables.toXml(Int(loc.branch), "int") />
                      <cfelseif loc.branch.getClass().isInstance(variables.instance.double)>
                      <!---
                      Note: in order to be CF7 compatible, we cannot use IsInstanceOf()
                      <cfelseif IsInstanceOf(loc.branch, "java.lang.Double")>
                      --->
                      <cfset loc.results = variables.toXml(loc.branch, "double") />
                      <cfelseif loc.branch.getClass().isInstance(variables.instance.boolean)>
                      <!---
                      Note: in order to be CF7 compatible, we cannot use IsInstanceOf()
                      <cfelseif IsInstanceOf(loc.branch, "java.lang.Boolean")>
                      --->
                      <cfset loc.results = variables.toXml(Int(loc.branch), "boolean") />

                       

                       

                      <cfelseif loc.branch.getClass().isInstance(variables.instance.string)>
                      <!---
                      Note: in order to be CF7 compatible, we cannot use IsInstanceOf()
                      <cfelseif IsInstanceOf(loc.branch, "java.lang.String")>
                      --->
                      <cfset loc.results = variables.toXml(XmlFormat(loc.branch), "string") />
                      </cfif>

                       

                       

                      <cfreturn loc.results />
                      </cffunction>

                       

                      Ending with this function:

                       

                      <cffunction name="toXml" output="false" access="private" returntype="string">
                      <cfargument name="value" required="true" type="any" />
                      <cfargument name="tagName" required="true" type="string" />
                      <cfset var loc = StructNew() />
                      <cfset loc.simpleTag = "<value><{tagName}>{value}</{tagName}></value>" />
                      <cfset loc.results = "" />
                      <cfset loc.results = Replace(loc.simpleTag, "{tagName}", arguments.tagName, "all") />
                      <cfset loc.results = Replace(loc.results  , "{value}"  , arguments.value) />
                      <cfreturn loc.results />
                      </cffunction>
                      • 8. Re: Change to javacast or json in CF2016?
                        athanasiusrc Level 1

                        I've found the developer and he is going to take a look at this. Thank you for the assist.

                        • 9. Re: Change to javacast or json in CF2016?
                          BKBK Adobe Community Professional & MVP

                          <cfset ArrayAppend(loc.array, JavaCast("int", arguments.contactId)) />

                          <cfset ArrayAppend(loc.array, JavaCast("int", arguments.groupId)) />

                          ContactId and GroupId are integers so I would just do this instead:

                           

                          <cfset ArrayAppend(loc.array, arguments.contactId) >

                          <cfset ArrayAppend(loc.array, arguments.groupId) >

                          • 10. Re: Change to javacast or json in CF2016?
                            athanasiusrc Level 1

                            Nope, didn't fix it.