As my application has grown, I've noticed that I am reusing a lot of database queries across multiple webpages.
At the moment I have done it using a .CFM file which has many <cfstoredproc> tags that gets included on every page that needs database data. All I am doing is wrapping these stored procedure executions in a <cfif> tag which tests what the name of the calling page is and then executes the appropriate <cfstoredproc> block of code.
I am no expert in anything, but this doesn't feel right to me. I just don't know how to manage all my database queries correctly so that they can be shared across any CFM page in the entire website. For example, one page might need the "GetUsers" stored procedure and another page might need "GetOrders".
I'm just about to embark on creating a CFC which holds every separate <cfstoredproc> or <cfquery> in its own method/function. E.g.:
<cfcomponent name="DBQueries" hint="Everything for DB retrieval">
<cffunction name="GetUsers" returntype="query">
<cfstoredproc procedure="GetUsers">
<cfprocresult name="rsUsers">
</cfstoredproc>
<cfreturn rsUsers>
</cffunction>
.....
<cffunction name="DBQuery100">
<cfstoredproc procedure="GetSomething" returntype="query">
<cfprocresult name="rsSomething">
</cfstoredproc>
<cfreturn rsSomething>
</cffunction>
</cfcomponent>
Then on a main .CFM page I will invoke the component and method required to return the data. Is this a good way to achieve DB query management?
The fact that it's database related is not as relevant as the fact that you have code repetition. You are on the right track in your effort to make the code more re-useable.
If you put your queries into a cfc, you might consider taking this one step further. Instead of invoking it all the time, use the onApplicationStart method of your Application.cfc to create an application variable that's available to all users on all pages.
Another approach is to put all these database tags into a .cfm file and to put a cfinclude in the onRequestStart method of your Application.cfc.
Both methods work. And, as is almost always the case when you compare two things, each has advantages over the other.
Consider the following two db tables
User
UserID PrimaryKey
firstname
lastname
Security
SecurityID PrimaryKey
UserID ForeignKey
Permission
All database tables have Create, Read, Update, Delete operations (CRUD)
CRUD operations can exist in several places
Inside of <cfquery> tags
Inside of Stored procedures
Others
The thing is all the CRUD operations belong together in their own way. Consider making a User object (user.cfc).
<cfcomponent>
<cffunction name="create"></cffunction>
<cffunction name="read"></cffunction>
<cffunction name="update"></cffunction>
<cffunction name="delete"></cffunction>
</cfcomponent>
Security is a part of user management, so is the object a one to one match to the db table? In some environments like ORM the answer is yes, in others not.
If you consider security to be a part of user managment, your user.cfc might look like this
<cfcomponent>
<cffunction name="create"></cffunction>
<cffunction name="read" hint="Read will also read security info"></cffunction>
<cffunction name="update" hint="Perhaps this can update security too"></cffunction>
<cffunction name="delete" hint="Delete will also delete security info"></cffunction>
<cffunction name="create_security"></cffunction>
<cffunction name="read_secrity" hint="This may not even be needed"></cffunction>
<cffunction name="update_security"></cffunction>
<cffunction name="delete_security" hint="This may not even be needed"></cffunction>
</cfcomponent>
At the end of the day you may find that you need far fewer objects (*.cfcs) than tables.
OK, now you have you user.cfc what do you do with it? It can be attached to you the rest of your app in various different ways
application.User = new user();
session.User = new user();
request.User = new user();
Each one of these is very from the next. Before we go down the road of which is appropriate, we have to consider member data, and how long we want it around.
<cfcomponent>
<cfset this.userid = ""><!--- This always points to the user I want to interact with --->
<cffunction name="create"></cffunction>
<cffunction name="read"></cffunction>
<cffunction name="update"></cffunction>
<cffunction name="delete"></cffunction>
</cfcomponent>
It is likely that your CRUD operations are going to interact with the same UserID for all their operations. You may find that after you update a record, you will often read it. Rather than always stating which UserID you are interacting with, you may just want to set it up once, and have all the functions just use the same one.
OK, now let's get back over to where you will be using them
application.User
Only one User object will exist in the the whole system. It will be created when the request comes in onthe site. This object will be shared for every request. If you attach your user object here, that suggests that all requests will be looking at the same user.
session.User
One User object will exist for a given end-user in the outside world. It will separated from all other end-users. This suggests that each end user will be looking at their own user AND that even as they click around the site, they will still be looking at the same user
request.User
One User object will exist per request. It will only exist for a particular request, and then be discarded. This suggests that looking at at particular User is meaningful on this request, but the next may be quite different, or maybe not even about users.
~~~~~~~~~~~~~~~
At the end of the day, you will need to decide how to bundle your DB interactions, and how long you will keep those bundled action together
I would have a model per table.
in there you have every query that ever does anything to that table
Lets say the Users table
Users.cfc
would have all the methods which return queries
getUsers - return alll users
getUserById - could be a paramater on the first function also.
Then when you need to work out where something in orders is being updated there is only one place to look.
I get the results like this
<cfset users = new model.Users().getUsers() />
or I use script
users = new model.Users().getUsers();
And if your really brave, try doing all the queries in script also.
One last thing to consider, if the data isn't changing, cache the query.
Things like OrderType or similar, you will get a lot of performance benefit rather than repeating the query over and over.
Related
I'm calling a web service through ColdFusion which returns an object, and I want to verify if one of the methods of this object exists as it won't always exist.
I found this source which seemed promising however based on my tests I can see the results are always negative and the method is never found when it's clearly there.
<cfif structKeyExists("#Result.getNotifications().getValidationResult(0)#","getField")>
Result is my underlying object, and my end goal is to verify if the method getField() exists.
Is there a clean way to do this as opposed to a try/catch?
Update:
Unfortunately, I am not sure IsInstanceOf() works with web services, due to the fact that CF uses a Proxy object to "wrap" the underlying web service class. If not, another simple option is to check class name. That avoids the ambiguity of checking for method name only (which could potentially exist in many different classes). Plus I suspect it may be more light-weight than IsInstanceOf() anyway.
<cfif compare(yourObject.getClass().name, "org.tempuri.ValidationResultField") eq 0>
Found ValidationResultField. do something
</cfif>
It looks like the dump contains several different types of objects/classes: ArrayOfValidationResult, ValidationResultField, etecetera. It sounds like what you are really trying to determine is which of those classes you are working with, so you know exactly what fields and methods will be available, per the web service definitions. Given that, I think IsInstanceOf() would be a more appropriate test, than checking for method names. More accurate as well. Nothing prevents two different classes from having the same method name. So even if method X or Y exists, there is still a possibility it may be a different class than expected.
<cfif IsInstanceOf(yourObject, "org.tempuri.ValidationResultField")>
do something
</cfif>
As far as I know, the mentioned structKeyExists approach only works if CF wraps the class internally, e.g. all instances of cfcomponent.
The only option left is to actually reflect the class:
<cftry>
<cfset Result.getNotifications().getValidationResult(0).getClass().getMethod("getField", javaCast("null", ""))>
<!--- method does exist --->
<cfcatch type="coldfusion.runtime.CfJspPage$UnsupportedBaseTypeException">
<!--- method does not exist --->
</cfcatch>
</cftry>
If the method doesn't exist, it throws UnsupportedBaseTypeException, which seems to be a follow-up of NoSuchMethodException.
Honestly, you might as well just invoke the method and catch it. Reflection comes with an additional overhead and you have to catch it anyway.
Like Miguel-F, I think this is something for getMetadata(). The following should return an array containing the respective functions of the object:
<cfset funcs = getmetadata(nameOfObj).functions>
The names of the functions are then funcs[1].name, funcs[2].name, and so on.
In general, you may obtain the metadata of all the functions of a webservice, given the URL of the WSDL, with something like
<cfhttp method="get" url="http://www.webservicex.net/globalweather.asmx?WSDL" result="res">
<cfset wsXml=xmlparse(res.filecontent)>
<cfset wsOperations = xmlsearch(wsXml,"//wsdl:operation")>
<cfdump var="#wsOperations#">
Another method you could look at (perhaps undocumented) is to get the method names from the class names in the stubs directory.
The code to run is:
<cfscript>
wsargs = structnew();
wsargs.savejava="yes";
</cfscript>
<cfset convert=createobject("webservice","url_of_wsdl",wsargs)>
Then figure out how to fish out the names from the stubs directory, {CF_INSTALL}/stubs. In my case, CF_INSTALL is C:/ColdFusion2016/cfusion/
I have a “best-practices” question in regards to the correct way to instance CFCs that all need to talk to each other in a given project.
Let’s say for example you have a web application that has a bunch of different modules in it:
Online Calendar
Online Store
Blog
File Manager (uploading/downloading/processing files)
User Accounts
Each of these modules is nicely organized so that the functions that pertain to each module are contained within separate CFC files:
Calendar.cfc
Store.cfc
Blog.cfc
Files.cfc
Users.cfc
Each CFC contains functions appropriate for that particular module. For example, the Users.cfc contains functions pertaining to logging users on/off, updating account info etc…
Sometimes a CFC might need to reference a function in another CFC, for example, if the store (Store.cfc) needs to get information from a customer (Users.cfc). However, I'm not sure of the correct way to accomplish this. There are a couple ways that I've been playing with to allow my CFC's to reference each other:
Method 1: Within a CFC, instance the other CFC’s that you’re going to need:
<!--- Store.cfc --->
<cfcomponent>
<!--- instance all the CFC’s we will need here --->
<cfset usersCFC = CreateObject("component","users") />
<cfset filesCFC = CreateObject("component","files") />
<cffunction name="storeAction">
<cfset var customerInfo = usersCFC.getUser(1) />
This approach seems to work most of the time unless some of the instanced CFC’s also instance the CFC’s that instance them. For example: If Users.cfc instances Files.cfc and Files.cfc also instances Users.cfc. I’ve run into problems with occasional dreaded NULL NULL errors with this probably because of some type of infinite recursion issue.
Method 2: Instance any needed CFCs inside a CFC’s function scope (this seems to prevent the recursion issues):
<!--- Store.cfc --->
<cfcomponent>
<cffunction name="storeAction">
<!--- create a struct to keep all this function’s variables --->
<cfset var local = structNew() />
<!--- instance all the CFC’s we will need here --->
<cfset local.usersCFC = CreateObject("component","users") />
<cfset local.filesCFC = CreateObject("component","files") />
<cfset var customerInfo = local.usersCFC.getUser(1) />
My concern with this approach is that it may not be as efficient in terms of memory and processing efficiency because you wind up instancing the same CFC’s multiple times for each function that needs it. However it does solve the problem from method 1 of infinite recursion by isolating the CFCs to their respective function scopes.
One thing I thought of based on things I've seen online and articles on object oriented programming is to take advantage of a “Base.cfc” which uses the “extends” property of the cfcompontent tag to instance all of the CFC's in the application. However, I've never tested this type of setup before and I'm not sure if this is the ideal way to allow all my CFCs to talk to each other especially since I believe using extends overwrites functions if any of them share a common function name (e.g. "init()").
<!--- Base.cfc --->
<cfcomponent extends="calendar store blog users files">
What is the correct "best-practices" method for solving this type of problem?
If each of your CFC instances are intended to be singletons (i.e. you only need one instance of it in your application), then you definitely want to looking into Dependancy Injection. There are three main Dependancy Injection frameworks for CF; ColdSpring, WireBox and DI/1.
I'd suggest you look at DI/1 or WireBox as ColdSpring hasn't been updated for a while.
The wiki page for DI/1 is here:
https://github.com/framework-one/di1/wiki/Getting-Started-with-Inject-One
Wirebox wiki page is here:
http://wiki.coldbox.org/wiki/WireBox.cfm
Essentially what these frameworks do is to create (instantiate) your CFCs (beans) and then handles the dependancies they have on each other. So when you need to get your instantiated CFC it's already wired up and ready to go.
Dependancy Injection is also sometimes called IoC (inversion of control) and is a common design pattern used in many languages.
Hope that helps and good luck!
If your cfcs not related to each other the base.cfc concept does not fit. The inheritance is for classes have common things that can inherit from each other. For example if you have User.cfc and you want to added new cfc called customer.cfc I would inherit from User and override some functionality or add some without touching the actual user.cfc.
So, back to your question, since the CFC are not related or have common between each other and to avoid cross referencing, I will create serviceFactory holds instances of cfcs like this
component name="ServiceFactory"
{
function init(){
return this;
}
public User function getUserService(){
return new User();
}
public Calendar function getCalendar(){
return new Calendar();
}
}
and referencing it by
serviceFactory= new ServiceFactory();
userService = serviceFactory.getUserService();
Keep in mind this approach works only if you have sort of another CFC to manage your logic
you can do the same for all other services. If your functions are static you can save your services in application scope and instantiate it only one time (like singleton).
The third option you have is DI(dependency Injection) framework
We currently use CF8 and don't have access to any ORM functionality. However, I'm hoping someone out there can give me any tips on how to create all my crud actions more quickly than we are doing them right now.
Right now we create a cfc with the functions we need for each new component, hardcoded all the db field names into each function which feels like it takes forever to do.
Unfortunately the bosses wont allow us to use anything like CFWheels and we are forever creating each function manually.
I'm not looking for the scripts to self create based on what's in the DB, just a quicker way of creating the necessary crud actions for any script we write.
Below is a basic function we write for all out apps.. So I'm hoping someone out there can give me some pointers on creating all these things much more quickly.
<cfcomponent extends="master.cfc">
<cffunction name="users" access="public" returntype="query">
<cfargument name="dsn" type="string" required="yes">
<cfargument name="id" type="numeric" required="yes">
<cfquery name="get_users" datasource="#arguments.dsn#">
SELECT ID,firstname,lastname,email
FROM users
WHERE ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.id#">
</cfquery>
<cfreturn get_users >
</cffunction>
</cfcomponent>
I prefer DataMgr for CRUD. It is compatible with many CF versions and database engines. It automatically applies cfqueryparam, too.
Example query using DatMgr:
<cfset get_users = Application.DataMgr.getRecords("users", {id: arguments.id})>
This doesn't replace your CFC, but it might save you same typing. I've found it especially helpful for insert and update actions.
Have you tried CFBuilder?
Use Adobe CFC Generator (in ColdFusion Builder 2.0) -> Create CFC
http://help.adobe.com/en_US/ColdFusionBuilder/2.0/Using/WS0ef8c004658c1089-1b4fc34c122964e1318-8000.html
I have not used Woodi, but I used Illudium PU-36 Code Generator # http://cfcgenerator.riaforge.org/ back in the CF7/8 days and it worked well.
At first glance, what I feel is you need a code generator. Try Woodi.
Also,
Say if you a table called 'user', create two components.
user.cfc
w_user.cfc
user extends w_user. This way, always put your code generator code in 'w_user' and any customization in code in the 'user'. So, your MODEL object will be just the 'user.cfc'.
Ex: Getting User records
let the function be named as 'get_users()'. This can be generated with Woodi. So, the code should be in w_user cfc.
While you may have a case where you need some filter on it. Lets call it get_userWithFilter(). This will be in the 'user'. Now, You can be referring to the 'get_users()' function from inside this function.
If you have no filters needed, then you can directly call the get_users() function from 'user.cfc' (available by inheritance).
I have written a gateway to get a result set from my database. How do i store every row in a separate dao so that i can manipulate every record further? Or can i access the result set directly to get the records?
This is my Gateway (btw, should i write the conditional logic within the cfquery into a seperate cfc that extends this one?)
<cfcomponent name="MaterialDao" hint="data access object" output="false">
<cffunction name="init" hint="constructor" access="public" output="false" returntype="MaterialDao">
<cfargument name="dsn" type="String" required="true" hint="datasource" />
<cfset variables.instance.dsn = arguments.dsn />
<cfreturn this />
</cffunction>
<cffunction name="readMaterial" hint="read" access="public" output="false" returntype="Query">
<cfargument name="district" type="String" />
<cfset var qReadMaterial = "" />
<cfquery name="qReadMaterial" datasource="#variables.instance.dsn#">
<cfif StructKeyExists(arguments,"district")>
SELECT A.NR, A.BEZ, D.BES, D.STA
<cfelse>
SELECT A.NR, A.BEZ
</cfif>
FROM DEK AS D INNER JOIN ART AS A
ON D.NR = A.NR
WHERE 0=0
<cfif StructKeyExists(arguments,"district")>
AND D.BEZ = #arguments.district#
</cfif>
ORDER BY A.BEZ
</cfquery>
<cfreturn qReadMaterial />
</cffunction>
</cfcomponent>
I have already read a lot of articles and it seems that there are different opinions about this matter (DAO vs. Gateway, DAO & Gateway etc.). What is the best practice, what do the pros do?
The pros use just one pattern for the database access layer. The use of both a DAO and Gateway is a misnomer that I'm not really sure where it got started, but seems to only exist in the ColdFusion crowd. The DAO and Gateway patterns can pretty much serve the same function, but I think the DAO fits the bill more when talking about database interaction.
DAOs should include functionality for CRUD methods plus returning sets of records. Since CRUD and basic sets of records is highly repetitive, I use a code generator to create the code for this interaction and then customize what I need. This is a good place for conditional logic for selecting the records you need.
As Aaron mentioned, returning an array of objects for a set of records in your database is unfeasible in ColdFusion due the the performance overhead of creating objects. I typically just use the basic query returned from the DAO in my views. However, if the thing I'm modeling needs some behavior in a view, then I will put the query in an object using something similar to what Peter Bell does.
Peter Bell had a great presentation some months ago on his release of the Iterating Business Object CFC which allows you to take multiple records and iterate over one record at a time using this simple framework: http://ibo.riaforge.org/. Until CF is a little faster at generating objects, recycling a single instance of an object and repopulating the properties is likely your best best. Perhaps this can help you load one record at a time into your DAO.
Conditional logic can go in the Gateway or in a Manager CFC. Typically, I would include logic that is simple like the logic outlined in your post directly in the CFC.
A bit of advice, you may wish to make the arguments.distinct NOT required and do a simple check with if (structKeyExists(arguments, "distinct") ) { do something }.
Regards,
-Aaron Greenlee
At our company we thought long and hard about this stuff for a few months, trying the Adobe CF DAO creator via RDS and some other older ones (anyone remember CFPowerTools?).
We decided in the end to write our own DAO code generator and I thought I'd share our thoughts here. The reason we decided was because we needed to add locking hints to out SQL, we wanted to make it more efficient, more secure and cleaner.
The setup we decided on was to create a pre-defined base DAO object (called DAO.cfc) which all generated 'table' DAOs extended. All it had was a few utility methods, but the key thing thing is we can add any other functions in there that we need all our generated DAOs to have access to.
So we auto-generate code by selecting a table from the database (using the CF admin API) and create the [TableName].cfc DAO with the usual init, setters and getters, so the basic CRUD stuff.
In addition to this, we also generate a [TableName]GatewayBase.cfc and a [TableName]Gateway.cfc. [TableName]Gateway.cfc extends [TableName]GatewayBase.cfc.
So for a sample DAO run on a table called 'Customers', the files created are:
Customers.cfc /* extends DAO.cfc [not created, already exists] */
CustomersGateway.cfc
CustomersGatewayBase.cfc /* extends CustomersGateway */
So, the idea is that the gateway provides a way to deal with many 'Customer' records - the DAO is used when dealing with one and only one. All methods in the gateway will generally return a CF query object. CF is too inefficient to create massive arrays of DAO objects and in our mind the query object in CF is really flexible, so we're happy to use it.
When coding, the sub-class CustomerGateway.cfc is the only one instantiated and used. However, the base class it extends has some very useful generic functions that come for free, such as getFieldListByProperty() which based on passed parameters will return certain fields (i.e. table columns) by a certain property (i.e. a column value), so for example:
myGateway.getFieldListByProperty(property="status", value="1", fieldList="customerName,customerID", orderBy="createdOn") />
That call will return the 'customerName' and 'customerID' values for all customers with a status of 1, ordered by the date they were created on. The code is also hardened against SQL injection and validated so sensible exceptions are thrown.
This function will provide 99% (we hope!) of the multi-record querying you do on a table. If you need a more sophisiticated query then the CustomerGateway.cfc is there for you to add functions to.
Finally, we allow you add functions to CustomerGateway CFC only because if you change the customers table (say add a column), you will need to recreate the table, and tha will overwrite the Customers.cfc and the CustomersGatewayBase.cfc. However, your custom code (if any) is safe in the sub-class.
Anyway, this might be slightly off topic, but sure I thought someone might find our experience useful.
Been going over my predecessor's code and see usage of the "request" scope frequently. What is the appropriate usage of this scope?
There are several scopes that are available to any portion of your code: Session, Client, Cookie, Application, and Request. Some are inadvisable to use in certain ways (i.e. using Request or Application scope inside your Custom Tags or CFC's; this is coupling, violates encapsulation principles, and is considered a bad practice), and some have special purposes: Cookie is persisted on the client machine as physical cookies, and Session scoped variables are user-specific and expire with the user's session on the website.
If a variable is extremely unlikely to change (constant for all intents and purposes) and can simply be initialized on application startup and never written again, generally you should put it into Application scope because this persists it between every user and every session. When properly implemented it is written once and read N times.
A proper implementation of Application variables in Application.cfm might look like this:
<cfif not structKeyExists(application, "dsn")>
<cflock scope="application" type="exclusive" timeout="30">
<cfif not structKeyExists(application, "dsn")>
<cfset application.dsn = "MyDSN" />
<cfset foo = "bar" />
<cfset x = 5 />
</cfif>
</cflock>
</cfif>
Note that the existence of the variable in the application scope is checked before and after the lock, so that if two users create a race condition at application startup, only one of them will end up setting the application variables.
The benefit of this approach is that it won't constantly refresh these stored variables on every request, wasting the user's time and the server's processing cycles. The trade-off is that it is a little verbose and complex.
This was greatly simplified with the addition of Application.cfc. Now, you can specify which variables are created on application startup and don't have to worry about locking and checking for existence and all of that fun stuff:
<cfcomponent>
<cfset this.name = "myApplicationName" />
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.dsn = "MyDSN" />
<cfset foo = "bar" />
<cfset x = 5 />
<cfreturn true />
</cffunction>
</cfcomponent>
For more information on Application.cfc including all of the various special functions available and every little detail about what and how to use it, I recommend this post on Raymond Camden's blog.
To summarize, request scope is available everywhere in your code, but that doesn't necessarily make it "right" to use it everywhere. Chances are that your predecessor was using it to break encapsulation, and that can be cumbersome to refactor out. You may be best off leaving it as-is, but understanding which scope is the best tool for the job will definitely make your future code better.
This is a very subjective question, and some would even argue that it is never "appropriate" to use the request scope in modern ColdFusion applications.
With that disclaimer out of the way, let's define what the request scope is and where it would be useful.
The request scope is the absolute global scope in a single ColdFusion page request. It is not a shared scope, like application, server, client, and session scopes, so locking is not necessary to make it threadsafe (unless you spawn worker threads from a single request using CF8's CFTHREAD tag). As a global scope, it is a very convenient way to persist variables through any level in the request's stack without having to pass them from parent to caller. This was a very common way to persist variables through nested or recursive Custom Tags in older CF apps.
Note that while many applications use this scope to store application-level variables (configuration settings, for example), the big (and sometimes subtle) difference between the request scope and the application scope is that the value of the same request-scoped variable can differ between individual page requests.
I would guess that your predecessor used this scope as a means to conveniently set variables that needed to survive the jump between encapsulated or nested units of code without having to pass them around explicitly.
Okay, I just wanted to comment on your code. Please forgive me if I seem crazy. But you already verified that the structKeyExists in the beginning. Since you know it's going to be true, it wouldn't make sense to run another check. So my version of it would be this... But thats just me.
<cfif not structKeyExists(application, "dsn")>
<cflock scope="application" type="exclusive" timeout="30">
<cfset application.dsn = "MyDSN" />
<cfset foo = "bar" />
<cfset x = 5 />
</cflock>
</cfif>
Alright.
I've been writing my company's framework that will be used to power our site.
I use the request variable to set certain data that would be available to the other CFC's I had to do this so the data would be available throughout the application, without the need to continually pass in the data. I honestly believe that using request , and application as long as its a static function component then you should not have a problem. I'm not sure if I am wrong in my thinking with this but once I release the framework we will see.