1

I'm on a shared linux server and I only have access to http://domain.com/~username/ which maps to ~/public_html.

I would like to use the Taffy framework for ColdFusion in this context. As far as I can tell, to use the framework you must have an Application.cfc that extends the Taffy framework component taffy.core.api.

https://github.com/atuttle/Taffy

https://github.com/atuttle/Taffy/wiki/Installing-Taffy

https://github.com/atuttle/Taffy/wiki/So-you-want-to:-Create-a-dead-simple-CRUD-API

The only directories I have access to are not sub-directories of the web root and therefore (as I understand it) not subsets of the ColdFusion path.

In my particular case I neither have access to CFADMIN nor are the server admins going to install a component I need to extend in a system-wide context where it is already on the path and accessible via global dot notation.

The instructions say you should unzip the taffy folder into your web root, and if you can't do that, you should make it a subfolder of your api. The former is not a possibility for me and when I do the latter I get "Could not find the ColdFusion Component or Interface taffy.core.api."

More Detail: My api is at http://domain.com/~username/api/, so I unzipped /taffy to ~/public_html/api/. If I copy the Taffy example at taffy/examples/api to ~/public_html/api so that going to http://domain.com/~username/api/ should access the example, I get "Could not find the ColdFusion Component or Interface taffy.core.api" even if have taffy/core/api.cfc beneath that directory (~/public_html/api).

On this server I have successfully made cfc's that extend a cfc in another directory using <cfset THIS.mappings["/subdir"]= getDirectoryFromPath(getCurrentTemplatePath()) & "subdir/"> and <cfobject name="parentObj" component="subdir.parent">.

I have also successfully made an Application.cfc that extends a cfc in the same directory.

I just haven't successfully made an Application.cfc that can extend a cfc in another directory, even if it's a subdirectory.

I did try to use grep & related tools to strip every reference of "taffy.core" out of Taffy's source code so I could just dump all the taffy cfc's into my root directory along with Application.cfc so I could extend api.cfc, but I got different errors and didn't pursue that hacky solution any further.

<cfdump var=#expandPath('/mapping')# /> outputs /var/www/html/mapping.

uname@domain $>ls -la /var/www/html
drwxr-xr-x  3 root   root 4096 Sep 16 00:34 .
drwxr-xr-x  7 root   root 4096 May 28  2012 ..
lrwxrwxrwx  1 root   root   19 Sep 16 00:34 cfide -> /var/www/html/CFIDE
drwxrwxr-x 10 apache root 4096 Sep 16 00:32 CFIDE

~/public_html/api/resources/successesCollection.cfc:

<cfcomponent extends="taffy.core.resource" taffy_uri="/successes">
    <cffunction name="get" access="public" output="false">
        <cfreturn representationOf('success').withStatus(200) />
    </cffunction>
</cfcomponent>

~/public_html/api/Application.cfc:

<cfcomponent extends="taffy.core.api">

<!--- doesn't work
<cfset THIS.mappings["/taffy"]= getDirectoryFromPath(getCurrentTemplatePath()) & "taffy/">
<cfset THIS.mappings["/core"]= getDirectoryFromPath(getCurrentTemplatePath()) & "taffy/core/">
--->

        <cfscript>
                this.name = hash(getCurrentTemplatePath());

                // do your onApplicationStart stuff here
                function applicationStartEvent(){}

                // do your onRequestStart stuff here
                function requestStartEvent(){}

                // this function is called after the request has been parsed and all request details are known
                function onTaffyRequest(verb, cfc, requestArguments, mimeExt){
                        // this would be a good place for you to check API key validity and other non-resource-specific validation
                        return true;
                }

                // called when taffy is initializing or when a reload is requested
                function configureTaffy(){
                        setDebugKey("debug");
                        setReloadKey("reload");
                        setReloadPassword("true");

                        // Usage of this function is entirely optional. You may omit it if you want to use the default representation class.
                        // Change this to a custom class to change the default for the entire API instead of overriding for every individual response.
                        setDefaultRepresentationClass("taffy.core.genericRepresentation");
                }
        </cfscript>
</cfcomponent>

Output of http://domain.com/~uname/api/index.cfm/successes/: Could not find the ColdFusion Component or Interface taffy.core.api.

Adding this to my Application.cfc doesn't fix the issue:

<cfcomponent extends="taffy.core.api">
        <cfscript>
                this.name = hash(getCurrentTemplatePath());
                this.mappings = StructNew();
                this.mappings['/taffy'] =
                expandPath('./taffy');

In addition, adding the following to ~/public_html/api/Application.cfc doesn't fix the issue either:

<cfset this.mappings["/taffy"] =
expandPath(getDirectoryFromPath(getCurrentTemplatePath()) & "taffy")>

Check out the following sequence of commands and let me know if I've overlooked something. I'm still left with "Could not find the ColdFusion Component or Interface taffy.core.api" upon browsing to "http://domain/~uname/api".

[uname@domain ~]$ cd ~/public_html

[uname@domain ~/public_html]$ rm -rf api

[uname@domain ~/public_html/api]$ wget -O taffy.zip https://github.com/atuttle/Taffy/zipball/master

[uname@domain ~/public_html/api]$ unzip taffy.zip

[uname@domain ~/public_html/api]$ mv atuttle-Taffy-35df54e/ taffy

[uname@domain ~/public_html/api]$ mv taffy/examples/api .

[uname@domain ~/public_html/api]$ mv taffy api/

[uname@domain ~/public_html/api]$ tree -d ~/public_html/api/
~/public_html/api/
|-- resources
`-- taffy
    |-- bonus
    |-- core
    |-- examples
    |   |-- ParentApplication
    |   |   |-- config
    |   |   |-- mixin
 ... etc

[uname@domain ~/public_html/api]$ ls -la ~/public_html/api/
total 8
drwxr-xr-x  4 uname ugroup 1024 Dec  9 11:00 .
drwxr-xr-x 10 uname web     1024 Dec  9 10:57 ..
-rw-r--r--  1 uname ugroup 1188 Dec  9 11:00 Application.cfc
-rw-r--r--  1 uname ugroup  172 Sep 20 13:04 .htaccess
-rw-r--r--  1 uname ugroup  218 Sep 20 13:04 index.cfm
drwxr-xr-x  2 uname ugroup 1024 Sep 20 13:04 resources
drwxr-xr-x  8 uname ugroup 1024 Sep 20 13:04 taffy

[uname@domain ~/public_html/api]$ ls -la ~/public_html/api/taffy/
total 15
drwxr-xr-x  8 uname ugroup 1024 Sep 20 13:04 .
drwxr-xr-x  4 uname ugroup 1024 Dec  9 11:00 ..
drwxr-xr-x  2 uname ugroup   96 Sep 20 13:04 bonus
-rw-r--r--  1 uname ugroup 4096 Sep 20 13:04 build.xml
drwxr-xr-x  2 uname ugroup 1024 Sep 20 13:04 core
drwxr-xr-x 15 uname ugroup 1024 Dec  9 10:57 examples
-rw-r--r--  1 uname ugroup   99 Sep 20 13:04 .gitignore
drwxr-xr-x  2 uname ugroup   96 Sep 20 13:04 lib
-rw-r--r--  1 uname ugroup 1356 Sep 20 13:04 LICENSE.TXT
-rw-r--r--  1 uname ugroup 2490 Sep 20 13:04 ReadMe.md
drwxr-xr-x  3 uname ugroup   96 Sep 20 13:04 snippets
drwxr-xr-x  5 uname ugroup 1024 Sep 20 13:04 tests

[uname@domain ~/public_html/api]$ ls -la ~/public_html/api/taffy/core/
total 72
drwxr-xr-x 2 uname ugroup  1024 Sep 20 13:04 .
drwxr-xr-x 8 uname ugroup  1024 Sep 20 13:04 ..
-rw-r--r-- 1 uname ugroup 42382 Sep 20 13:04 api.cfc
-rw-r--r-- 1 uname ugroup  4574 Sep 20 13:04 baseRepresentation.cfc
-rw-r--r-- 1 uname ugroup  2572 Sep 20 13:04 dashboard.cfm
-rw-r--r-- 1 uname ugroup  1756 Sep 20 13:04 dashboard.css
-rw-r--r-- 1 uname ugroup  4538 Sep 20 13:04 docs.cfm
-rw-r--r-- 1 uname ugroup  3030 Sep 20 13:04 factory.cfc
-rw-r--r-- 1 uname ugroup   179 Sep 20 13:04 genericRepresentation.cfc
-rw-r--r-- 1 uname ugroup  3516 Sep 20 13:04 mocker.cfm
-rw-r--r-- 1 uname ugroup   389 Sep 20 13:04 nativeJsonRepresentation.cfc
-rw-r--r-- 1 uname ugroup  3765 Sep 20 13:04 resource.cfc
Myer
  • 3,670
  • 2
  • 39
  • 51
  • Sounds like you need to create a mapping. Since you're on a shared host, you'll probably need to do it in Application.cfc - i.e. `This.Mappings = {'/taffy':'/path/to/taffy'}` – Peter Boughton Dec 08 '12 at 20:26
  • Correct me if I'm wrong, but according to some googling that requires Per Application Settings to be checked in an admin panel that I don't have access to - how do I know if this is enabled? – Myer Dec 09 '12 at 08:54
  • 1
    Do `` - this will either evaluate to where the mapping points (i.e. working), or look for a file/dir mapping in your root dir (i.e. not working). If not turned on, I'd definitely ask the host to fix it - can't think of any reason they wouldn't. – Peter Boughton Dec 09 '12 at 12:47

2 Answers2

3

You do have a couple of options.

Mapping (per-application or otherwise)

As Taffy is a development framework, your sysadmin/host may be willing to install it in a central location for all developers to make use of. They could put the Taffy folder in the web root, or create a server-level mapping to wherever the folder may be.

Relative Path

It should be possible to run Taffy from a relative path. It sounds like this is the approach you're trying to take, but you may not have the files in the right locations.

In order to use relative paths, you need a directory structure that resembles:

~uname/api/

~uname/api/taffy/core/api.cfc        <- Framework contents
~uname/api/taffy/core/factory.cfc
~uname/api/taffy/core/dashboard.cfm
~uname/api/taffy/core/...
~uname/api/taffy/...

~uname/api/Application.cfc           <- your api code
~uname/api/index.cfm
~uname/api/resources                 <- where you put your resource CFC's

It sounds like you're missing the "taffy" folder and either put the CFC's directly in your api folder or put the "core" folder in your api folder.

The "taffy" folder is required. Think of the dot-notation path you're putting in your Application.cfc's extends attribute as a filesystem path. Since it's taffy.core.api then your filesystem needs to contain taffy/core/api.cfc.

Adam Tuttle
  • 19,505
  • 17
  • 80
  • 113
  • Adam - thanks for your response. I believe I have things set up as you indicated - please see the sequence of commands I included in my post to demonstrate this. Is there something else that I haven't thought of? – Myer Dec 09 '12 at 15:41
  • Since you're on linux, Case matters. Make sure the folder isn't named "Taffy", it should be "taffy". – Adam Tuttle Dec 09 '12 at 16:10
  • It's really hard to understand your commands without the directory structure. Can you explain what `~/api` is? Is it supposed to be different from `~/public_html/api`? – Adam Tuttle Dec 09 '12 at 16:15
  • I cleaned up the commands and added the output of tree and ls -la. ~/api was a miscopying error; it was supposed to be ~/public_html/api. – Myer Dec 09 '12 at 17:13
  • I can't seem to get this work work, even when I have taffy/core/api.cfc inside ~/public_html/api, even when I have in ~/public_html/api/Application.cfc – Myer Dec 09 '12 at 18:34
  • Could it have something to do with this? I'm on CF8. http://www.modernsignal.com/coldfusion_cfc_inheritance_bug – Myer Dec 09 '12 at 18:47
  • The blog post you linked either has a typo, or represents a couple of significant bugs. I'm guessing the former, as that bug would not likely have lived this long -- it would affect too many people too severely. I added you as a contact on G+, maybe we can do some screen sharing over a G+ Hangout to try and figure out what's wrong? – Adam Tuttle Dec 09 '12 at 22:49
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20867/discussion-between-peter-nore-and-adam-tuttle) – Myer Dec 10 '12 at 08:12
  • According to this stackoverflow post(http://stackoverflow.com/a/7814823/78202), "your Application.cfc can't extend a CFC in a mapped folder." Is there a way to use Taffy as an object? cfset application.myComponent = new taffy.core.api()? – Myer Dec 12 '12 at 17:44
  • Your Application.cfc most certainly CAN extend a CFC in a mapped folder, but NOT an application-specific mapping (this.mappings)... it has to be a server-wide mapping for that to work. It is not possible to use Taffy as an object like you're proposing. – Adam Tuttle Dec 12 '12 at 18:13
  • If I don't have access to server-wide mappings, does that mean I can't use taffy? – Myer Dec 13 '12 at 09:59
  • In general, no, you should still be able to use Taffy. I've had success using the subfolder approach we've been trying to get working here, and I know others who have as well. – Adam Tuttle Dec 13 '12 at 12:57
2

Have you tried using a relative path proxy, as Ben Nadel explains here: http://www.bennadel.com/blog/2115-Extending-The-Application-cfc-ColdFusion-Framework-Component-With-A-Relative-Path-Proxy.htm

The idea is that your application.cfc would extend a local proxy (rootProxy.cfc) that resides in the same directory. That proxy then cfincludes the cfc you are interested in. Since cfinclude takes a relative path, you needn't worry about global dot notation or mappings.

jasperjohnny
  • 121
  • 1
  • 2
  • Basically, app/Application.cfc extended TaffyProxy, and api/TaffyProxy.cfc had one line: – Myer Dec 13 '12 at 17:29