Coldfusion 11 Ajax CFC binding impossible - ajax

I know a lot of people have had issues with Ajax and older versions of Coldfusion, but I'm using Coldfusion 11 Developer on my local machine and am finding it impossible to bind - under all circumstances - using Coldfusion functions, to a CFC, although it's not always the same error that gets returned.
I can't use autosuggest for a cfdiv when that binds to a CFC - but I can bind to autosuggest data on the same page, including from a database. When I bind to a CFC, invariably, the error message in CFDebug comes up as
"error:widget: Bind failed for autosuggest lastname, bind value is not a 1D array of strings.
info:http: CFC invocation response: ["Barken","Barnes"] ...
... by which you can see, that the bind IS a 1D array of strings and the CFC produced them, but wouldn't return them to the calling page!
I've also tried making the CFC much simpler, removing the database element and manually creating a straightforward 1D array of strings, but the same error comes up as when fed from my database.
So I made a test even simpler, avoiding databases and arrays to test ordinary, simple binding, not involving autosuggest - just an ordinary bind to a CFC (I always can successfully bind to data on the same page, or a URL.)
Here's the simplest test code, which still doesn't work:
<body>
<cfform id="myForm" name="myForm">
Enter your name into the box:<br />
<cfinput type="text" name="myText">
</cfform>
<hr />
Below is a cfdiv container, with a bind to a CFC:<br />
<cfdiv bind="cfc:bindsource.getDivContent({myText})"></cfdiv>
</body>
This is the CFC, named bindsource.cfc, in the same folder as the form page:
<cfcomponent output="false">
<cffunction name="getDivContent" returntype="string" access="remote" >
<cfargument name="edit">
<cfreturn "Your entered content was: #arguments.edit#">
</cffunction>
</cfcomponent>
In this case, the error I get is:
window:global: Uncaught exception: TypeError: Cannot convert '_289[i]' to object (http://localhost:8500/CFIDE/scripts/ajax/package/cfajax.js, line 872)
info:http: CFC invocation response: "Your entered content was: William"
(William is the text I entered into the box on the main page. line 872 in the cfajax.js is "872 throw new SyntaxError("parseJSON")"
In this simple test, on my main page, both before and after I enter something into the text input, in the area of what would be the cfdiv, the word "undefined" appears.
Sometimes, if I don't get the 1D array of strings error on some of the test pages, I get this can't convert to object error.
All the examples I've tried - not just my own stuff but all the samples I can find - run, up to the point where the Ajax error kicks in, so there are no other syntax errors. In all cases, the form page loads and runs, the CFC seems to get called, processes as appropriate - CFDebug shows me correct output of the CFC in the debug window - but then nothing ever comes back to the calling page. If I use a url bind, or a same page bind, it does - with a CFC, it doesn't. Ever.
When I test the CFC independently in a direct URL with method and argument passed, it works - I get the same result as the CFC invocation response.
Has anybody EVER got a CFC bind to work in Coldfusion? What am I missing or is CF11 just flawed? The whole things seems a bit unstable. I also get "cannot find CFC" errors, but if I do nothing, switch off, start up again - that particular error doesn't happen again for the same files until sometime later in the session, after repeated attempts to get one of the tests to work.

Wow - that was an obscure one, but I now know what's causing it.
Thanks for the suggestions, especially the one from #Dan Bracuk mentioning conflicts with javascript in the Application.cfc file, which led me to it, but it also helped to know the basic code should and did actually work, as others suggested, so the issue obviously had to do with something else.
Firstly, I removed my Application.cfc file completely - and for the first time, I could bind to a cfc. So then it was a question of finding what, in the Application.cfc, might be doing it.
Well, as it's my development set up, I'm dumping some variables to the page in the onRequestEnd function of Application.cfc. By removing them - it works. Put any of them back (dumps of server, cgi, session, application variables etc.) and again the cfc bind will not work.
I'm not using onRequestEnd for anything other than the variable dumps, but I thought to test what might happen if I were, still while removing the variable dumps. So I just added a simple cfinclude in the onRequestEnd function (the included cfm file does nothing at all - it's an empty cfm framework page with doctype and empty head/body tags that do or output nothing) and again, the cfc bind does not work.
It seems like it (onRequestEnd) will accept basic operations like cfset a=2+1 directly in onRequestEnd (but not in an included file) and the cfc will bind, but that's all (obviously not done exhaustive testing on what you can still do - basically, onRequestEnd is pretty unusable if you want to bind to your CFC.)
So that's it, the onRequestEnd function basically can't be relied upon if the bind to a CFC is to work. If you want it just to perform maths or maybe other things - perhaps you can get away with using it.
Hope this helps somebody else. It's been driving me nuts for weeks.
For what it's worth, so people can compare to their own setup and in case it doesn't apply in every development circumstance, I've been using the CF11 Developer Edition and I'm using the built-in Tomcat server on port 8500.
Thanks again everyone.

Related

Link change SESSION var

I have a listing page for an e-commerce website with various items (item_list.php). This page is generated with a PHP loop and displays each item inside a <li> element. Every item is a link to the same page, called item_details.php .
When clicking on the link i want to run a script that changes a SESSION var to a certain $id (which will be excracted from the <li> itself with .innerHTML function) and then allowing the browser to move into the next page (item_details).
This is needed so i can display the proper information about each item.
I think this is possible with Ajax but I would prefer a solution that uses JS and PHP only.
(P.S.This is for a University project and im still a PHP newbie, i tried searching for an answer for a good while but couldn't find a solution)
No JS or other client-side code can set session values, so you need either an ajax call to php, or some workaround. This is not a complete answer, but something to get you thinking and hopefully going on the project again.
The obvious answer is just include it in the link and then get it in PHP from the $_GET -array, and filter it properly.
item title
If, however, there is some reason this is not a question with an obvious answer:
1.) Closest what you're after can be achieved with a callback and an ajax call. The idea is to have the actual link with a click function, returning false so the link doesn't fire at once, which also calls an ajax post request which finally will use document.location to redirect your browser.
I strongly advice against this, as this will prevent ctrl-clicks causing a flawed user experience.
Check out some code an examples here, which you could modify. You will also need an ajax.php file which will actually set the session value. https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#product-click
2.) Now, a perhaps slightly better approach, if you truly need to do this client-side could be to use an click handler which instead of performing an ajax call or setting session directly, would be to use jQuery to set a cookie and then access this data on the item_list.php -page.
See more information and instructions here: https://www.electrictoolbox.com/jquery-cookies/
<script>
$('product_li a).click(function(){
$.cookie("li_click_data", $(this).parent().innerhtml());
return true;
});
</script>
......
<li class="product_li">your product title</li>
And in your target php file you check for the cookie. Remember, that this cookie can be set to anything, so never ever trust user data. Test and filter it in order to make sure your code is not compromised. I don't know what you want to do with this data.
$_COOKIE['li_click_data'];
3.) Finally, as the best approach, you should look at your current code, and see if there is something you can re-engineer. Here's a quick example.
You could do the following in php to save an array of the values in the session on each page load, and then get that value provided you have some kind of id or other usable identifier for your items:
// for list_items.php
foreach($item as $i) {
// Do what you normally do, but also set an array in the session.
// Presuming you have an id or some other means (here as item_id), to identify
// an item, then you can also access this array on the item_details -page.
$_SESSION['mystic_item_data_array'][$i['item_id]] = $i['thedata'];
}
// For item_details.php
$item_id = // whatever means you use to identify items, get that id.
$data_you_need = $_SESSION['mystic_item_data_array'][$item_id];
Finally.
All above ways are usable for small data like previous page, filters, keys and similar.
Basically, 1 and 2 (client-side) should only be used, if the data is actually generated client-side. If you have it in PHP already, then process it in php as well.
If your intention is to store actual html, then just regenerate that again on the other page and use one of the above ways to store the small data in case you need that.
I hope this gets you going and at least thinking of how to solve your project. Good luck!

Session is not a struct?

The error I get is this:
Element USER is undefined in a Java object of type class [Ljava.lang.String;
The lines of code I get this error are when I do anything like this:
SESSION.user.functionName()
It's randomly and I assume is happening after the user's session is expired. My problem is first of all, isn't the SESSION scope always a structure? How/Why does ColdFusion think it's a string.
Regardless, my main problem is I am using CFWheels. All my controllers extend the main Controller.cfc of course and all my controllers (except the public one) filter through a checkLogin function. That function has this in it:
<cfif !structKeyExists(session, "user")>
<cfif !structKeyExists(params,'layout') || params.layout EQ true>
<cfset redirectTo(route="home",error="You must be logged in to continue.") />
<cfelse>
<cfset flashInsert(error="You session has expired and you must login to continue. <a href=''>Reload the Page</a> to login.") />
<cfset redirectTo(controller="Shared",action="ajaxError") />
</cfif>
</cfif>
In this part of the function, I explicitly check if user exists in the session and if it doesn't one way or the other I'm sending them somewhere else. How on earth does the code get past this part to then fail when the session is somehow a string?
Not to mention there are various other places before I get to the error line where I'm making sure various things in the SESSION.user object are correct.
What was happening was on ajax requests. Some ajax requests load reports and such that can take several seconds to query, especially before some caching takes place. If a user executes an ajax call and then logs out, technically the request could make it through all my permission checking to get to the controller (it takes just milliseconds) but in the controller while fetching data from the models the user is logged out.
Then by the time the view is ready to load, the Session is cleared. If I use anything from the session scope there, it errors out.
I think I'll fix this by adding a filter that runs after the controller action to check if the session scope is still there. If it's not I'll just abort the request. I don't have model logic in any of my views, but I sometimes reference methods in the SESSION.user scope. Probably not purist MVC.
On the cases where the logout happens before parts of the controller are complete, I'll just let those errors happen as they may and ignore them, knowing the user really isn't seeing it happen.

How do I use continuations in FubuMVC

https://github.com/adymitruk/fubumvc/commit/083e1d593d4e797ac04fb493acd1e29a332cd303?w=1
It seems returning a continuation breaks the binding to the view. It used to work before I added the continuation. Now I get a blank page for the default view.
You're using the same input model for your get and your post, so when you transfer, you get into an endless loop. I'm surprised you don't get a stackoverflow. There must be some checking in FubuContinuation that breaks the loop.
You're using the input model as the view model which you (generally) shouldn't do.
Your form tag needs to be a
Also, it looks like due to the naming of your models and the folders, the default view conventions weren't matching up views to your actions. To get things working, I threw them all in the same folder (bad, I know).
You'll want to sort out the folders and namespaces before doing anything serious with this.
Here's the pull request which I was able to get working and posting and such:
https://github.com/adymitruk/fubumvc/pull/1

querying info from an existing dojo.itemfilereadstore

I'll start off by mentioning I'm a dojo noob. That said,
I'm having trouble reading data from a itemfilereadstore. When my page is loaded, I perform a .fetch() on a itemfilereadstore. The ajax call retrieves some data from the server and my onComplete handler is executed. My problem is after this store is populated (and after my onComplete handler is executed), I don't see a way to read its contents (enumerate its items) again without hitting the server.
How can I fetch() against this existing datastore without it trying to hit my webserver again? Surely I can look up information that already exists in this object somehow? The dojo documentation doesn't seem to have any obvious answers, what am I missing?
I believe what you're looking for is itemfilereadstore.query. If all you need is to get all the elements, just a plain old query should do the trick. If you need to filter, then you'll have to read up on the query syntax : http://dojotoolkit.org/reference-guide/dojo/data/ItemFileReadStore.html#query-syntax

What might be causing this IllegalStateException discrepancy in JSP/Spring?

I had a JSP file with a c:redirect tag that would forward along a user to another page.
<!-- Yes, I know this loop is probably unnecessary, but I'm not fluent in jsp and have determined it is not the problem. :) -->
<c:if test="${cmd.numberOfResults == 1}">
<c:forEach items="${cmd.matches}" var="someVar">
<c:redirect url="/loadThatResultInfo.html"/>
</c:forEach>
</c:if>
The old implementation of the command object is needs updating (where I come in). The way I'm doing so is by creating a generic "search result" object which contains an instance of that old object (for now). I get that instance through a property in that generic class, so my code is now this:
<c:if test="${cmd.genericSearchObject.numberOfResults == 1}">
<c:forEach items="${cmd.genericSearchObject.matches}" var="acct">
<jsp:forward page="/loadThatResultInfo.html"/> <!-- new try! -->
<c:redirect url="/loadThatResultInfo.html"/> <!-- old try... -->
<% response.sendRedirect("/loadThatResultInfo.html"); %> <! new try! -->
</c:forEach>
</c:if>
Each of those three tries all result in IllegalStateExceptions of some sort. Why does this change cause the exception, especially considering that the lines involved -- the redirect, not the changed/bound class instances -- are causing the problem?
Back-end changes were made accordingly, referencing the property within my new encompassing "generic" class to satisfy the old functionality. I know this works because all related functionality, beside what I'm writing about, works.
Research online indicates:
- I can't redirect/forward after a submission has already been submitted. Then how was I able to do it before?
- Attempt to flush an already-cleared buffer causes this. What changed that makes it cleared now as opposed to the older (first) implementation?
- The size of the page's buffer needs to be bigger. THIS is one I don't understand and would really love for the stackoverflow community to address; I can see my new class causing size changes that would need changes to be dealt with.
------- ANOTHER ANSWER! -------
First and foremost, ALWAYS SET UP THE SITUATION IN THE CODE as described by the marked answer. However... if you're stuck and don't want to do that, here's a quick fix: javascript!
<script type="text/javascript">
location='./yourPageToGoTo.html'
</script>
JSP is part of the response. You're attempting to change the response destination in a JSP instead of in a controller. If you do this halfway in a JSP, then it's too late, because the HTTP response headers may already have been sent (the response is then in committed state). This is a point of no return and an illegal state for changing the response. It's too late then. Any attempt will result in the servletcontainer to throw IllegalStateException: response already committed.
To fix this, you need to put this piece code in the very top of JSP file and pray that the response hasn't already been committed at that point (which will usually happen after writing about 2KB of data to the response, depending on the servletcontainer config). However, JSP is still the wrong place for the job, you should rather do this in the controller, before forwarding the response to the JSP (or to instruct from within the model the controller somehow to do the job, when you're using a MVC framework).

Resources