Search code examples
javacoldfusioncoldfusion-9

How does one get debugging information out of a cfWindow


We decided to use cfWindows for our modal dialogs. This is something that cannot be changed, so answers and comments of "use another framework" will not resolve the issue.

While we have debugging turned on for our IP addresses, and the debugging information shows up just fine on normal pages, nothing appears in cfWindows. Today I went about trying to recreate the debugging information and manually write it out to the window HTML. I began by using the following code in onRequestEnd, which worked fine on pages called normally:

<cfset tempFactory = createObject("java", "coldfusion.server.ServiceFactory")>
<cfset tempCfdebugger = tempFactory.getDebuggingService()>
<cfset qEvents = tempCfdebugger.getDebugger().getData()>

After taking the time to format the output as desired, I finally tried this on a cfWindow. However, I received the following error on the third line of code:

Detail  Its possible that a method called on a Java object created by CreateObject returned null.
ErrNumber   0
Message     Value must be initialized before use.

This implies that it's not just that CF is set not to display debugging information in cfWindows, but that the Java elements that supply the debugging information don't work the same in the case of cfWindows. I understand very little about the underlying Java, and the code I posted was taken from a CF blog some time ago, so I'm not sure how to troubleshoot this issue.

Is it possible to get debugging information for pages called within a cfWindow? If so, how?

EDIT

To follow up on a suggestion in the comments, I have tried opening the CFWindow templates in their own browser window. Debugging information appears as normal. I then tried CFDumping the results of each of the three lines listed above. The first two work. The "tempCfdebugger" variable does contain a function called "getDebugger()". The problem seems to be when that function is called within a CFWindow. The server must be somehow interpreting CFWindow requests differently.

Is there a different way to get this debugging information other than connecting to the ServiceFactory?


Solution

  • I am going to award the bounty to Scott, as he correctly suggested the _cf_nodebug url variable which resolved the original issue. However, I wanted to post a more complete answer here.

    Scott was correct that we could get full debugging information in a cfWindow by appending _cf_nodebug=true to the url when making the call (though I'm not clear on the logic given the name of the variable). This solved the problem as stated in the original question and was easy to add to our cf_window custom tag; thank you so much Scott. However, I poorly worded the question as we were actually trying to get debugging information from all cfWindow interactions, including the AJAX requests. This ended up being a two stage fix, with _cf_nodebug taking care of stage one.

    While we now have the ability to get debug information from the initial load of the cfWindow, we also needed to modify the cfc to report details on the queries. I could find no url variable that would allow us to access the serviceFactory from a cfc, but given that it was a cfc, and essentially just a dense collection of queries, I was able to add the following function to the component to reproduce some of the desired functionality:

        <cffunction name="debugFunc" access="private" output="yes">
            <cfparam name="session.debugEnabled" default="false">
            <cfif session.debugEnabled>
                <cfoutput>
                    <cfsavecontent variable="debugDetails">
                        Recordcount: #Request.getDataQueryResult.recordcount#<br>
                        Execution Time: #Request.getDataQueryResult.ExecutionTime#ms<br>
                        <cfif isDefined('Request.getDataQueryResult.sqlparameters')>
                            Params: #Request.getDataQueryResult.sqlparameters#<br>
                        </cfif>
                        <br>
                        #Request.getDataQueryResult.sql#
                    </cfsavecontent>
    
                    <script>
                        parent.cfWindowDebugDivAdd("cfWindow: #url.method#", "#ReplaceList(debugDetails, "#Chr(10)#,#Chr(13)#,""", " ")#");
                    </script>
                </cfoutput>
            </cfif>
        </cffunction>
    

    I then did a search and replace in the cfc to modify the beginning and end of each of our 100 or so cfQuery tags:

            <cfquery result="Request.getDataQueryResult" ...>
                ...
            </cfquery>
            <cfset debugFunc()>
    

    This stores the query information in a struct in the Request scope, then calls the debug function above to write some JS to pass that back to the parent page. All you need then is a function on the parent page to take the debug information and dump it into a div, span, or browser console. In case it helps anyone else, here is the code I used for my testing:

        <div id="cfWindowDebugDiv" style="width:1000px; height:300px; overflow:auto; text-align:left;"></div>
    
        <script>
            function cfWindowDebugDivAdd(heading, details) {
                $("#cfWindowDebugDiv").append("<b><u>" + heading + "</u></b><br>");
                $("#cfWindowDebugDiv").append(details + "<br><br><br><br>");
            }
        </script>