I had a controller that looked like this.
component accessors="true" {
property AuthorService;
public Author function init(fw){
variables.fw = arguments.fw;
return this;
}
public void function list(){
rc.authors = AuthorService.list();
}
}
Whenever I tried to access the authorservice it would come up
undefined. I set the authorService setter attribute to false and wrote
my setter. Not to my surprise it worked just fine. I jumped into the
framework and found the autowire method. The problem is the way we are
looping through the components methods here. After talking with a
friend he pointed out that they are not really methods, which was
right along the lines I was thinking. So running autowire would never
see my setter, therefore never inject my service.
<cffunction name="autowire" access="private" output="false"
hint="Used to autowire controllers and services from a bean
factory.">
<cfargument name="cfc" />
<cfargument name="beanFactory" />
<cfset var key = 0 />
<cfset var property = 0 />
<cfset var args = 0 />
<cfloop item="key" collection="#arguments.cfc#">
<cfif len(key) gt 3 and left(key,3) is "set">
<cfset property = right(key, len(key)-3) />
<cfif arguments.beanFactory.containsBean(property)>
<!--- args = [ getBeanFactory().getBean(property) ] does not seem
to be portable --->
<cfset args = structNew() />
<cfset args[property] = arguments.beanFactory.getBean(property) /
>
<cfinvoke component="#arguments.cfc#" method="#key#"
argumentCollection="#args#" />
</cfif>
</cfif>
</cfloop>
</cffunction>
A quick rewrite using getMetaData() and it works just great now!
<cffunction name="autowire" access="private" output="false"
hint="Used to autowire controllers and services from a bean
factory.">
<cfargument name="cfc" />
<cfset var key = 0 />
<cfset var property = 0 />
<cfset var args = 0 />
<cfset var methods = getMetaData(arguments.cfc).functions>
<cfloop array="#methods#" index="method">
<cfif structKeyExists(method,"name")>
<cfif len(method.name) gt 3 and left(method.name,3) is "set">
<cfset property = right(method.name, len(method.name)-3) />
<cfif getBeanFactory().containsBean(property)>
<!--- args = [ getBeanFactory().getBean(property) ] does not
seem to be portable --->
<cfset args = structNew() />
<cfset args[property] = getBeanFactory().getBean(property) />
<cfinvoke component="#arguments.cfc#" method="#method.name#"
argumentCollection="#args#" />
</cfif>
</cfif>
</cfif>
</cfloop>
</cffunction>
So I was messing around with fw1 tonight and I came across a bug.
Whenever I tried to access the authorservice it would come up
undefined.
--
You received this message because you are subscribed to the Google Groups "framework-one" group.
To post to this group, send email to framew...@googlegroups.com.
To unsubscribe from this group, send email to framework-on...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/framework-one?hl=en.
On Jan 13, 10:04 pm, Dutch Rapley <dutch.rap...@gmail.com> wrote:
That is unfortunate because I just found another instance and I expect
I will find more.
The populate method does the same loop.
On Jan 14, 9:23 am, Dutch Rapley <dutch.rap...@gmail.com> wrote:
> On Wed, Jan 13, 2010 at 10:50 PM, Dan Vega <danv...@gmail.com> wrote:
> > That is unfortunate because I just found another instance and I expect
> > I will find more.
>
> I don't think it's that unfortunate for auto wiring controllers. Auto wiring
> doesn't happen on every request, only when the framework loads the
> controllers, when the framework is first initialized (or if you're using
> subsystems, only the first time each subsystem is loaded). Controllers are
> singletons and cached during framework initialization.
>
> > The populate method does the same loop.
>
> populate() doesn't loop through the cfc *if* you pass a list of keys, but it
I think Adobe have made a mistake in their approach to this - but I
understand why they took this approach. Essentially, they can generate
faster code for setters / getters if they're not relying on real
functions. I think the better approach would have been to generate
real functions but to still use the native (high-performance)
implementation. This would allow all the existing code out there that
matches collections of data against public setXyz() methods in
components to work without having to resort to getMetadata() on the
component and everyone having to code their own solution to the
inheritance issue.
And you're right that both autowire() and populate() use a similar
approach, requiring real methods.
The metadata approach simply won't work in the presence of runtime
method injection - which is certainly possible for transient objects
that you might want to use populate() on. Runtime injection is how
ColdBox works with models, BTW, although it uses a custom metadata
DSL.
That said, current approaches that walk the CFC for public setXyz()
methods don't take onMissingMethod() into account either...
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/
"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood
Dan
On Jan 14, 6:25 pm, Sean Corfield <seancorfi...@gmail.com> wrote:
> Railo Technologies US --http://getrailo.com/
> An Architect's View --http://corfield.org/
--
You received this message because you are subscribed to the Google Groups "framework-one" group.
To post to this group, send email to framew...@googlegroups.com.
To unsubscribe from this group, send email to framework-on...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/framework-one?hl=en.
I updated my local copy of fw1 and it works fine but I don't want to
do this on our production box because if I ever go to update the
framework it could cause issues.
> > framework-on...@googlegroups.com<framework-one%2Bunsubscribe@goog legroups.com>
Sean already addressed this question earlier in this same thread (see
below). Bob's method deals with inheritance, but not runtime method
injection.
On Feb 24, 12:11 pm, Ryan Cogswell <ryancogsw...@gmail.com> wrote:
Metadata doesn't address onMissingMethod(), nor injected setters (on
your controllers or services), nor methods declared via <cfinclude>'d
files, nor several other scenarios. It would only address CF9 property
set/get methods if special, CF9-specific code was added to look for
the additional metadata for those - rather than the regular methods
metadata present on CF8 and Railo and OpenBD.
Looping over public methods doesn't address onMissingMethod() nor CF9
property set/get methods - so it addresses more scenarios.
Since you are only worried about services and controllers, I'm
surprised you think this is a big deal? The CF9 property stuff is
intended mainly for ORM / transient objects...
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/