bennadel
Community Beginner
bennadel
Community Beginner
Activity
‎Mar 16, 2022
02:37 AM
1 Upvote
This may be a silly question, but I believe that null support is a setting you have to enable. Did you enable it? If so, is it enabled at the server level? Or, in the `Application.cfc`?
... View more
‎Mar 15, 2022
02:43 AM
1 Upvote
Adding to my list of things to read. My "big goal" for 2022 is to learn how to deploy something with Docker!
... View more
‎Mar 14, 2022
07:19 AM
Hmmmm, that's an interesting thought. Let me think on that one.
... View more
‎Mar 14, 2022
06:26 AM
There's no doubt that it's odd !! Honestly, I don't quite understanding what is happening at the low-level. All I can tell you is that it works. Meaning, when the `CFQuery` tag throws an error in the `onApplicationStart()` when the datasource isn't defined, then calling `applicationStop()` in the `onError()` seems to fix the issue (or, at least allows the next request to re-start the application). This whole thing is really frustrating. Especially since it's to hard to reproduce. I had to restart CF like 15-times in a row before it finally started in a wonky state. Then, I had to edit the `Application.cfc` file in production (adding in the `applicationStop()` stuff) to see if it worked. Before I put the `applicationStop()` line in place, I made some other non-important updates to the `Application.cfc` to make sure that "touching the file" wasn't what was fixing it. But, it wasn't. Editing the App.cfc didn't change the corrupted state of the app until I added in the `applicationStop()` line. Then it fixed. If this is also a bug - that `applicationStop()` works at this point - then it's like I'm using one bug to cancel out another bug 😆
... View more
‎Mar 14, 2022
05:45 AM
The "nothing special here" part is all static - nothing there is dynamic, nothing is based on env variables. It's the same on every single request. As far as returning `true` from the `onApplicationStart()`, that is documented as being optional. From the Adobe site: > A Boolean value: True if the application startup code ran successfully; False, otherwise. You do not need to explicitly return a True value if you omit the cffunction tag returntype attribute. If I need to return `true` in order for datasources to work, then this would also be a bug in the ColdFusion runtime. As far as whey I consider the `isBootstrapped` flag to indicate that the application is bootstrapped, I think we're just splitting semantic hairs. What I mean is that my application startup logic has all executed without error. And since I'm preloading data in the startup logic, it means that the datasource worked, which is really all I want to validate here. If I get to the `onError()` event-handler and the flag isn't set, it means that something went wrong during my startup logic, and the application is not in a "known good state" (again, from my logic perspective, not necessarily from CF's perspective). I could check to see if the `eventName` argument in the `onError()` method signature is "onApplicationStart" ... but that seems less explicit to my intention. As far as not doing something like this in production, I suppose it depends on how your production works. For example, if you were deploying with Docker containers, none of this would even matter since the "healthcheck" on the container would never pass and the container would be killed. In my case, I'm just FTPing files to my VPS, so there's nothing orchestrating the health of the server except me 😄
... View more
‎Mar 13, 2022
11:07 AM
Ok, I think I finally came up with a solution that works! I got rid of the whole time-stamp / cache invalidation issue. Now, I'm setting an `isBootstrapped` flagged at the end of the `onApplicationStart()` method. And then, in the `onError()` method, if that flag is not set - meaning, an error was thrown before the application could be bootstrapped, I then call `applicationStop()`. The next request appears to then re-start the ColdFusion application, bringing it into a valid state. An appreciated version: component
output = false
hint = "I define the application settings and event handlers."
{
// Define application settings.
this.name = "WwwBenNadelCom";
this.applicationTimeout = createTimeSpan( 2, 0, 0, 0 );
this.sessionManagement = false;
this.setClientCookies = false;
this.config = getConfigSettings();
// Define the datasources and default datasource.
// --
this.datasources = {
"bennadel": {
username: this.config.dsn.username,
password: this.config.dsn.password,
driver: "MySQL",
class: "com.mysql.jdbc.Driver",
// .... nothing special here ....
}
};
this.datasource = "bennadel";
// ---
// LIFE-CYCLE METHODS.
// ---
/**
* I get called once when the application is being bootstrapped. This method is
* inherently single-threaded by the ColdFusion application server.
*/
public void function onApplicationStart() {
// .... truncated initialization for demo ....
// .... truncated initialization for demo ....
// .... truncated initialization for demo ....
// As the very last step in the initialization process, we want to flag that the
// application has been fully bootstrapped. This way, we can test the state of the
// application in the onError() event handler.
application.isBootstrapped = true;
}
/**
* I handle uncaught errors within the application.
*/
public void function onError( required any exception ) {
// If the bootstrapping flag is null, it means that the application failed to
// fully initialize. However, we can't be sure where in the process the error
// occurred, so we want to just stop the application and let the next inbound
// request re-trigger the application start-up.
if ( isNull( application.isBootstrapped ) ) {
cfheader( statusCode = 503, statusText = "Service Unavailable" );
writeOutput( "<h1> Service Unavailable </h1>" );
writeOutput( "<p> Please try back in a few minutes. </p>" );
try {
applicationStop();
} catch ( any stopError ) {
// Swallow error, let next request start application.
}
return;
}
// .... truncated for demo ....
}
} The next request to the app then seems to boot the app into a valid state. I'm still convinced that this is a ColdFusion bug. In order to test this, I had to restart my ColdFusion service about 15-times before it actually started in an invalid state. And, I had a maintenance page up, so I was the only one making requests against the app (the maintenance page aborts before the app even has a name defined).
... View more
‎Mar 13, 2022
04:35 AM
This is _mostly_ working. The application bootstrapps now; however, I am sometimes seeing an issue in the bootstrapping process where ColdFusion complains that the connection pool isn't defined and I get a Null Pointer Exception during the SQL execution. Still working at it.
... View more
‎Mar 12, 2022
05:42 AM
Ok, I think I may have found a super hacky solution. Earier in this thread, I discovered that if I simply "touch" any value in the `this.datastructures`, some internal magical cache appears to get flushed and the application will bootstrap properly. This got me thinking about possibly doing this "touch" programmatically. What I've done now is include a timestamp when my config is cached in memory: private struct function getConfigSettings( boolean useCacheConfig = true ) {
var configName = "appConfig_#this.name#";
if ( useCacheConfig && server.keyExists( configName ) ) {
return( server[ configName ] );
}
var config = server[ configName ] = deserializeJson( PATH_TO_CONFIG_FILE );
// HACK: I'm having trouble with my "this.datasources" configuration bombing-out
// on server-start for reasons that I don't understand. Through trial-and-error,
// I've discovered that "touching" that structure fixes this issue. As such, I'm
// going to see if this date/time-stamp can act as a "touch" on that value.
config.loadedAt = getTickCount();
return( config );
} As you can see, I'm injecting a `.loadedAt` property when this is cached in the `server` scope. Then, in my `this.datasources` struct, I now have: this.datasources = {
"bennadel": {
username: this.config.dsn.username,
password: this.config.dsn.password,
driver: "MySQL",
class: "com.mysql.jdbc.Driver",
// ...... truncated .......
// HACK: For reasons that I don't understand at all (and what is looking very
// much like a bug in ColdFusion), the datasources configuration occasionally
// bombs-out when the service-start up for the first time. But, I've
// discovered that simply "touching" this structure (ie, changing any property
// in it) appears to fix the problem (maybe by flushing some sort of cache).
// As such, I'm going to see if including a timestamp will act as a "touch".
// This timestamp is when the config object was cached. And, since it's cache
// whenever the onApplicationStart() method runs, if the application fails to
// bootstrap, the next request will get a newer timestamp.
_loaded_at_: this.config.loadedAt
}
};
this.datasource = "bennadel"; Once I had this code in place, I started restarting the ColdFusion service. After about 7 restarts, I finally was able to reproduce the "datasource cannot be found error." However, unlike in previous tests, where this bad state _persisted_ indefinitely, I found that the next page request lead to a working application. I'm presuming this is befcause the next request triggered a new `onApplicationStart()` call, which in turn, reloaded the config, which in turn lead to a new `config.loadedAt` date/time stamp. It seems this new timestamp was enough to "touch" the structure, which cleared whatever crazy caching is going on. This is nuts!!! But, it seems to work 🤞
... View more
‎Mar 12, 2022
04:04 AM
Ok, I've spent the last hour-and-a-half restarting my live site and trying to add debugging. What a pain. It only actually breaks like 1 out of every 10 CF restarts. So, here's what I did: First, I wrapped my `this.datasources` definition in a try/catch and logged any error using `cflog()`. There were no errors to be found in this block of code, even when the application was having trouble bootstrapping. I added this to the top of my `onError()` handler: writeDump( getApplicationMetadata().datasource );
writeDump( getApplicationMetadata().datasources.keyList() );
writeDump( exception );
abort; And, when the application got into a bad state, here's what it showed me: Note that both the `this.datasource` and `this.datasources` properties are correctly defined within `getApplicationMetadata()`. Just bananas!!
... View more
‎Mar 11, 2022
05:43 AM
I thought the point of `this.datasource` was to define which datasource should be used _by default_ in the queries. Meaning, my `<cfquery>` tags do **not** have a `datasource` attribute. They are like: <cfquery name="test">
SELECT 1;
</cfquery> I _believe_ it's the `this.datasource` that allows this to work. If I were to _just_ use the `this.datasources` **struct**, how would ColdFusion know which datasource to use in the `<cfquery>` tag?
... View more
‎Mar 11, 2022
05:35 AM
I had started to `dump` some data in the `onApplicationStart()`, and I noticed that all calls to the site were hitting this line of code, which is why I concluded that the app had not been bootstrapped and that ACF as implicitly calling this, attempting to bootstrap the app over and over (it never succesfully completes). I'll keep experimenting over the weekend. It's hard to test because the problem doesn't happen locally; and, it doesn't happen every time I spin-up the service 😄 Such a crazy problem!
... View more
‎Mar 11, 2022
05:33 AM
I did try the `writeDump( new Application() )` test and wasn't able to get anything to error. But, later today, I'll try to wrap the `this.datasources` config in a try/catch and see if I can find any error information.
... View more
‎Mar 11, 2022
05:30 AM
It's not even getting as far as the return statement. I am doing some data pre-loading inside the `onApplicationStart()` event, which is breaking because it can't find the datasource. So, the entirety of the `onApplicationStart()` method isn't even executing, let alone returning.
... View more
‎Mar 11, 2022
05:29 AM
Interesting. I assumed that the `this.datasources` would need to be defined first since it contains the definition for the value that is then in the `this.datasource`: this.datasources = { "bennadel": { ... } };
this.datasource = "bennadel"; But, I can try to flip them and see if it makes a difference.
... View more
‎Mar 11, 2022
03:45 AM
I tried creating an isolated test-case for this locally, where I define `this.datasources` inside the `onApplicationStart()` function. Definitely does _not_ work. But, when I move it into the pseudo-constructor, it works. Unless I'm missing something subtle, I don't think you can define any of the per-app settings anywhere other than the pseudo-constructor.
... View more
‎Mar 11, 2022
03:26 AM
Ok, so I just tried one more thing. I restarted the ColdFusion service, and the datasource bombed-out. Then, all I did was update a value in the `this.datasources` - I changed `interval: 420` to `interval: 421`, re-uploaded my `Application.cfc` and the site immediately came online. To be clear, it has nothing to do with `interval`. I tried it a few more times, changing _different_ properties, and everytime I "touch" the `this.datasources` structure, the site immediately bootstraps and comes online. It's like an invalid version of the datasource is getting cached and then ColdFusion re-caches it if any of the keys change.
... View more
‎Mar 11, 2022
03:12 AM
Oh also, I tried copying the `this.datasources` and `this.datasource` configuration to inside the `onApplicationStart()` function - this made no difference. I'm pretty sure you _can't_ define that stuff there.
... View more
‎Mar 11, 2022
03:11 AM
So, to be clear, no error is being thrown in the _pseudo constructor_. The `this.` data structures are all in tact and have the right data. It's getting to the `onApplicationStart()` method correctly. It just can't seem to find the datasource.
... View more
‎Mar 11, 2022
03:09 AM
Ok, so I just restarted the server and the datasource bombed-out again. Here's what I discovered: It is never making it past the `onApplicationStart()` method because I have some query-operations being triggered inside that function (preloading some in-memory structures from the DB). Meaning, once it gets in this state, every request is calling the `onApplicationStart()` method. If I dumped-out the `getApplicationMetadata()` inside the `onApplicationStart()`, it shows _all the data_ that I expected, including the default `datasource` and the `datasources` configuration. If I comment-out the data-pre-loading inside the `onApplicationStart()`, the application bootstraps. But then it errored due to missing pre-loaded data. BUT, if I then put this in the `onRequestStart()` code: ``` applicationStop(); location( url = cgi.script_name ); ``` ... in order to restart the application and refresh the page, then **everything starts up fine**. This is just so strange.
... View more
‎Mar 10, 2022
12:10 PM
There's nothing wrapping the setting of the datasource. It's the darndest thing.
... View more
‎Mar 10, 2022
10:35 AM
Hey all! 👋 so, the datasource that I'm defining is in the `Application.cfc` pseudo-constructor - basically right after I setup the name, mappings, serialization key-casing, etc. It was my understanding that this kind of stuff _had_ to be done in the pseudo-constructor; but, maybe that understanding it outdated? It sounds like @Mark Takata is saying that I can do it inside of `onApplicationStart()`. If that's true, this is news to me. @Charlie Arehart good idea with the `getApplicationMetadata()` test. It's a bit tricky, this since this _only_ happens in production and I don't want everyone to suddenly get a dump of my app configuration values 🤣 but, I can probalby put it in some separate template and maybe even sanitize the password just in case. I'll do that stuff and report back. Also, I'll try to hang-out in the forum more.
... View more
‎Mar 10, 2022
04:03 AM
I'm running into a rather strange issue and I don't know how to debug it. I'm using a per-application datasource feature in the `Application.cfc`: this.datasources[ "bennadel" ] = { .... } And, when I restart the ColdFusion service is sometimes says that the datasource cannot be found. This "state" seems to hold for the entire life of the application, and all requests coming into the application are breaking. But then, if I restart the ColdFusion service again, it works fine (probably). I'm kind of stumped here - not sure how to even go about debugging this.
... View more