Hi Peter,
I totally agree with you, the whole point of the exercise is to do the
integration without requiring any custom modification to either
framework and use only the exposed mechanisms to do the hook up.
I'm not creating a requestHandler instance directly, but rather
picking it up from the appLoader instance on the application scope.
The assumption here is that since I'm reusing an existing instance it
is already configured and ready to use.
For what is worth, here is the CFC that I use to proxy the Mach-II
event request. This CFC is instantiated for each widget/portlet on the
page. Each instance is responsible for calling an event in the Mach-II
app and returning back the generated HTML (actually its appended to an
output buffer). The entry method is renderContent() and is called
internally by the HomePortals page renderer.
<cfcomponent extends="homePortals.components.contentTagRenderer"
hint="This content tag renderer renders regular Mach-II events as
reusable widgets on a page">
<cfproperty name="event" default="" type="string" displayname="Event"
hint="Mach-II Event to execute">
<cffunction name="renderContent" access="public" returntype="void"
hint="sets the rendered output for the head and body into the
corresponding content buffers">
<cfargument name="headContentBuffer"
type="homePortals.components.singleContentBuffer" required="true">
<cfargument name="bodyContentBuffer"
type="homePortals.components.singleContentBuffer" required="true">
<cfscript>
var html = "";
var nodeAttr = getContentTag().getModuleBean().toStruct();
// process Mach-II request and generate output
html = processMachIIRequest(nodeAttr);
// append HTML to output buffer
arguments.bodyContentBuffer.set( html );
</cfscript>
</cffunction>
<cffunction name="processMachIIRequest" access="private"
returntype="string" hint="Process a Mach-II Request. Returns the
generated output" output="true" >
<cfargument name="reqState" type="struct" required="true">
<cfset var renderedContent = "">
<cfset var eventParameter = "">
<cfset var appManager = 0>
<cfset var appHash = hash(getBaseTemplatePath())>
<cfset var lockTimeout = 30>
<cfset var appKey = GetFileFromPath(ExpandPath('.'))>
<cfset appKey = REReplace(appKey, "[[:punct:]|[:cntrl:]]", "", "all")
<!--- Start Application Requests --->
<cflock type="readonly" name="#appHash#" timeout="#lockTimeout#"
throwontimeout="true">
<cfset appManager = application[appKey].appLoader.getAppManager()>
</cflock>
<cfset eventParameter = appManager.getPropertyManager().getProperty
("eventParameter")>
<cfset url[eventParameter] = arguments.reqState.event>
<cfset StructAppend(url, arguments.reqState, true)>
<cfsavecontent variable="renderedContent">
<cfset appManager.getRequestHandler().handleRequest()>
</cfsavecontent>
<cfreturn renderedContent>
</cffunction>
</cfcomponent>
Here you can also see a couple of the things I was referring on my
other questions. Since each 'instance' of the widget can have its own
set of attributes, I am adding them into the URL scope (yes i know,
this is horrible) since I couldn't find a way of adding the attributes
directly to the internal event context. Also I am using cfsavecontent
to capture the output of the request.
I think what I'm trying to do is similar to what you would use when
exposing framework events to an Ajax or Flex client, except that in my
particular case I do need to trap the HTML output of the request, and
need to do everything on the same ColdFusion request (no remoting or
xmhttprequest).
Also I will look into the plugins suggestion, I guess you can tell be
now that I'm completely new to Mach-II, so I'm discovering it bit by
bit, starting from the deep end and working my way backwards to the
kiddie pool :)
Oscar
On Nov 11, 4:02 pm, "Peter J. Farrell" <pe...@mach-ii.com> wrote:
> Inline below:
> Oscar Arevalo said the following on 11/11/2009 04:42 PM:
> > 1. Have Mach-II own and manage the creation of the HomePortals engine
> > singleton,
> > 2. Have Mach-II events render normal HomePortals pages (indicating
> > which HP page to load by using a URL variable)
> > 3. Have Mach-II widgets embedded on a HomePortals page.
> > #1 and #2 were pretty easy to solve (I will post all code and details
> > later on a blog post), but my issue is with #3.
> > To explain better what I want to achieve with number 3, imagine a
> > portal container, in which each portlet is implemented as a Mach-II
> > event request, with the catch that the page contains multiple portlets
> > and each one is independent of the other. In other words, what I want
> > to do is to encapsulate an entire Mach-II event request so that I can
> > fire it programmatically (from within the HomePortals page renderer)
> > and then capture its HTML output so that it can be incorporated on the
> > final page.
> > The problem that I run is on the RequestHandler.cfc, method
> > processEvents(). What happens is since the HomePortals page rendering
> > is called by a Mach-II event, when I try to process another Mach-II
> > request I run into the restriction that the processEvents method can
> > only be called once per request. If I comment out the lines where it
> > checks this (lines 206-209), I can get the whole thing to work. But I
> > would like to find a way that does not involve modifying the framework
> > code.
> How are you running this? The RequestHander.cfc isn't for public
> consumption so you are definitely in "voodoo" as you call it. I have a
> feeling you are manually creating a RequestHandler.cfc and calling
> handlerRequest() method then trying to reuse the CFC for additional
> requests. There are a lot of little things that must be setup and
> configured correctly for a Mach-II request. I suggest you just create a
> new RequestHandler per request you need to
> make instead of trying to reuse a RequestHandler for multiple requests.
> See below the common approach.> Question #2: Another doubt that I have if there is a way for capturing
> > the HTML output of an event request.
> Again, I have no clue how you are making the request to your Mach-II
> application from inside HomePortals. I think the easiest way of
> accomplishing what you want to do with to do a cfmodule to your
> index.cfm page and wrap the cfmodule call with a cfsavecontent.
> Another option is to create a plugin that implements the postProcess()
> plugin point in which you stash data or output that is the event object
> into some other place (like the request scope). After the cfmodule
> completes you can grab that data.
> You could easily wrap all the cfmodule and data extraction stuff in a
> nice CFML custom tag.> Bonus Question: Is there a way for me to override the behavioer of
> > RequestHandler.getRequestEventArgs() so that I can inject a different
> > set of event arguments other than URL and Form.
> I'd suggest not overriding any framework method. I'd create a Mach-II
> plugin that implements the preProcess() method in which you can pull
> data from other places and place it into the event object. I have a
> feeling you're wanting to stick stuff in the request scope.
> Best,
> .pjf