RC scope not updating properly?

52 views
Skip to first unread message

Kericr00

unread,
Nov 11, 2011, 4:31:48 PM11/11/11
to framework-one
I am working with Framework One for the first time and attempting to
piece together an application that will act as a template for future
applications for our team. In this template, I am attempting to
create an LDAP authentication function. My login form has an action
submitting a controller CFC called main and an action called
'checkLogin.' My authenticateLogin function is as follows:

<cffunction name="checkLogin" output="false" hint="Check Login">
<cfargument name="rc" />

<cfset variables.fw.service('login.authenticatelogin',
'loginStruct') />
<cfdump var="#rc#" abort="yes" />
</cffunction>

In my services folder, I've created a login CFC with a function named
authenticateLogin, which appears as follows:

<cffunction name="authenticateLogin" output="false">
<cfargument name="username" type="string" required="yes" default="" /
>
<cfargument name="password" type="string" required="yes" default="" /
>

<cfset var authStruct = structNew() />
<cfset authStruct.role = 'guest' />
<cfset authStruct.loggedin = 0 />

<cftry>
<cfldap server="ldapserver" username="presenseUN"
password="presensePW"
action="query" name="userExists" />
<cfcatch type="any">
<cfdump var="#cfcatch#">
</cfcatch>
</cftry>

<cfif isDefined('userExists') and userExists.recordcount>
<cfldap server="ldapserver" username="#arguments.username#"
password="#arguments.password#" action="query"
name="userAuthentication"
maxrows="1" />
<cfelse>
<!--- database user authentication goes here --->
</cfif>

<cfif userAuthentication.recordcount>
<cfset authStruct.role = 'user' />
<cfset authStruct.loggedin = 1 />
</cfif>

<cfreturn authStruct />
</cffunction>

To my understanding, by specifying the arguments in my service
function, FW/1 should automatically detect what arguments are being
requested and only pass those arguments. When I cfdump the arguments
struct inside the service function however, the entire RC scope is
presented, including the URL action and the formfields value.
Similarly, when I allow the service action to finish and dump the RC
scope after the call has been made, my loginStruct value is nowhere to
be found. I do not understand why this is happening.

System Information
FW/1 1.2 on CF9.0.1 running IIS on Windows 7 Pro (production servers
are CF8 so FW/1 2.0 is not possible; we're waiting for Zeus)

Sean Corfield

unread,
Nov 11, 2011, 4:46:50 PM11/11/11
to framew...@googlegroups.com
On Fri, Nov 11, 2011 at 4:31 PM, Kericr00 <keri...@gmail.com> wrote:
>                <cfset variables.fw.service('login.authenticatelogin',
> 'loginStruct') />

This queues up BUT DOES NOT EXECUTE the service call. Please take a
deeper look at the documentation for the lifecycle which shows that
services execute *after* the controller item.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

Sean Corfield

unread,
Nov 11, 2011, 5:05:11 PM11/11/11
to framew...@googlegroups.com
On Fri, Nov 11, 2011 at 4:46 PM, Sean Corfield <seanco...@gmail.com> wrote:
> This queues up BUT DOES NOT EXECUTE the service call. Please take a
> deeper look at the documentation for the lifecycle which shows that
> services execute *after* the controller item.

As an aside on this, I have abandoned the concept of queuing up
service calls completely for FW/1 on Clojure.

FW/1 1.x implicitly called services for you because a lot of (naive)
MVC code I'd seen had a lot of simple controller methods that merely
delegated to service methods. That's why there was the start/end item
method pairs as well. I still believe that was the right choice in
2009.

In FW/1 2.0, the implicit service calls no longer happen (by default)
but the service() call remains for queuing up calls. This is
deliberate to discourage fat controllers with lots of service calls
and manipulation of data.

In Clojure, there are no side effects - so there's no temptation to
write a slew of service calls and assignments in your controller
functions. Consequently, your controller functions are pure functions
of the request context: given rc, return an updated rc containing keys
whose values are the results of function calls into the model. Since
there's no objects in Clojure, there's no separation into "services"
and "domain objects" so there's just The Model (which is code
containing your business logic). Consequently, there's no service()
API.

Nor is there a controller() API method in the Clojure version. There's
no "lifecycle" methods (a la Application.cfc). There's no
"application" scope (because that concept is all about mutable global
variables). Cookies, sessions and "flash" are all handled as keys in
the request context (because that's how the underlying Ring machinery
which handles HTTP request/response works).

Currently, the Clojure version supports before() / after() around
controller item functions to make section-wide operations easy. I plan
to add :before / :after configuration to specify application-wide
functions (you'll simply specify functions for those).

I'll probably back-port some of these simplifications and concepts
back to a future release of FW/1 for CFML (so, yes, there will be
continued development of the CFML version for a long time, don't
worry!).

Sean Corfield

unread,
Nov 11, 2011, 5:09:22 PM11/11/11
to framew...@googlegroups.com
On Fri, Nov 11, 2011 at 5:05 PM, Sean Corfield <seanco...@gmail.com> wrote:
> I'll probably back-port some of these simplifications and concepts
> back to a future release of FW/1 for CFML (so, yes, there will be
> continued development of the CFML version for a long time, don't
> worry!).

And as a follow-on from this, the simplification and streamlining is
likely to be the easiest way to a version of FW/1 that doesn't require
you to extend it into Application.cfc - which in turn will make it
_much_ easier to migrate existing applications to FW/1 by allowing
piecemeal migration while the legacy code continues to use
Application.cfm, for example...

Kericr00

unread,
Nov 14, 2011, 11:22:01 AM11/14/11
to framework-one
I appreciate the responses to my question, but I am still not
following. I don't know where I'm supposed to tell my loginStruct to
get added to the session scope, I don't know where I'm supposed to
perform the check I need to confirm a valid login, and I don't know
how I'm supposed to redirect users back to my login screen when the
password is incorrect versus to send them ahead into the site when a
valid login was discovered. I come from a background of spaghetti
code and procedural Fusebox. My understanding of MVC is the
controller controls the flow of an action, and the service interacts
with the DB for CRUD, so I do not know why when I call a service
function like a checkLogin in a controller and ask it to return a
result (valid/invalid login struct), that I cannot take that result
and perform another controlling action on it. The examples in FW/1
download that refer to this functionality use beans, and while I want
to get there eventually, I do not want to do that for this template
(or the initial site this will be based off of), because the other
members on my team are even less familiar with MVC and OO than I am; I
also need to teach my coworkers on how to develop within this
framework.

On Nov 11, 5:09 pm, Sean Corfield <seancorfi...@gmail.com> wrote:
> On Fri, Nov 11, 2011 at 5:05 PM, Sean Corfield <seancorfi...@gmail.com> wrote:
> > I'll probably back-port some of these simplifications and concepts
> > back to a future release of FW/1 for CFML (so, yes, there will be
> > continued development of the CFML version for a long time, don't
> > worry!).
>
> And as a follow-on from this, the simplification and streamlining is
> likely to be the easiest way to a version of FW/1 that doesn't require
> you to extend it into Application.cfc - which in turn will make it
> _much_ easier to migrate existing applications to FW/1 by allowing
> piecemeal migration while the legacy code continues to use
> Application.cfm, for example...
> --
> Sean A Corfield -- (904) 302-SEAN
> An Architect's View --http://corfield.org/
> World Singles, LLC. --http://worldsingles.com/

Sean Corfield

unread,
Nov 14, 2011, 1:42:42 PM11/14/11
to framew...@googlegroups.com
On Mon, Nov 14, 2011 at 8:22 AM, Kericr00 <keri...@gmail.com> wrote:
> with the DB for CRUD, so I do not know why when I call a service
> function like a checkLogin in a controller and ask it to return a
> result (valid/invalid login struct), that I cannot take that result
> and perform another controlling action on it.  The examples in FW/1

Because - as the documentation explains - calling service() causes the
method call to be queued up, not executed.

Look at the documentation:
https://github.com/seancorfield/fw1/wiki/Developing-Applications-Manual

Under "Designing Controllers" it explains the lifecycle of a request
and when various things run.

If you have startFoo() / endFoo() controller methods and startFoo()
calls service("main.foo") then the main.cfc:foo() service will be
called before endFoo() is executed.

The point of MVC is to decouple your model (your services) from the
framework so they are reusable. FW/1's approach with services is meant
to encourage that.

Most FW/1 developers switch to explicitly calling services themselves
as their application complexity grows - and managing the model with a
DI framework (such as ColdSpring or DI/1). This is a natural
evolutionary path, IMO.


--
Sean A Corfield -- (904) 302-SEAN

An Architect's View -- http://corfield.org/

World Singles, LLC. -- http://worldsingles.com/

Kevin Cruz

unread,
Nov 14, 2011, 3:12:08 PM11/14/11
to framework-one
Ok, I think I understand what I'm doing wrong here. I've been combing
through the documentation prior to me asking as well as afterwards to
try to understand how this all works. I'll come back if (when) I have
more questions.

On Nov 14, 1:42 pm, Sean Corfield <seancorfi...@gmail.com> wrote:
> On Mon, Nov 14, 2011 at 8:22 AM, Kericr00 <keric...@gmail.com> wrote:
> > with the DB for CRUD, so I do not know why when I call a service
> > function like a checkLogin in a controller and ask it to return a
> > result (valid/invalid login struct), that I cannot take that result
> > and perform another controlling action on it.  The examples in FW/1
>
> Because - as the documentation explains - calling service() causes the
> method call to be queued up, not executed.
>
> Look at the documentation:https://github.com/seancorfield/fw1/wiki/Developing-Applications-Manual
>
> Under "Designing Controllers" it explains the lifecycle of a request
> and when various things run.
>
> If you have startFoo() / endFoo() controller methods and startFoo()
> calls service("main.foo") then the main.cfc:foo() service will be
> called before endFoo() is executed.
>
> The point of MVC is to decouple your model (your services) from the
> framework so they are reusable. FW/1's approach with services is meant
> to encourage that.
>
> Most FW/1 developers switch to explicitly calling services themselves
> as their application complexity grows - and managing the model with a
> DI framework (such as ColdSpring or DI/1). This is a natural
> evolutionary path, IMO.
> --
> Sean A Corfield -- (904) 302-SEAN
> An Architect's View --http://corfield.org/
> World Singles, LLC. --http://worldsingles.com/

Sean Corfield

unread,
Nov 14, 2011, 3:56:59 PM11/14/11
to framew...@googlegroups.com
On Mon, Nov 14, 2011 at 12:12 PM, Kevin Cruz <keri...@gmail.com> wrote:
> Ok, I think I understand what I'm doing wrong here.  I've been combing
> through the documentation prior to me asking as well as afterwards to
> try to understand how this all works.  I'll come back if (when) I have
> more questions.

If it's any consolation, if I had the chance to do FW/1 over from
scratch, I would not implement the services convention - I would push
people to a single model/ folder and encourage folks to manage service
calls directly, using a simple DI framework (so I would have made DI/1
a couple of years earlier :)

For the Clojure version, I'm taking advantage of this lesson and not
offering the services convention...


--
Sean A Corfield -- (904) 302-SEAN

An Architect's View -- http://corfield.org/

World Singles, LLC. -- http://worldsingles.com/

Kevin Cruz

unread,
Nov 15, 2011, 2:59:58 PM11/15/11
to framework-one
Yeah, that's where I was getting fouled up because I was thinking of
the controller cfc like it was a service manager and the service cfc
like it was an object. Once I grasped the idea that it's OK to have
empty controller and service functions, it all fell into place.

On Nov 14, 3:56 pm, Sean Corfield <seancorfi...@gmail.com> wrote:
> On Mon, Nov 14, 2011 at 12:12 PM, Kevin Cruz <keric...@gmail.com> wrote:
> > Ok, I think I understand what I'm doing wrong here.  I've been combing
> > through the documentation prior to me asking as well as afterwards to
> > try to understand how this all works.  I'll come back if (when) I have
> > more questions.
>
> If it's any consolation, if I had the chance to do FW/1 over from
> scratch, I would not implement the services convention - I would push
> people to a single model/ folder and encourage folks to manage service
> calls directly, using a simple DI framework (so I would have made DI/1
> a couple of years earlier :)
>
> For the Clojure version, I'm taking advantage of this lesson and not
> offering the services convention...
> --
> Sean A Corfield -- (904) 302-SEAN
> An Architect's View --http://corfield.org/
> World Singles, LLC. --http://worldsingles.com/

Sean Corfield

unread,
Nov 15, 2011, 6:07:06 PM11/15/11
to framew...@googlegroups.com
On Tue, Nov 15, 2011 at 11:59 AM, Kevin Cruz <keri...@gmail.com> wrote:
> Yeah, that's where I was getting fouled up because I was thinking of
> the controller cfc like it was a service manager and the service cfc
> like it was an object.  Once I grasped the idea that it's OK to have
> empty controller and service functions, it all fell into place.

If your controller function is empty, you can omit it entirely. Unlike
ColdBox, you don't need a controller function when it doesn't need to
do anything. So, for pure "view" actions, you only need the view
itself (hence the "Simplest Possible FW/1 Application" example has
just views/main/default.html containing Hello World! and no
controller). Hope that makes sense?


--
Sean A Corfield -- (904) 302-SEAN

An Architect's View -- http://corfield.org/

World Singles, LLC. -- http://worldsingles.com/

Kevin Cruz

unread,
Nov 16, 2011, 3:25:41 PM11/16/11
to framework-one
Yes, absolutely. I was picking up on the fact that there's no need to
even define the function if it has no purpose based on the sample
userManager application; I've done some work with Coldbox previously
but it's nearly-literal mountain of documentation scared me away from
that framework so I wasn't really aware that it shared that type of
functionality.
On Nov 15, 6:07 pm, Sean Corfield <seancorfi...@gmail.com> wrote:
> On Tue, Nov 15, 2011 at 11:59 AM, Kevin Cruz <keric...@gmail.com> wrote:
> > Yeah, that's where I was getting fouled up because I was thinking of
> > the controller cfc like it was a service manager and the service cfc
> > like it was an object.  Once I grasped the idea that it's OK to have
> > empty controller and service functions, it all fell into place.
>
> If your controller function is empty, you can omit it entirely. Unlike
> ColdBox, you don't need a controller function when it doesn't need to
> do anything. So, for pure "view" actions, you only need the view
> itself (hence the "Simplest Possible FW/1 Application" example has
> just views/main/default.html containing Hello World! and no
> controller). Hope that makes sense?
> --
> Sean A Corfield -- (904) 302-SEAN
> An Architect's View --http://corfield.org/
> World Singles, LLC. --http://worldsingles.com/
Reply all
Reply to author
Forward
0 new messages