This shouldn't be too hard to answer, but the discussions and documentation I've found can be rather unclear.
First of all, a little bit of information about my setup:
I'm on a hosted environment, and going through our ColdFusion admin group can be time-consuming. Therefore, I'm using the
restInitApplication function to register my RESTful web service.
My webroot folder (where my Application.cfm is located) is in
"E:\docs\wwwroot". I can only see, add, edit folders/files from
wwwroot down. I have no idea what's in "e:\docs". I believe that up
above where I cannot see there is another Application.cfm that sets
such things as the serverType (development, staging, or production),
that we (and other ColdFusion sites hosted on this server) use in
various places in our application code.
My pdfRestfulAPI.cfc (the component containing my webservice function) is in this folder,
"e:\docs\wwwroot\RESTservices". My component code looks like this:
<cfcomponent rest="true" >
<cffunction name="pdfconvert" access="remote" returntype="binary"
output="false" produces="application/xml" method="get" >
<cfargument name="sourceWebPageURL" type="string" >
<cfset pdfDoc = "" >
<cfdocument name="pdfDoc"
format="PDF"
src="#sourceWebPageURL#"
saveAsName="sample.pdf" >
</cfdocument>
<cfreturn #pdfDoc#>
</cffunction>
</cfcomponent>
The function itself is not an issue. It just converts a web page to pdf--pass a URL, get a PDF version of that web page. When I set it up as non-RESTful API (SOAP/xml) it works just fine.
In my Application.cfm, I am attempting to register my web service using the following code:
<cfset restInitApplication( getDirectoryFromPath(getCurrentTemplatePath())
& "RESTservices" ) >
This gives me a dir_path attribute of "E:\docs\wwwroot\RESTservices", which seems correct to me. I've omitted the optional mapping_name attribute. When the documentation says that this "can be anything", that is not helpful.
The error that I get in my Application.cfm reads:
coldfusion.rest.RestAppAdapter$InvalidApplicationException: No mapping
found for path E:\docs\wwwroot\RESTservices
Hopefully, I've laid out the details in such a way that anyone could try this out and let me know what I'm doing wrong.
Thanks, everyone!
Related
We have created a CFX customer tag and a jar file. The jar files are in coldfusion server ../WEB-INF/lib. It processed successfully for years. Recently we are going to upgrade to coldfusion11 linux. For the maintenance concerns, the system admin prefer to move out these library files from server WEB-INF/lib to application local directory.
Here is the code for setting the localpath for coldfusion 10.
Application.cfc
<cfcomponent>
<cfscript>
//this.name = hash( getCurrentTemplatePath() ); // unique app name
this.javaSettings = {
loadPaths: [
"/opt/WebRoot-DEV/afsapps/tp-web-apps/payroll/process/java/lib"
],
loadColdFusionClassPath: true,
reloadOnChange: true,
watchInterval: 100,
watchExtensions = "jar,class"
};
</cfscript>
<cffunction name="OnRequestStart" returnType="void">
<cfargument name="targetPage" type="string" required="true" />
<!--- Include Application.cfm --->
<cfinclude template="Application.cfm" />
</cffunction>
</cfcomponent>
But it doesn't work, could find the jar file. I got this error message:
"The error message is "The CFX custom tag CFX_GenerateGarnishmentDocuments was not found in the custom tag database. You must add custom tags to the database before using them. If you have added your tag to the database, check the spelling of the tag within your template to ensure that it matches the database entry. "
I am not sure we could move the library files to local path, is this feasible? If yes, how to do it?
As the error message says - it is not enough to simply add the jar file. You must also register it in the ColdFusion Adminstrator under "Extensions->CFX Tags" ... A CFX tag is a specific jar file that implements a native API interface to CF so it can be used without java. it's a special thing.
Step 1 is to get your file INTO the class path. You can do this by putting it in the Lib director, or you can specify the path via the JVM args like so:
Restart CF and then register the CFX Tag in the CF Administrator like so:
The class name will be part of the documentation of the CFX tag. To use it you then call it as one thing - CFX_nameofthetag with attributes specified by the documentation.
CFX is basically a wrapper so that you can use something more complex and Java like in a simple primitive values in/out and get something coldfusiony back like a query or struct. It's designed to let you do ColdFusion without knowing a lot of Java. :)
I have:
Server Details
Server Product ColdFusion
Version 9,0,1,274733
Edition Standard
Operating System Windows Server 2008
OS Version 6.0
Adobe Driver Version 4.0 (Build 0005)
Is it possible that I can receive all the errors that happen on coldfusion to a specific email?
If you don't want to add a cferror to every page you can add a onError method to your application.cfc this function will be called whenever any page has an error.
<cffunction name="onError">
<!--- The onError method gets two arguments:
An exception structure, which is identical to a cfcatch variable.
The name of the Application.cfc method, if any, in which the error
happened. --->
<cfargument name="Except" required="true"/>
<cfargument type="String" name = "EventName" required="true"/>
error handling goes here
</cffunction>
I also saw you had a question where you were worried about the mail server not working. If you are worried that you will not be able to receive emails about your errors you can log them to a file.
<!--- Log all errors in an application-specific log file. --->
<cflog file="filename" type="error" text="Event Name: #Eventname#" >
<cflog file="filename" type="error" text="Message: #except.message#">
Check out the cferror tag. It is exactly what you need.
You can put cferror in the Application.cfm file, if you are not using Application.cfc, and it will work on every page.
<cferror type="exception"
template="/error.cfm"
mailto="your#email.com"
exception="any">
This is the recommended way to email notification of errors pre CFMX7. It still works in CFMX7 and after but best practice suggests the use the onError() method of Application.cfc
wikidocs.adobe.com/wiki/display/coldfusionen/onError
I am testing consuming a web-service and I'm getting an error.
Here is the web-service component:
<cfcomponent >
<cffunction name="listBooks" access="remote" returntype="string" output="no" >
<cfquery name="getBooks" datasource="cfbookclub" >
SELECT bookID, title, bookDescription, genre
FROM books
ORDER BY title desc
</cfquery>
<cfsavecontent variable="bookList" >
<books>
<cfoutput query="getBooks" >
<book id="#getBooks.bookID#" >
<title>#XMLFormat( getBooks.title )#</title>
<description>#XMLFormat( getBooks.bookDescription )#</description>
<genre>#XMLFormat( getBooks.genre )#</genre>
</book>
</cfoutput>
</books>
</cfsavecontent>
<cfreturn bookList >
</cffunction>
Here is the consuming page:
<cfinvoke
webservice="http://127.0.0.1/books.cfc?wsdl"
method="listBooks"
returnvariable="rawXMLBookList" >
</cfinvoke>
Seems simple enough - I was actually trying to pass an argument "genre" when I got the initial error,
Web service parameter name category cannot be found in the provided parameters {genre}.
So I removed all reference to arguments, and STILL get this error
Web service operation with parameters {} cannot be found.
The error makes it sound like the web-service cannot be found, however if I cut and paste the url into my browser I get the expected XML doc...
There was another post like this on this site, but the problem was a base64 issue, I'm just returning txt so I don't think it's a similar problem, even through the error msg is similar.
Try adding the refreshWSDL argument to your <cfinvoke> call and see if that helps.
<cfinvoke
webservice="http://127.0.0.1/books.cfc?wsdl"
method="listBooks"
refreshwsdl="yes"
returnvariable="rawXMLBookList">
</cfinvoke>
Setting refreshwsdl="yes" reloads the WSDL file and regenerates the artifacts used to consume the web service.
Note you do not want to keep this setting for all of your requests. You just need to set it for one request to refresh the artifacts. Then you should change it back to refreshwsdl="no". Until you need it again.
Here is an excerpt from Charlie Arehart's Blog about the refreshWSDL argument:
Why should you have to refresh the web service metadata?
Just to back up for a moment, the problem stems from CF's attempt to help. On the first request for a given web service, CF does some caching to make future requests go faster, not caching the results of the web service method but rather the artifacts used by CF based on the description of the web service itself.
CF uses the web service description (WSDL) reported at the time of that first call to create a java proxy/stub based on that, which it then reuses on future calls from CF to that web service.
The issue arises if/when the web service metadata changes. CF won't know, and will continue to use the older cached proxy/stub, and your long-running code may fail if it doesn't match the new WSDL returned by the web service.
So we need a way to tell CF to refresh its cache of that proxy stub.
This new feature is certainly the easiest way to make that happen, but it's not the only way.
ColdFusion 8 is caching my cfcs. Development is at a stand-still. I don't have access to the admin panel. What are my options?
1) Get access to CF Administrator.
Really. I wouldn't want to host anywhere where I didn't have control over this.
2) Programmatically clear the cache.
Using the Admin API:
createObject("component","cfide.adminapi.runtime").clearTrustedCache()
Of course, if you don't have access to the CFAdmin, you might not have access to this either, but is worth trying.
According to this blog entry from Ray Camden you'll need to login to the admin via the API before running the above command, which of course suggests it's not going to work without already having access.
<cfset API = createObject("component","cfide.adminapi.runtime") />
<cfset API.login(adminPassword="password") />
<cfset API.clearTrustedCache() />
I use application.cfc to clear all of the cfc cache.
<!--- *****************************************************************
Run before the request is processed
************************************************************--->
<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfargument name="thePage" type="string" required="true">
<cfscript>
if (structKeyExists(url,'reinit')) {
structClear(application);
structClear(session);
onApplicationStart();
onSessionStart();
}
</cfscript>
<cfreturn true>
</cffunction>
The idea is to pass a url variable called "reinit". Whenever this variable is defined in the URL, the application is started.
In order to test this:
1. make a change to cfc
2. call a cfm page by xxx.cfm?reinit=1
3. observe the changes in the cfc are reflected.
hope it helps...
I know that this post is old, but I needed to do this for a (more) modern version of ColdFusion (2016) and the answer from Peter wouldn't work on CF 2016. Not looking to be the answer, just a footnote for newer versions of CF.
Here is a version that will work with CF 2016:
<cfscript>
variables['adminPW'] = "my cf admin password";
cfAdminAPIAdmin = createObject("component", "cfide.adminapi.administrator");
cfAdminAPIAdmin.login(variables.adminPW);
cfAdminAPIRuntime = createObject("component", "cfide.adminapi.runtime");
// clear the component and trusted (template) caches
cfAdminAPIRuntime.clearComponentCache();
cfAdminAPIRuntime.clearTrustedCache();
</cfscript>
Adobe appears to have separated the CF admin functionality from the runtime component. That's really the only difference. The version above shows how to clear the component cache too.
NOTE: I had been doing something very similar to CFNinja's answer, but one site (out of about 25 similar sites) just wouldn't clear the application scope components, the old version remained in a cache somehow.
My application.cfc uses the OnRequestStart to check users are logged in
<cfif not isDefined("session.auth.isLoggedIn")>
<cfinclude template="loginForm.cfm">
<cfabort>
</cfif>
and this is mangling my attempts to use a gateway service which errors out with
Error invoking CFC for gateway watchInboundFiles: null {GATEWAYTYPE={FileWatcher},ORIGINATORID={},CFCMETHOD={onDelete},DATA={{FILENAME={C:\temp\New Text Document.txt},TYPE={DELETE}}},CFCPATH={F:\ColdFusion9\wwwroot\watch_dir.cfc},GATEWAYID={watchInboundFiles}}.
If I comment out the OnRequestSTart method the gateway works as expected.
Someone else ran into this before here and a solution is apparently to
add a new application.cfc which
extended my original but overrode the
onRequestStart() - which worked
perfectly.
So how do I do that please?
To answer your question:
Your new Application.cfc will live in another directory but extend your original:
<cfcomponent extends="path.to.my.original.Application">
<cffunction name="onRequestStart">
<!--- No login code here --->
</cffunction>
</cfcomponent>
All other functions are available as usual.
Hoep that helps! More info here.
You could also add something to the application.cfc to see if the call is coming from the gateway. If so then skip the if block.