I'm using using ColdFusion and iText to generate PDF documents, and I want to be able to add a header and a footer to a PDF "automatically" whenever iText decides to make a page break.
I've seen examples of how to do this in Java, and here is the basic way to do that:
public class MyHeaderFooterPageEvent extends PdfPageEventHelper {
public void onEndPage(PdfWriter writer, Document document) {
//add your content here
}
}
And then, before you start composing your PDF document, you "register" your event like his:
MyHeaderFooterPageEvent event = new HeaderFooterPageEvent();
writer.setPageEvent(event);
(At least as far as I understands it.)
I've successfully managed to load the class PdfPageEventHelper into ColdFusion, so I know it's there:
<cfset local.PdfPageEventHelper=CreateObject("java","com.lowagie.text.pdf.PdfPageEventHelper")>
And when I dump local.PdfPageEventHelper i get:
So how do I tell ColdFusion what to do when the onEndPage is called, and how do I register the event so it will be called?
I'm using Coldfusion 11 on a Linux server.
This solution is mainly based on this
old blog post at cfSearching.blogspot.se.
While that solution uses the javaloader dynamic proxy library, this solution uses the newer(?) function CreateDynamicProxy (available from ColdFusion 10 I think), which Ageax (many thanks!) made me aware of.
This has been successfully tested in ColdFusion 11 on a Linux server.
To try it yourself:
Copy and paste the content below into one cfm file and one cfc file. While you can name the cfm file whatever you want, the cfc file must be named PdfPageEventHandler.cfc in order for this code to work.
Put the files in the same folder in a www root on you ColdFusion server.
Run the code by surfing to the cfm-file.
The browser should display a PDF of 3 pages with body text and footers.
content of the cfm-file:
<!---call function--->
<cfset _createPdf()>
<!---function for creating pdf with footer that is created via an event handler in onEndPage--->
<cffunction name="_createPdf" output="no" returntype="void">
<cfargument name="pdfFile" type="string" default="document.pdf" hint="the file name to write to disc">
<cfargument name="writeToBrowser" type="boolean" default="true" hint="will open the pdf document in the browser and delete the file when done">
<cfscript>
//set filePath for document
local.filePath = ExpandPath('.')&"/"&arguments.pdfFile;
//get BaseFont
local.BaseFont = CreateObject("java", "com.lowagie.text.pdf.BaseFont");
//get CMYK color
local.CMYKColor = CreateObject("java", "com.lowagie.text.pdf.CMYKColor");
//create color
local.color = local.CMYKColor.init(JavaCast("int",0),JavaCast("int",0),JavaCast("int",0),JavaCast("int",256));
//create font
local.font = local.BaseFont.createFont(local.BaseFont.COURIER, local.BaseFont.CP1252, true);
//compose custom config to make accessable in PdfPageEventHandler.cfc
local.config = {myCustomFooter = {text = "Page number", color = local.color, font = local.font, size = 20}};
//init the event handler (make sure the PdfPageEventHandler.cfc is present in the same folder as this template)
local.eventHandler = CreateObject("component", "PdfPageEventHandler").init(config = local.config);
//we can pass in an array of strings which name all the interfaces we want out dynamic proxy to implement
local.interfaces = ["com.lowagie.text.pdf.PdfPageEvent"];
//create a dynamic proxy that we will pass to the iText writer
local.eventHandlerProxy = CreateDynamicProxy(local.eventHandler, local.interfaces);
//init success flag
local.success = true;
try {
//init document
local.document = CreateObject("java", "com.lowagie.text.Document").init();
//init outstream
local.outputStream = CreateObject("java", "java.io.FileOutputStream").init(local.filePath);
//init writer
local.writer = CreateObject("java", "com.lowagie.text.pdf.PdfWriter").getInstance(local.document, local.outputStream);
//register the PROXY as the page event handler
local.writer.setPageEvent(local.eventHandlerProxy);
//open document
local.document.open();
//init paragraph
local.paragraph = CreateObject("java", "com.lowagie.text.Paragraph");
//output some pages with a simple text message. NOTE that our eventHandler will take care of adding footers on every page - that's the whole point with this example by the way :)
for (local.i = 1; local.i lte 3; local.i = local.i + 1) {
//add paragraph with text
local.document.add(local.paragraph.init("This page should have a footer with a page number on it!"));
//trigger new page
local.document.newPage();
}
} catch (any e) {
//an error occured
WriteOutput("Error: " & e.message);
//set success flag to false
local.success = false;
}
if (StructKeyExists(local, "document")) {
//close document
local.document.close();
}
if (StructKeyExists(local, "outStream")) {
//close outStream
local.outputStream.close();
}
if (local.success && arguments.writeToBrowser) {
_openPdf(filePath=local.filePath);
}
</cfscript>
</cffunction>
<!---function for opening pdf in browser--->
<cffunction name="_openPdf" output="no" returntype="void">
<cfargument name="filePath" type="string" required="yes">
<cfcontent type="application/pdf" file="#arguments.filePath#" deletefile="yes">
</cffunction>
Content of the cfc file, that should be named PdfPageEventHandler.cfc:
<cfcomponent output="false" hint="iText Event handler used to add headers, footers, etc.">
<!---1. INIT FUNCTION--->
<cffunction name="init" access="public" returntype="PdfPageEventHandler" output="false">
<!---come up with your own arguments that you want to have access to in onEndPage etc--->
<cfargument name="config" type="any" required="true" hint="custom config" />
<!---make sure the config is accessable by other functions--->
<cfset variables.config = arguments.config>
<cfreturn this />
</cffunction>
<!---2. ON END PAGE - the function that is in focus in this example--->
<cffunction name="onEndPage" access="public" returntype="void" output="true" hint="Called when a page is finished, just before being written to the document.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---edit below to make your own header / footer--->
<cfscript>
local.cb = arguments.writer.getDirectContent();
local.cb.saveState();
local.cb.beginText();
local.cb.setColorFill(variables.config.myCustomFooter.color);
local.cb.setFontAndSize(variables.config.myCustomFooter.font, variables.config.myCustomFooter.size);
local.cb.setTextMatrix(arguments.document.left(), arguments.document.bottom() - 10);
local.text = "#variables.config.myCustomFooter.text# #arguments.writer.getPageNumber()#";
local.cb.showText(local.text);
local.cb.endText();
local.cb.restoreState();
</cfscript>
</cffunction>
<!---3. OTHER FUNCTIONS THAT MUST EXIST (at least in this example)--->
<cffunction name="onOpenDocument" access="public" returntype="void" output="false" hint="Called when the document is opened.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---To be implemented: Code called when the document is opened--->
</cffunction>
<cffunction name="onCloseDocument" access="public" returntype="void" output="false" hint="Called when the document is closed">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---To be implemented: Code called when the document is closed--->
</cffunction>
<cffunction name="onStartPage" access="public" returntype="void" output="false" hint="Called when a page is initialized.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<!---To be implemented: Code called when a page is initialized--->
</cffunction>
<cffunction name="onParagraph" access="public" returntype="void" output="false" hint="Called when a Paragraph is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<!---To be implemented: Code called when paragraph is written --->
</cffunction>
<cffunction name="onParagraphEnd" access="public" returntype="void" output="false" hint="Called when a Paragraph is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<!---To be implemented: Code called on end of paragraph is written--->
</cffunction>
<!---4. FUNCTIONS THAT ONLY NEEDS TO EXIST IF YOU DO SOMETHING THAT TRIGGERS THEM
<cffunction name="OnChapter" access="public" returntype="void" output="false" hint="Called when a Chapter is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<cfargument name="title" type="any" required="true" hint="Title of the chapter. Instance of com.lowagie.text.Paragraph" />
<!---To be implemented: Code called when a Chapter is written--->
</cffunction>
<cffunction name="onChapterEnd" access="public" returntype="void" output="false" hint="Called when the end of a Chapter is reached">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="position" type="numeric" required="true" hint="The position of the end of the chapter. Value is a java float" />
<!---To be implemented: Code called when the end of a Chapter is reached--->
</cffunction>
<cffunction name="onGenericTag" access="public" returntype="void" output="false" hint="Called when a Chunk with a generic tag is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="rect" type="any" required="true" hint="The Rectangle containing the Chunk. Instance of com.lowagie.text.Rectangle" />
<cfargument name="text" type="string" required="true" hint="The text of the tag" />
<!---To be implemented: Code called when a Chunk with a generic tag is written--->
</cffunction>
<cffunction name="onSection" access="public" returntype="void" output="false" hint="Called when a Section is written">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<cfargument name="depth" type="numeric" required="true" hint="The number depth of the Section. Value is a java int" />
<cfargument name="title" type="any" required="true" hint="Title of the section. Instance of com.lowagie.text.Paragraph" />
<!---To be implemented: Code called when a Section is written--->
</cffunction>
<cffunction name="onSectionEnd" access="public" returntype="void" output="false" hint="Called when the end of a Section is reached.">
<cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" />
<cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" />
<cfargument name="paragraphPosition" type="numeric" required="true" hint="The position the chapter will be written to. Value is a java float" />
<cfargument name="depth" type="numeric" required="true" hint="The number depth of the Section. Value is a java int" />
<cfargument name="title" type="numeric" required="true" hint="Title of the section. Instance of com.lowagie.text.Paragraph" />
<!---To be implemented: Code called when the end of a Section is reached--->
</cffunction>
--->
</cfcomponent>
UPDATE!
Here's that same cfc, but in pure cfscript, for you that rather prefer that:
<cfscript>
component output="false" hint="iText Event handler used to add headers, footers, etc." {
property name="config" type="struct";
//1. INIT FUNCTION
public PdfPageEventHandler function init(required any config) {
//make sure the config is accessable by other functions
variables.config = arguments.config;
return this;
}
//2. ON END PAGE - the function that is in focus in this example
public void function onEndPage(required any writer, required any document) {
//Called when a page is finished, just before being written to the document
//edit below to make your own header / footer
local.cb = arguments.writer.getDirectContent();
local.cb.saveState();
local.cb.beginText();
local.cb.setColorFill(variables.config.myCustomFooter.color);
local.cb.setFontAndSize(variables.config.myCustomFooter.font, variables.config.myCustomFooter.size);
local.cb.setTextMatrix(arguments.document.left(), arguments.document.bottom() - 10);
local.text = "#variables.config.myCustomFooter.text# #arguments.writer.getPageNumber()#";
local.cb.showText(local.text);
local.cb.endText();
local.cb.restoreState();
}
//3. OTHER FUNCTIONS THAT MUST EXIST (at least in this example)
public void function onOpenDocument(required any writer, required any document) {
//Called when the document is opened
}
public void function onCloseDocument(required any writer, required any document) {
//Called when the document is closed
}
public void function onStartPage(required any writer, required any document) {
//Called when a page is initialized
}
public void function onParagraph(required any writer, required any document, required numeric paragraphPosition) {
//Called when a Paragraph is written
//paragraphPosition - The position the chapter will be written to. Value is a java float
}
public void function onParagraphEnd(required any writer, required any document, required numeric paragraphPosition) {
//Called when a Paragraph is written
//paragraphPosition - The position the chapter will be written to. Value is a java float
}
//4. FUNCTIONS THAT ONLY NEEDS TO EXIST IF YOU DO SOMETHING THAT TRIGGERS THEM
public void function OnChapter(required any writer, required any document, required numeric paragraphPosition, required any title) {
//Called when a Chapter is written
//paragraphPosition - The position the chapter will be written to. Value is a java float
//title - Title of the chapter. Instance of com.lowagie.text.Paragraph
}
public void function onChapterEnd(required any writer, required any document, required numeric position) {
//Called when the end of a Chapter is reached
//position - The position of the end of the chapter. Value is a java float
}
public void function onGenericTag(required any writer, required any document, required any rect, required string text) {
//Called when a Chunk with a generic tag is written
//rect - The Rectangle containing the Chunk. Instance of com.lowagie.text.Rectangle
//text - The text of the tag
}
public void function onSection(required any writer, required any document, required numeric paragraphPosition, required numeric depth, required any title) {
//Called when a Section is written
//paragraphPosition - The position the section will be written to. Value is a java float
//depth - The number depth of the Section. Value is a java int
//title - Title of the section. Instance of com.lowagie.text.Paragraph
}
public void function onSectionEnd(required any writer, required any document, required numeric paragraphPosition, required numeric depth, required any title) {
//Called when the end of a Section is reached
//paragraphPosition - The position the section will be written to. Value is a java float
//depth - The number depth of the Section. Value is a java int
//title - Title of the section. Instance of com.lowagie.text.Paragraph
}
}
</cfscript>
Related
In one of my components, abc.cfc, I am extending another one: xyz.cfc. Component xyz.cfc has an init() method which is expecting: datasource,username,password.
In my application, I am using it like this:
<cfset this.mappings = structNew() />
<cfset this.mappings["/com"] = getDirectoryFromPath(getCurrentTemplatePath()) & "com/">
<cfset Application.tools = new com.abc()>
Now in abc.cfc I am doing the following:
<cfcomponent hint="The File which acces the Information about the Detail" extends="xyz">
and xyz.cfc has the following function:
<cffunction name="init" access="public" output="No" returntype="mysql" hint="Initializes the component">
<cfargument name="datasource" required="Yes" type="string" />
<cfargument name="username" required="Yes" type="string" />
<cfargument name="password" required="Yes" type="string" />
<cfscript>
variables.instance = structNew();
setDatasource(argumentcollection=arguments); // set datasource information
clearCache(); // create cache struct
variables.instance.trim = true;
return this;
</cfscript>
</cffunction>
It is producing an error like this:
The DATASOURCE parameter to the INIT function is required but was not passed in. The error occurred in C:/ColdFusion11/cfusion/wwwroot/project1/admin/Application.cfc: line 28
You just pass the argument values in the constructor call:
<cfset Application.tools = new com.abc(datasource=datasource, etc)>
I am working with Google API using Coldfusion, So making a call to the following URL:
https://www.googleapis.com/plus/v1/people/{userID}?key={MyGoogleKey}
I am able to get the details of the user. Whatever they have shared in their google plus account. One thing that is missing is their email address and phone numbers (if available).
I think, I need to make another call to the API to get the email and phone numbers, but I am struggling with how to do that. Here is the code I am trying to use:
<cfset objGoogPlus = createObject("component","services.auth").init(apikey="#application.google_server_key#",parseResults=true)>
<cfdump var="#objGoogPlus.people_get(userID='#data.id#')#">
<cffunction name="init" access="public" output="false" hint="I am the constructor method.">
<cfargument name="apiKey" required="true" type="string" hint="I am the application's API key to access the services." />
<cfargument name="parseResults" required="false" type="boolean" default="false" hint="A boolean value to determine if the output data is parsed or returned as a string" />
<cfset variables.instance.apikey = arguments.apiKey />
<cfset variables.instance.parseResults = arguments.parseResults />
<cfset variables.instance.endpoint = 'https://www.googleapis.com/plus/v1/' />
<cfreturn this />
</cffunction>
<cffunction name="getparseResults" access="package" output="false" hint="I return the parseresults boolean value.">
<cfreturn variables.instance.parseResults />
</cffunction>
<cffunction name="people_get" access="public" output="false" hint="I get a person's profile.">
<cfargument name="userID" required="true" type="string" hint="The ID of the person to get the profile for. The special value 'me' can be used to indicate the authenticated user." />
<cfargument name="parseResults" required="false" type="boolean" default="#getparseResults()#" hint="A boolean value to determine if the output data is parsed or returned as a string" />
<cfset var strRequest = variables.instance.endpoint & 'people/' & arguments.userID & '?key=' & variables.instance.apikey />
<cfreturn getRequest(URLResource=strRequest, parseResults=arguments.parseResults) />
</cffunction>
<cffunction name="getRequest" access="private" output="false" hint="I make the GET request to the API.">
<cfargument name="URLResource" required="true" type="string" hint="I am the URL to which the request is made." />
<cfargument name="parseResults" required="true" type="boolean" hint="A boolean value to determine if the output data is parsed or returned as a string" />
<cfset var cfhttp = '' />
<cfhttp url="#arguments.URLResource#" method="get" />
<cfreturn handleReturnFormat(data=cfhttp.FileContent, parseResults=arguments.parseResults) />
</cffunction>
<cffunction name="handleReturnFormat" access="private" output="false" hint="I handle how the data is returned based upon the provided format">
<cfargument name="data" required="true" type="string" hint="The data returned from the API." />
<cfargument name="parseResults" required="true" type="boolean" hint="A boolean value to determine if the output data is parsed or returned as a string" />
<cfif arguments.parseResults>
<cfreturn DeserializeJSON(arguments.data) />
<cfelse>
<cfreturn serializeJSON(DeserializeJSON(arguments.data)) />
</cfif>
</cffunction>
<cffunction access="public" name="getProfileEmail" returntype="any" returnformat="json">
<cfargument name="accesstoken" default="" required="yes" type="any">
<cfhttp url="googleapis.com/oauth2/v1/userinfo"; method="get" resolveurl="yes" result="httpResult">
<cfhttpparam type="header" name="Authorization" value="OAuth #arguments.accesstoken#">
<cfhttpparam type="header" name="GData-Version" value="3">
</cfhttp>
<cfreturn DeserializeJSON(httpResult.filecontent.toString())>
</cffunction>
I do not what to say, but i used the following method and its seems to bring the email-address, not with new way but with old way:
<cfset googleLogin = objLogin.initiate_login(
loginUrlBase = "https://accounts.google.com/o/oauth2/auth",
loginClientID = application.google_client_id,
loginRedirectURI = application.google_redirecturl,
loginScope = "https://www.googleapis.com/auth/userinfo.email"
)>
I discuss Google+ and Sign In via this blog post (http://www.raymondcamden.com/index.cfm/2014/2/20/Google-SignIn-and-ColdFusion), and yes, I know it is bad to just point to a blog post so none of my hard work there will be appreciated by SO (sigh). As Prisoner said, what you get is based on the scopes initially requested. Here are the docs on additional scopes: https://developers.google.com/+/api/oauth#login-scopes. Email is there, but not phone as far as I see. And to be honest, I don't see a place to enter my phone # at Google+ anyway.
Based on the "getProfileEmail" function that you've added, it looks like you're using the userinfo scope and access point. Google has announced that this method is deprecated and will be removed in September 2014.
You should switch to using the people.get method and adding the email scope to the G+ Sign-in button that Raymond has outlined on his blog.
Update
In your call to objLogin.initiate_login you should change the loginScope parameter to use both the profile and email scopes at a minimum (see https://developers.google.com/+/api/oauth#scopes for a more complete list of scopes you may wish to use). So it might look something like:
<cfset googleLogin = objLogin.initiate_login(
loginUrlBase = "https://accounts.google.com/o/oauth2/auth",
loginClientID = application.google_client_id,
loginRedirectURI = application.google_redirecturl,
loginScope = "profile email"
)>
You can then use the people.get API call to get the information you need. Looking at your getRequest function, however, this appears to call people.get using the API Key, which is insufficient to get email - all it can do is get public information. You need to call people.get in the same way you called userinfo in the getProfileEmail function. I don't know ColdFusion well enough, but you should be able to adapt this function to call the people.get endpoint instead.
I need a little hand holding to convert my CFML cfexchange tags to the EWS API. I'm using CF 9.0.1 and need to add mail/calendar items to a hosted Exchange server.
I get the following error:
Error:
Could not log in to the Exchange server.
________________________________________
connection="exchangeConn"
server="EXVMBX016-5.exch016.msoutlookonline.net"
username="exch016\j_ttt"
mailboxname="j#ttt.com"
password="[removed]"
Protocol="http"
port="80"
formbasedauthentication="TRUE"
formbasedauthenticationURL="https://owa016.msoutlookonline.net/owa/auth/logon.aspx"
I have come up with the following code so far;
<cffunction name="EWSAddEvent" output="false" returntype="Boolean">
<!--- EWS added by vjl 2013/10/31 --->
<!---
CFExchange in CF server 9 or older will not talk with Exchange 2010 at all, it is promissed to be fixed in CF 10.
As a solution you can use the EWS API. Read the stuff below. I hope my hint is helpfull to you.
---------------------------------------------------------------------- ----------------------
With Exchange 2007 Microsoft abandoned WebDav as an interface to Exchangeserver.
The standard Coldfusion Tags relied on WebDav and will not work anymore.
Since I needed a way to interface with Exchange Server a started looking for possible solutions and this is what i came up with.
In december 2010 Microsoft released the Exchange Managed Services Library for java.
You can find it here: http://archive.msdn.microsoft.com/ewsjavaapi/Release/ProjectReleases.a spx?ReleaseId=5691
In the getting started document it tells you it depends on 4 3rd party libraries which you need to be download separately:
- Apache Commons HttpClient 3.1 (commons-httpclient-3.1.jar)
- Apache Commons Codec 1.4 (commons-codec-1.4.jar)
- Apache Commons Logging 1.1.1 (commons-codec-1.4.jar)
- JCIFS 1.3.15 (jcifs-1.3.15.jar)
With Coldfusion 9.1 (the version I tested with) you only need
- JCIFS 1.3.15 (jcifs-1.3.15.jar) which you can download here: http://jcifs.samba.org/src/
Place the EWS Jar and the JCIFS Jar in your Coldfusion libray folder and after restarting CF server the following code should work.
If you understand this you will be able to figure out your specific needs from the EWS API documentation.
--->
<cfargument name="EmailAddress" type="String" required="True" />
<cfargument name="EventName" type="String" />
<cfargument name="EventStartDateTime" type="Date" />
<cfargument name="EventEndDateTime" type="Date" />
<cfargument name="EventSubject" type="String" />
<cfargument name="EventDescription" type="String" />
<cfargument name="EventLocation" type="String" Required="False" Default="" />
<!--- <cfargument name="EventSensitivity" type="String" Required="False" Default="Normal" />
<cfargument name="EventImportance" type="String" Required="False" Default="Normal" /> --->
<cfargument name="EventReminder" type="String" Required="False" default=0 />
<!--- <cfargument name="Organizer" type="String" Required="False" Default="" /> --->
<cfargument name="OptionalAttendees" type="String" Required="False" Default="" />
<cfargument name="leadID" type="numeric" required="no" default="0" />
<cfargument name="serviceID" type="numeric" required="no" default="0" />
<cfargument name="userID" type="numeric" required="no" default="0" />
<cfargument name="companyID" type="numeric" required="no" default="0" />
<cfargument name="serviceTypeID" type="numeric" required="no" default="0" />
<cfmail to="v#g.com" from="info#t.com" subject="Exchange EWSAddEvent debug Arguments" type="html"><cfdump var="#Arguments#"></cfmail>
<!--- Build Mailbox --->
<cfset UserName = Left(Arguments.EmailAddress,Find("#",Arguments.EmailAddress)-1) />
<cfset Arguments.UserName = Application.Exchange.Domain & "\" & lcase(UserName) & Application.Exchange.MailboxPostFix />
<cfset Arguments.Pword = Trim(FetchExchangePassword(Arguments.EmailAddress)) />
<!--- 1. I need an instance of the ExchangeService class --->
<cfobject type="Java" class="microsoft.exchange.webservices.data.ExchangeService" name="service">
<cfset service.init()>
<cfmail to="v#g.c" from="info#t.com" subject="Exchange EWSAddEvent debug service" type="html"><cfdump var="#service#"></cfmail>
<!--- 2. I need to set the credentials --->
<!--- 2a. Create an instance of the WebCredentials class --->
<cfobject type="Java" class="microsoft.exchange.webservices.data.WebCredentials" name="credentials">
<!--- 2b. Set the credentials --->
<cfset credentials.init("#arguments.UserName#","#Arguments.Pword#", "t.com")>
<!--- 2c. Set the credentials in the service object --->
<cfset service.setCredentials(credentials) />
<!--- 3. In need to set the URL to Exchange (stay away from autodsicovery) --->
<!--- 3a. Create an instance of the Uri class --->
<cfobject type="Java" class="java.net.URI" name="uri">
<!--- 3b. Set the full path --->
<cfset uri.init("https://mail.t.com/ews/Exchange.asmx")>
<!--- 3c. Set the url in the service object --->
<cfset service.setUrl(uri) />
<!--- These are the steps you need to create valid a service object. --->
<!--- Now we need to do something with it. --->
<!--- I create a test message to my own mailbox to see if it works --->
<cfobject type="Java" action="create" class="microsoft.exchange.webservices.data.EmailMessage" name="message">
<cfset message = message.init(service) />
<cfset message.SetSubject("EWSTest")>
<cfset messageBody = CreateObject("java", "microsoft.exchange.webservices.data.MessageBody")>
<cfset messageBody.init("My EWS test message")>
<cfset message.SetBody( messageBody )>
<cfset message.ToRecipients.Add("v#t.com") >
<cfmail to="v#g.c" from="info#t.com" subject="Exchange EWSAddEvent debug message" type="html"><cfdump var="#message#"></cfmail>
<cfoutput>
#message.SendAndSaveCopy()#
</cfoutput>
<cfreturn True />
</cffunction>
Did you get any operation to work using EWS? Or are you facing problem when trying to send mails? If EWS itself is not working for you can you try the following snippet(Change the URL, user name and password) of code?
<cfscript>
service = createObject("java", "microsoft.exchange.webservices.data.ExchangeService");
service.init();
serviceURI = createObject("java", "java.net.URI");
serviceURI.init("http://10.192.37.30/ews/Exchange.asmx");
service.setUrl( serviceURI );
credentials = createObject("java", "microsoft.exchange.webservices.data.WebCredentials");
credentials.init("user", "password");
service.setCredentials(credentials);
folderAPI = createObject("java", "microsoft.exchange.webservices.data.Folder");
folderName = createObject("java", "microsoft.exchange.webservices.data.WellKnownFolderName");
result = folderAPI.bind(service, folderName.Inbox);
writeOutput(result.getDisplayName());
The corresponding java code is
ExchangeService service = new ExchangeService();
URI url = new URI( "http://10.192.37.30/ews/Exchange.asmx" );
service.setUrl( url );
service.setCredentials( new WebCredentials( "username", "password" ) );
System.out.println( "Created ExchangeService" );
Folder folder = Folder.bind( service, WellKnownFolderName.Inbox );
System.out.println( folder.getDisplayName() );
If this works, we can try more complex operations.
Please make sure you are using the correct ASMX URL, user name and password. Try accessing the URL in the browser. Provide the user name and password. If you are able to see the WSDL, then it is fine.
Also make sure that you are using Basic Authentication in Exchange Server.
Thanks,
Paul
I know this has been asked, but I cannot seem to find the solution that works.
I have a CFM page that uses the following to pass data to a CFC
<cfinvoke
component="common.cfcs.geotrails"
method="UpdateGeoTrail">
<cfinvokeargument name="title" value="#form.title#"/>
<cfinvokeargument name="Description_short" value="#form.Description_short#"/>
<cfinvokeargument name="Description" value="#form.description#"/>
<cfinvokeargument name="GTID" value="#form.gtid#"/>
<cfinvokeargument name="CatID" value="#form.catid#"/>
<cfif structKeyExists(form,"fileUpload") and len(form.fileUpload)>
<cfinvokeargument name="fileUpload" value="#form.fileUpload#"/>
</cfif>
</cfinvoke>
In the CFC that receives the data, I followed the direction at the Adobe Cookbook
<cffunction name="UpdateGeoTrail" access="public" returntype="void">
<cfargument name="title" type="string" required="yes">
<cfargument name="Description_short" type="string" required="yes">
<cfargument name="Description" type="string" required="yes">
<cfargument name="GTID" type="numeric" required="yes">
<cfargument name="CatID" type="numeric" required="yes">
<cfargument name="fileUpload" type="string" required="no">
<!--- IF THE IMAGE HAS BEEN UPLOADED --->
<!--- set the full path to the images folder --->
<cfif isdefined("arguments.fileUpload") AND len(arguments.fileUpload)>
<cfset tempmediapath = "#expandPath('/')#media/gtimages/temp/">
<cfset mediapath = "#expandPath('/')#media/gtimages/">
<cfset var cffile = "">
<cffile action="upload"
filefield="#ARGUMENTS.fileUpload#"
destination="#TempMediaPath#"
nameconflict="makeunique">
...
But I still get the dreaded error message...
"The form field /data/disk01/opt/coldfusion9/runtime/servers/coldfusion/SERVER-INF/temp/wwwroot-tmp/neotmp5003883285207133802.tmp did not contain a file."
If I follow the directions at StackExchange
( CFFILE - Uploading a file using a component )
<cffile action="upload"
filefield="fileUpload"
destination="#TempMediaPath#"
nameconflict="makeunique">
It passes without error, but a <CFDUMP> shows: [empty string].
What am I missing.
Thanks.
Phil
I know it isn't part of your cfc but did you make sure that the form has the enctype set?
<cfform action="/upload.cfm" enctype="multipart/form-data">
By removing the cffile scope, I was able to get it to work.
I am using ColdFusion 9.1.
I am rebuilding a site from scratch and pointing an existing domain name to it. The site is still getting a few hits each day and I want to take advantage of that. I want to redirect those page requests to the home page, and not the error that is currently being served.
I am looking ONLY for a ColdFusion solution to move the bad request to the home page. So, if they request domain.com/BadPage.cfm?QString=XYZ, they will be moved to domain.com/.
I tried using the following method in the Application.cfc, but I couldn't get to work as described. It seemed to have no effect.
<cffunction name="OnError" access="public" returntype="void" output="true">
<cfargument name="Exception" type="any" required="true" /">
<cfargument name="EventName" type="string" required="false" default="" />
<cfif Exception>
<cflocation url="http://www.MyDomain.cfom/">
</cfif>
<!--- Return out. --->
<cfreturn />
</cffunction>
In short, what is the simplest ColdFusion means to redirect bad requests?
onError will not catch missing templates. Add an onMissingTemplate Handler to Application.cfc:
<cffunction name="onMissingTemplate" returntype="Boolean" output="false">
<cfargument name="templateName" required="true" type="String" />
<!--- Put your home page file name here --->
<cflocation url="/index.cfm" />
<cfreturn true />
</cffunction>
Use onMissingTemplate()
<cffunction name="onMissingTemplate">
<cfargument type="string" name="targetPage" required=true/>
<cflocation url="http://www.MyDomain.cfom/">
</cffunction>