Skip to main content
Chinyenje
Participating Frequently
March 4, 2016
Answered

Dealing with parallel requests to cfc

  • March 4, 2016
  • 3 replies
  • 1708 views

I have a cfc that is exposed as a web service . However when a request from 2 different servers consume the webserice at the same time one request is dropped and the other processed. Im not sure why this happens and would really appreciate some insight

Thanks!

    This topic has been closed for replies.
    Correct answer BKBK

    Thank for the link. Below is the declarant code

    <cffunction name="getDeclarant" returntype="any" access="private">

      <cfargument name="clienttpi" type="string" required="no" hint="This carries the TPIN"  >

      <cfargument name="poe" type="string" required="yes"   >

      <cfargument name="rnum" type="string" required="yes"  >

      <cfargument name="rser" type="string" required="yes"  >

      <cfargument name="registrationYear" type="string" required="yes"  >

      <cfset getArrD= arraynew(2)>

    <cfset var size = 0>

    <cfsavecontent variable="soapBodyd">

          <cfoutput>

          <?xml version="1.0" encoding="utf-8"?>

          <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:asy="http://www.asy.org">

            <soapenv:Header/>

            <soapenv:Body>

              <asy:getutp>

                <!--Optional:-->

                <asy:tinfo>

                  <bankCode>SCB</bankCode>

                  <!--Optional:-->

                  <ctpi>#arguments.clienttpi#</ctpi>

                </asy:tinfo>

              </asy:getutp>

            </soapenv:Body>

          </soapenv:Envelope>

          </cfoutput>

          </cfsavecontent>

          <cfif localtest eq "YES">

          <cfhttp url="http://localhost" method="head"  result="httpResponse" >

    </cfhttp>

          <cfelse>

             <cfhttp

    url="https://127.0.0.1:8443/asy/WSZ"

    method="post"

    result="httpResponse" username="123" password="123">

         

          <cfhttpparam

    type="header"

    name="SOAPAction"

    value="urn:getU"

    />

          <cfhttpparam

    type="header"

    name="accept-encoding"

    value="no-compression"

    />

          <cfhttpparam

    type="xml"

    value="#trim( soapBodyd )#"

    />

          </cfhttp>

          </cfif>

    <cfif localtest eq "YES">

    <cfset tranXML =getTransXML()>

    </cfif>

          <cfif find( "200", httpResponse.statusCode )>

          <cfif localtest eq "YES">

       <cfset soapResponsed = xmlParse( #tranXML# ) />

          <cfelse>

            <cfset soapResponsed = xmlParse( httpResponse.fileContent ) />

            </cfif>

            <!--- --->

            <cfset responseNodesd = xmlSearch(

    soapResponsed,

    "//*[ local-name() = 'unSR' ]"

    ) />

            <cfset FindTPIN = xmlSearch(

    soapResponsed,

    "//*[ local-name() = 'TPIN' ]"

    ) />

            <cfoutput>

            <cfsavecontent variable="strXml"> #soapResponsed# </cfsavecontent>

            <cfset strXml = strXml.ReplaceAll(

      "(</?)(\w+:)",

      "$1"

      ) />

            <cfset strXml = strXml.ReplaceAll(

      "xmlns(:\w+)?=""[^""]*""",

      ""

      ) />

            <cfset xmlRequest = XmlParse(

      strXml.Trim()

      ) />

            <cfset XMLDOM = xmlParse(xmlRequest)>

            <cfset i=1>

            <cfset products =ArrayNew(2)>

            <cfloop   index="results" array="#xmlsearch(XMLDOM,'/Envelope/Body/getUTResponse/unSR/assmntPaid')#">

            <cfset results = xmlparse(results)>

            <cfset getArrD[1]=#results.asmTpd.declarantCode.xmltext#>

            <cfset getArrD[2]=#results.asmTpd.TPIN.xmltext#>

            <cfset getArrD[3]=#results.asmTpd.officeCode.XmlText#>

            <cfset getArrD[4]=#results.asmTpd.astp.XmlText#>

            <cfset getArrD[5]=#results.asmTpd.registrationYear.xmltext#>

            <cfset getArrD[6]=#results.asmTpd.rser.xmltext#>

            <cfset getArrD[7]=#results.asmTpd.rnum.xmltext#>

            <cfset getArrD[8]=#results.asmTpd.amtP.xmltext#>

            <cfset i=i+1>

            </cfloop>

            </cfoutput>

           

          </cfif>

      

          <cfset size = ArrayLen(getArrD)>

          <cfif size gte 1>

            <cfset myqueryD = QueryNew("trans_id,declarantCode,tpi,poe,astp,ayear,rser,rnum,amtP,reasonCode,reasonDescription,source,sourceID,timestamp,type,country","VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar") >

            <cfset temp = QueryAddRow(myqueryD,#size#)>

            <cfloop index="i" from = "1" to = #size#>

            <cfset temp = QuerySetCell(myqueryD, "trans_id", #i#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "declarantCode", #getArrD[1]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "tpi", #getArrD[2]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "poe", #getArrD[3]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "astp", #getArrD[4]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "ayear", #getArrD[5]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "rser", #getArrD[6]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "rnum", #getArrD[7]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "amtP", #getArrD[8]#, #i#)>

            <cfset temp = QuerySetCell(myqueryD, "reasonCode", "0", #i#)>

            <cfset temp = QuerySetCell(myqueryD, "reasonDescription", "Sucessful", #i#)>

            <cfset temp = QuerySetCell(myqueryD, "source", "SP" ,#i#)>

            <cfset temp = QuerySetCell(myqueryD, "sourceID", "1234", #i#)>

            <cfset temp = QuerySetCell(myqueryD, "timestamp", "12:00", #i#)>

            <cfset temp = QuerySetCell(myqueryD, "type", "CHN", #i#)>

            <cfset temp = QuerySetCell(myqueryD, "country", "CHN", #i#)>

            </cfloop>

            <cfelse>

            <cfset myqueryD = QueryNew("trans_id,declarantCode,tpi,poe,astp,ayear,rser,rnum,amtP,reasonCode,reasonDescription,source,sourceID,timestamp,type,country","VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar,VarChar") >

          </cfif>

     

      

          <cfquery name="filteredData" dbtype="query">

        select * from myqueryD where

      

        rnum=<cfqueryparam value="#arguments.rnum#"> and rser=<cfqueryparam value="#arguments.rser#"> and poe =<cfqueryparam value="#arguments.poe#">

        and ayear= <cfqueryparam value="#arguments.registrationYear#" cfsqltype="cf_sql_varchar">

        </cfquery>

      <cfreturn filteredData>

        

    </cffunction>


    Some immediate suggestions

    1) localtest is undefined; define it.

    2) Var all your function-local variables:

    <cfset var getArrD= arraynew(2)>

    <cfset var size = 0>

    <cfset var soapBodyd = "">

    <cfset var soapResponsed = "">

    <cfset var responseNodesd = "">

    <cfset var FindTPIN = "">

    <cfset var strXml = "">

    <cfset var xmlRequest = "">

    <cfset var XMLDOM = "">

    <cfset var products = "">

    <cfset var results = "">

    <cfset var myqueryD = queryNew("")>

    <cfset var temp = "">

    <cfset var filteredData = queryNew("")>

    3) Where you use arguments, prefix them with arguments.someVar

    3 replies

    BKBK
    Community Expert
    Community Expert
    March 5, 2016

    By default, requests to a web service run concurrently, each as a separate thread. If that is different in your service, then it means you have to redesign your service. Could you show us the CFC?

    Dave Ferguson
    Participating Frequently
    March 5, 2016

    There is something in your code that is not thread safe.  Can you share the code from your service that you are having issues with?  I have written many services like you describe and have not ran into the issue you are having.  You shouldn't need to use cflock for this.

    --Dave

    Chinyenje
    ChinyenjeAuthor
    Participating Frequently
    March 5, 2016

    this is the code that is giving the issue BKBK

    <cffunction name="sendPaymentConfirmation" returntype="any" access="remote" >

      <cfargument name="tid" type="string" required="true"  />

      <cfargument name="cid" type="string" required="true"   />

      <cfargument name="declarantFlag" type="string" required="true" />

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

      <cfargument name="aNumber" type="string" required="true" />

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

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

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

      <cfargument name="asYear" type="string" required="true"  />

      <cfargument name="pEntry" type="string" required="true"  />

      <cfargument name="rSerial" type="string" required="true" />

       <cfargument name="rNumber" type="string" required="true" />

      <cfargument name="rDate" type="string" required="false"/>

    <cfargument name="pType" type="string" required="true"/>

      <cfargument name="source" type="string" required="true"  />

      <cfargument name="sourceID" type="string" required="true"   />

      <cfargument name="timestamp" type="string" required="true"/>

      <cfargument name="type" type="string" required="true"  />

      <cfargument name="country" type="string" required="true"  />

        <cfif #pflag# eq 2>

    <cfset declarantCode=getDeclarant(#cid#,#pEntry#,#rNumber#,#rSerial#,#asYear#)>

         <cfif #iAmt# gt 0>

            <cfquery datasource="smartpay_log">  

        INSERT INTO Log_table (taxPerIdentification, aNumber, aPaid, asYear, pEntry, rSerial, rNumber, rDate, source, sourceID, timestamp, type, country,asyResponse,log_time,item_type,declarant_code)

    VALUES (<cfqueryparam value="#cid#">,<cfqueryparam value="#rNumber#">,<cfqueryparam value="#iAmt#">,<cfqueryparam value="#asYear#">,<cfqueryparam value="#pEntry#">,<cfqueryparam value="#rSerial#">,<cfqueryparam value="#rNumber#">,<cfqueryparam value="#asYear#">,<cfqueryparam value="#source#">,<cfqueryparam value="#sourceID#">,<cfqueryparam value="#timestamp#">,<cfqueryparam value="#type#">,<cfqueryparam value="#country#">,<cfqueryparam value=" ">,<cfqueryparam value="#DateFormat(now(),"DD-MM-YYYY")# #TimeFormat(now(),"HH:mm:ss")#">,<cfqueryparam value="INTQ">,<cfqueryparam value="#declarantCode.declarantCode#">)

      </cfquery>

        

    <cfset var xmlPacket_details_INT = "">

        <cfxml variable="xmlPacket_details_INT">

         <cfoutput><sendPaymentConfirmationResponse>

            <PaymentConfirmation>

              <pType>1</pType>

              <reasonCode>0</reasonCode>

              <reasonDescription>PAYMENTQUEUED</reasonDescription>

              <source>#source#</source>

              <sourceID>#sourceID#</sourceID>

              <timestamp>#DateFormat(now(),"YYYY-MM-DD")#T#TimeFormat(now(),"HH:mm:ss")#</timestamp>

              <type>#type#</type>

              <country>#country#</country>

            </PaymentConfirmation>

          </sendPaymentConfirmationResponse></cfoutput>

         </cfxml>

        </cfif>

      

      <cfif #pAmt# gt 0>

        <cfquery datasource="smartpay_log">  

        INSERT INTO Log_table (taxPerIdentification, aNumber, aPaid, asYear, pEntry, rSerial, rNumber, rDate, source, sourceID, timestamp, type, country,asyResponse,log_time,item_type,declarant_code)

    VALUES (<cfqueryparam value="#cid#">,<cfqueryparam value="#rNumber#">,<cfqueryparam value="#pAmt#">,<cfqueryparam value="#asYear#">,<cfqueryparam value="#pEntry#">,<cfqueryparam value="#rSerial#">,<cfqueryparam value="#rNumber#">,<cfqueryparam value="#asYear#">,<cfqueryparam value="#source#">,<cfqueryparam value="#sourceID#">,<cfqueryparam value="#timestamp#">,<cfqueryparam value="#type#">,<cfqueryparam value="#country#">,<cfqueryparam value=" ">,<cfqueryparam value="#DateFormat(now(),"DD-MM-YYYY")# #TimeFormat(now(),"HH:mm:ss")#">,<cfqueryparam value="PRNQ">,<cfqueryparam value="#declarantCode.declarantCode#">)

      </cfquery>

     

        </cfif>

       

        <cfif #iAmt# gt 0>

      </cfif>

       

      

      </cfif>

     

    </cffunction>

    BKBK
    Community Expert
    Community Expert
    March 5, 2016

    I haven't looked into the content. But I do believe you can improve the code by doing something like

    <cffunction name="sendPaymentConfirmation" returntype="any" access="remote" >

       

    <cfargument name="tid" type="string" required="true"  />

    <cfargument name="cid" type="string" required="true"   />

    <cfargument name="declarantFlag" type="string" required="true" />

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

    <cfargument name="aNumber" type="string" required="true" />

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

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

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

    <cfargument name="asYear" type="string" required="true"  />

    <cfargument name="pEntry" type="string" required="true"  />

    <cfargument name="rSerial" type="string" required="true" />

    <cfargument name="rNumber" type="string" required="true" />

    <cfargument name="rDate" type="string" required="false"/>

    <cfargument name="pType" type="string" required="true"/>

    <cfargument name="source" type="string" required="true"  />

    <cfargument name="sourceID" type="string" required="true"   />

    <cfargument name="timestamp" type="string" required="true"/>

    <cfargument name="type" type="string" required="true"  />

    <cfargument name="country" type="string" required="true"  />

    <cfset var declarantCode = "">

    <cfset var xmlPacket_details_INT = "">

    <cfif arguments.pflag eq 2>

        <cfset declarantCode=getDeclarant(arguments.cid,arguments.pEntry,arguments.rNumber,arguments.rSerial,arguments.asYear)>

        <cfif arguments.iAmt gt 0>

            <cfquery datasource="smartpay_log"> 

            INSERT INTO Log_table (taxPerIdentification, aNumber, aPaid, asYear, pEntry, rSerial, rNumber, rDate, source, sourceID, timestamp, type, country,asyResponse,log_time,item_type,declarant_code)

            VALUES (<cfqueryparam value="#arguments.cid#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.rNumber#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.iAmt#" cfsqltype="CF_SQL_NUMERIC">,

                    <cfqueryparam value="#arguments.asYear#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.pEntry#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.rSerial#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.rNumber#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.asYear#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.source#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.sourceID#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.timestamp#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.type#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.country#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value=" " cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#DateFormat(now(),'DD-MM-YYYY')# #TimeFormat(now(),'HH:mm:ss')#" cfsqltype="CF_SQL_DATE">,

                    <cfqueryparam value="INTQ" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.declarantCode.declarantCode#" cfsqltype="CF_SQL_VARCHAR">)

            </cfquery>

            <cfxml variable="xmlPacket_details_INT">

            <cfoutput><sendPaymentConfirmationResponse>

            <PaymentConfirmation>

            <pType>1</pType>

            <reasonCode>0</reasonCode>

            <reasonDescription>PAYMENTQUEUED</reasonDescription>

            <source>#arguments.source#</source>

            <sourceID>#arguments.sourceID#</sourceID>

            <timestamp>#DateFormat(now(),"YYYY-MM-DD")#T#TimeFormat(now(),"HH:mm:ss")#</timestamp>

            <type>#arguments.type#</type>

            <country>#arguments.country#</country>

            </PaymentConfirmation>

            </sendPaymentConfirmationResponse></cfoutput>

            </cfxml>

        </cfif>

       

        <cfif arguments.pAmt gt 0>

            <cfquery datasource="smartpay_log"> 

            INSERT INTO Log_table (taxPerIdentification, aNumber, aPaid, asYear, pEntry, rSerial, rNumber, rDate, source, sourceID, timestamp, type, country,asyResponse,log_time,item_type,declarant_code)

            VALUES (<cfqueryparam value="#arguments.cid#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.rNumber#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.pAmt#" cfsqltype="CF_SQL_NUMERIC">,

                    <cfqueryparam value="#arguments.asYear#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.pEntry#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.rSerial#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.rNumber#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.asYear#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.source#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.sourceID#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.timestamp#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.type#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#arguments.country#" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value=" " cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#DateFormat(now(),'DD-MM-YYYY')# #TimeFormat(now(),'HH:mm:ss')#" cfsqltype="CF_SQL_DATE">,

                    <cfqueryparam value="PRNQ" cfsqltype="CF_SQL_VARCHAR">,

                    <cfqueryparam value="#declarantCode.declarantCode#" cfsqltype="CF_SQL_VARCHAR">)

            </cfquery>

        </cfif>

       

        <cfif arguments.iAmt gt 0>

        </cfif>

       

    </cfif>

    <cfreturn someVar><!---Otherwise remove this line and set returntype = "void"--->

    </cffunction>

    WolfShade
    Legend
    March 4, 2016

    One possible solution that I can think of would be to use CFTHREAD for the requests.  That should eliminate any collisions, conflicts, or (a VERY small, miniscule, remote chance) identical IDs.

    HTH,

    ^_^

    UPDATE: I highly doubt that two servers could both have the same CFID/CFTOKEN combination, so never mind.. 

    Chinyenje
    ChinyenjeAuthor
    Participating Frequently
    March 5, 2016

    Hmm something like this ....

    <cfset VARIABLES.Instance.LockID = CreateUUID() />

        <cffunction

            name="Add"

            access="public"

            returntype="any"

            output="false"

            >

            <!--- Define arguments. --->

            <cfargument

                name="Message"

                type="string"

                required="true"

                          />

            <!--- Lock method call. --->

            <cflock

                name="#VARIABLES.Instance.LockID#-Message"

                type="exclusive"

                timeout="5">

                <cfreturn SUPER.Add(

                    Message = ARGUMENTS.Message

                    ) />

            </cflock>

        </cffunction>

    Inspiring
    March 5, 2016

    This is the code you have at the moment?

    The exclusive lock you have there will cause the behavior you have described. The lock wont let another request run the code until the previous request is done