I’m just testing out the whole blogging from IMified Interface. It looks like it has a lot of promise.
Tag: ColdFusion
I was asked today:
Could someone please explain the differences between cfc package and public access? I thought that package access made the method available to other templates within the same application, but that doesn’t seem to be the case.
Now, I remember being confused by this when I first started doing CFC’s so figured I would share.
A function with an access of “package” will be restricted to calling CFC’s and templates in the same directory as the CFC file of the function.
In my personal experience, I haven’t found access=package to be terribly useful. I tend to organize my files into subfolders like cfc, and then further subdivide by type of CFC. (Gateway, DAO, utility.) So to access them, I tend to put functions as either public or private. All in all, “package” just makes it harder to work with all of this stuff.
However, I have the luxury of working on private server, and not a hosting provider for the majority of my work, so my view maybe atypical. Anybody have a different viewpoint?
My wife, Janice, and I work for the same company. In fact we work for the same boss. It has its ups and downs. But if we didn’t work together, situations like these would never happen:
Janice was working on a Perl script that handles integrating Active Directory and MajorDomo. It was buggy and confusing and overall not well written. Janice was struggling with the parts that were crappy, basically trying to grok the ungrokable, and she calls me over.
Janice: Can you tell me what this section of code does:
## Im not really sure why I did this. It works so back off! my $max = $mesg->count; for($i = 0 ; $i < $max ; $i++) { my $entry = $mesg->entry($i); foreach my $attr ($entry->attributes) { $dn=$entry->get_value($attr) } }
Me: No.
Janice: Why not?
Me: I didn’t understand it when I wrote it. What makes you think I understand it now?
You see, I’ve worked for our current department on and off for the past 6 years. My first past through the group was doing Exchange and Windows Domain systems administration. I managed the upgrade from NT4 to Windows 2000 and Active Directory. I wrote the first batches of code that we used to integrate Active Directory and our legacy systems. That meant Perl. I learned it sort by accident back in the day, and at my height of ability I was never one of those guys who would write twenty lines of function in one line.
Which brings us back to this section of code; I wrote it in my first Active Directory LDAP Perl to CSO script. It was copy and pasted by another developer, and reused again. Until my wife had to deal with it… six years after I wrote it.
Sorry, hon.
I’ve been meaning to blog about <cfntauthenticate> for awhile, but I keep forgetting. However, someone had an issue with it today, and it spurred me on.
Disclaimer
I don’t work for Adobe, so I have no idea why they did anything they did. Any supposition posted here is just that my supposition. Additionally, it’s not meant as criticism, as for the most part <cfntauthenticate> does exactly what it is supposed to do.
We’re a Window shop that relies heavily on out Active Directory Domain. We use it for LDAP mail routing, Exchange, and single sign on across our environment. From time to time we’ve had issues with <cfntauthenticate> under certain outlier conditions. Let me take you through some of them.
Too Many Groups
Occasionally, we’ll run in to singular users that cannot log into some applications but can log in to others. We’ll tease out variations in form inputs, and ensure the username and password works, and still can’t figure it out. We’ll look at our logs that track the reason for failure, and we’ll see “UserNotInDirFailure.” Even turning on the throwError option of the tag doesn’t help.
Eventually we trace it back to the listGroups flag. Turn it off, it succeeds, turn it on, it fails. So it’s something with the groups. Try taking some groups away from the user. Voila it stops failing.
Turns out, there is some number, N, of groups over which some sort of uncaught error will start to be thrown. It gets caught by the default error code and gets thrown as “UserNotInDirFailure.” N is a little nebulous, as it is unclear to me what effects domain local groups versus global groups versus distribution groups has on N. But in my last set of tests, N was 23.
To workaround, if you aren’t using groups, don’t use listGroups, as you don’t need it. If you are using groups for let’s say, authorization, revert to using LDAP for retrieving groups information. Also you could just prune your group membership…
Service Account Issues
This is the one that happened today. Every user’s login was returning “UserNotInDirFailure,” but only for a particular server. No changes in underlying networking were made.
My default recommendation: restart the server. When the admin of that server did that the ColdFusion service didn’t start. A quick check of the system logs showed that the login for the account the ColdFusion service was running under was failing. Turns out someone changed the password of it and didn’t change it in the services configuration on the server. It took about 36 hours before the problem was noticed.
According to the documentation, “ColdFusion must run as a user that has the privilege to authenticate other users in the specified domain.” So problems with the service account would cause problems with the tag.
No workaround here, just manage your service accounts properly.
PDC emulator
Active Directory domain controllers are intended to be redundant. Except for something called Flexible Single Master Operations roles, or FSMO roles. Each FSMO role makes the domain controller that hosts it unique in a fashion. I’m not going to go into all of it, but suffice it to say one of those FSMO’s is “PDC Emulator.” PDC stands for Primary Domain Controller, and was a feature of NT 4 and below. Basically the PDC was the domain controller to which domain information was read from and written to. Other domain controllers only allowed read operations. When Microsoft moved to Active Directory and multiple domain controller model, they left the PDC Emulator role in order to provide backward compatibility with tools that used NT 4 API’s for various operations.
What does all this have to do with ColdFusion? It’s my theory that <cfntauthenticate> uses the vestigial NT 4 API’s. I base this theory on the fact that if your PDC emulator is inaccessible, <cfntauthenticate> will fail for all users. However, if you have throwError set to false, you won’t know what is going on you’ll get a “UserNotInDirFailure” error. However, if you set throwError to true, you will see the real message, “Could not find domain controller for this domain XXXX” Where XXXX is the name of your domain.
There’s not much you can do about this. If the PDC emulator is unreachable from your Coldfusion server, <cfntauthenticate> will not work. The only solution I have come up with to replace <cfntauthenticate> with an analogous CFC that uses Secure LDAP queries against the domain controller instead.
Conclusion
I blogged this because when I’ve gone looking for <cfntauthenticate> errors, I’ve only found my own random posts on CF-talk. Hopefully, someone else will be less mystified by errors with this very useful tag.
I’m not talking about being unemotional about code, which would be “objectively”. No, “objectly,” I’m talking about code generation. When I first started writing Squidhead, I was writing procedural code to generate my code. After all, it’s tempting to think of it procedurally, as code tends to read from top to bottom. One of the breakthroughs for me was figuring out that most of the coding structures I was using can be expressed as objects. I mean the actual code text itself can be expressed as objects. In ColdFusion, this means a CFC.
Let me show you an example of what I’m talking about:
<!—************************************************—>
<!—create—>
<!—This function inserts a single comment record into the database.—>
<!—************************************************—>
<cffunction
access=“public”
name=“create”
output=“FALSE”
returntype=“numeric”
hint=“This function inserts a single comment record into the database.”
>
<cfargument
name=“body”
type=“string”
required=“FALSE”
default=“”
/>
<cfargument
name=“authorID”
type=“numeric”
required=“FALSE”
default=“0”
/>
<cfargument
name=“createdBy”
type=“numeric”
required=“FALSE”
default=“0”
/>
<cfargument
name=“updatedBy”
type=“numeric”
required=“FALSE”
default=“0”
/>
<cfset
var commentID = “”
/>
<cfset
var results = “”
/>
<cfstoredproc
procedure=“usp_comment_insert”
datasource=“#application.datasource#”
username=“#application.dbusername#”
password=“#application.dbpassword#”>
<cfprocparam
type=“OUT”
cfsqltype=“CF_SQL_INTEGER”
variable=“commentID”
dbvarname=“@commentID”
maxlength=“4”
null=“NO”
/>
<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_LONGVARCHAR”
variable=“body”
dbvarname=“@body”
value=“#arguments.body#”
maxlength=“16”
null=“NO”
/>
<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“authorID”
dbvarname=“@authorID”
value=“#arguments.authorID#”
maxlength=“4”
null=“NO”
/>
<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“createdBy”
dbvarname=“@createdBy”
value=“#arguments.createdBy#”
maxlength=“4”
null=“NO”
/>
<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“updatedBy”
dbvarname=“@updatedBy”
value=“#arguments.updatedBy#”
maxlength=“4”
null=“NO”
/>
<cfprocresult
name=“results”
/>
</cfstoredproc>
<cfset results = commentID />
<cfreturn results />
</cffunction>
This is a basic insert function. We’ve all written this type of function as part of a CFC.
Let’s break this down into its properties:
|
Documentation |
<!—********************************—> <!—create—> <!—This function inserts a single comment record into the database.—> <!—********************************—> |
|
Header |
<cffunction |
|
Arguments |
<cfargument |
|
<cfargument |
|
|
<cfargument |
|
|
<cfargument |
|
|
Local Variables |
<cfset |
|
<cfset |
|
|
Content |
<cfstoredproc <cfprocparam <cfprocparam <cfprocparam <cfprocparam <cfprocparam <cfprocresult </cfstoredproc> <cfset results = commentID /> |
|
Results |
<cfset results = commentID /> |
|
Footer |
</cffunction> |
Once you’ve established the structure of the CFC, you make these properties into variables. Anything that could be a list is actually an array. So arguments and local variables are actually an array of <cfargument> declarations, as is local variables. You write getter and setters. Actually I tend to write adders instead of setters as I’m just adding content to properties that grow. The getter that I write just concatenates all of the code and outputs it.
Here’s the code:
You can even break it down even further. If you wanted, each <cfargument> could be an object with each attribute being a property. I didn’t go that far in Squidhead, but I did break the <cfstoredproc> declaration into an CFC.
This works very well for highly structured code, like <cfcomponents>’s , <cffunction>’s and <cfstoredproc>’s but it can be extended into less obviously structured code like custom tags. I was able to convert most of my procedural code creators to object oriented code creators.
So for whatever that’s worth, maybe this can help someone else out there.
I know, I know, we don’t need another framework post. But the latest posts from Sean Corfield, Brian Rinaldi, and Jake Munson make me want to speak up. While I’m naming dropping, I feel the need to cite Joel Spolsky’s In Defense of Not-Invented-Here Syndrome.
I am not against frameworks. I’ve tried coding against a couple. I’ve at least looked at most of them. I don’t currently use one. The one I got the furthest with was Model Glue 2. I like it a lot, but I’m just not productive enough in it yet to rely on it. That means that I can accept that Joe Rinehart came up with a better solution to my problems than I, but I can’t use them as productively, as I can use my own, perhaps flawed solutions.
It’s that bit of logic that I think should be the key to using frameworks. Use them where they will be more productive than your own efforts.
Follow what I mean here.
Let’s say you are a database wiz. You design textbook perfect databases in your sleep. You love seeing execution plans with no table scans. You think it’s cool when your queries have to use parallelism. It would not be in your best interest to use a database framework like Reactor. Why? Because you would be substituting Doug Hughes‘ judgment for your own, where you provide the most value.
Well that’s not quite true, because you don’t exercise the full extent of your knowledge on every single piece of SQL interaction code you write. If Reactor makes 80% of what you do take 20% of the time it used to, then it still might be worth it to use, and then manage the exceptional cases.
Okay, I haven’t convinced you – you still prefer the way you deal with your database to the way Reactor does. Okay, but you’re still probably doing a lot of repetitive, rule based code like writing <cfstoredproc> code blocks with are more characters the actual SQL stored procedures you’ve written. Perhaps you should write your own code generator. That’s essentially what I did with Squidhead, and it was easier than I thought, and a great experience for me.
Okay, database wiz, now it comes to the UI. You need to do an Ajax front end. What do you do? Start writing JavaScript? No! You told us you were a database wiz. If you’re not a JavaScript wiz then stop and download an Ajax framework. Because at some point someone has better judgment than you about some of the technology you use.
Now I started with a database guy, but I could have started with an Ajax wiz, or a designer and the advice would have been analogous.
If your expertise is based on a certain set of skills, you would be nuts to accept someone else’s judgment for yours. But if you’re not an expert in an area, that it is equally nuts to assume your judgment is better than an expert.
Pick frameworks and techniques that strengthen your weak spots.
One of the requests I’ve gotten for Squidhead is a MySQL version. Being the responsible Open Source author (or wanting to suck up to the people that are actually interested in it,) I tried to make it work with MySQL 5.0.
It did not go well. Specifically, I cannot call MySQL stored procedures from ColdFusion using <cfstoredproc>. (I get a null error from indexOfIgnoreCaseRespectQuotes in the MySQL driver.) It isn’t an absolute deal breaker, but makes my job much, much harder. I have to branch off more than just the database interaction. I would also have to branch off the CFC code too. (Which is much more complicated than the database stuff.)
So now I’m stuck at a quandary:
- Do I do the work to get it to interact with MySQL at Squidhead’s present level of features? OR
- Do I start adding features to Squidhead, along just the MSSQL path, and go back later and add MySQL support for the whole thing?
Part of my original logic behind doing it in MS SQL only, was that the problem I was trying to solve with Squidhead was DBA mandates of “You must use stored procedures!” My gut feeling was that this type of mandate was more likely to found in a shop with a more established database. I’m not knocking MySQL here, but stored procedures were just introduced in version 5.0, and a lot of shops don’t run it yet. Therefore less shops would mandate stored procedures with MySQL. So it would be smarter to go after an Oracle version than a MySQL version.
Then there are the features that I would like to add.
- I would like to remove the requirement identities. (I would do CRUD against Primary Keys.)
- I would like to add support for configuration metadata for things like “ORDER BY.”
- I would like to decouple the custom tags from the data retrieval cfc methods.
Does anyone out there with either an interest in Squidhead, or experience with an open source product have any advice?
This is the third time I’ve tried to switch to CFEclipse. It looks like this time it might stick.
My big problem with CFEclipse to date is that it has been incompatible with the way I have worked. I tend to work on many small projects, each with its own network share. In Dreamweaver each of my sites point to the UNC address of the project’s share. CFEclipse does not seem to handle files over UNC path’s directly. From the little bit of information I have been able to find, it looks like a problem with Eclipse, not CFEclipse specifically. It works just fine with mapped drives, but I have many projects, each with their own share, and that’s a lot of mapped drives.
Now, one of the guys I work with, newly minted MXNA blogger Dave Konopka, pointed out that I could just map the root of my web server. I have the ability to do so, because I have elevated privileges on my ColdFusion servers, seeing as how I built them. Now I’ve always viewed this as abusing my administrative rights since not all of our developers have these rights. I try to consume the services we provide as the rest of the developers here do, because 1, there’s usually a good reason for doing things the way we do, and 2. It helps me spot . However, come to think of it, the whole reason that I have a whole bunch of smaller projects is because I am an administrator. So maybe it’s not really cheating to do it this way.
Anyway, I’m over that hurtle, I’ve got a whole bunch of projects assigned, I’ve integrated Source Safe, and giving it an honest try.
What I like:
I like Snippets, especially after Mark’s tutorial. I like default code folding. I love Control+Shift+D (<cfdump> for those that haven’t used it). I love how much faster it is than Dreamweaver, especially working remotely. I love that the component explorer allows me to drop a fully written <cfinvoke> set down. (Well technically so does Dreamweaver, but CFEclipse does it much faster.)
What Surprised Me:
I’ve gone ANT crazy. It’s not really within the scope of CFEclipse, but now that I get ANT, I love it. It’s so much easier to run build tasks now.
What I don’t like:
I still wish the aforementioned difficulties with UNC paths weren’t there. Other than a few “I’m used to doing a different way” problems that are just learning curve issue, I only have one other concrete issue. I wish I could color the background of comments to the bright yellow I’ve gotten used to in Dreamweaver. (I know, it’s coming. )
I think between the speed, the integration with ANT, and the general direction of the community, I might stick with CFEclipse this time around.
A question popped up on CF-Talk today about adding users to an Exchange Distribution list using <CFLdap>. I figured I would share my solution in case it could help anyone else.
The easiest way to do this is to add the user to the list of members of the group, as opposed to adding the group to the user. (I’m not 100% sure, but I think that you technically can’t add a group membership to the user.) You also need to do all modifications to ldap objects through their distinguished names, not their username, group name or as Microsoft likes to call it, “samAccountName.”
So you find out the distinguished name for the user, the distinguished name for the group, then add the user to the group. The code for doing so is in the extended version.
Update: My initial attempt to post this code caused my server to barf. Evidently my code displayer didn’t like it. So I’m just linking to it.
You want people to find every problem with your code and publicly point them out? I’m not talking about code reviews again; I’m talking about releasing Squidhead as Open Source on RIAForge. I haven’t been this panicked about updates for awhile.
Not that I’m complaining. Every comment has been a move towards making it a better product, but I was unprepared for it. I missed a whole bunch of dumb things. (Dumb that I missed them, not that people want them.)
Thanks to everyone that downloaded it, and everyone who commented. I’ve made pretty much every recommendation, and fixed every bug report to date. With one exception that is. I haven’t made any movement on a MySQL version. I want to get it to work right in MS SQL before switching to another database. Good news is that errors are being found at a good clip.