Cannot set properties on factory-bean result

11 views
Skip to first unread message

Elliott Sprehn

unread,
Mar 7, 2010, 1:15:45 AM3/7/10
to ColdSpring-Users
I'm trying to set properties on a bean that's returned from a factory-
bean.

Here's a simple a test case:
<beans>
<bean id="Factory" class="testing.Factory">
</bean>
<bean id="Child" factory-bean="Factory" factory-
method="create">
<property name="Property">
<value>400</value>
</property>
</bean>
</beans>

ColdSpring throws an error:
The VALUE parameter to the setProperty function is required but was
not passed in.

/coldspring/beans/DefaultXmlBeanFactory.cfc: line 940
/coldspring/beans/DefaultXmlBeanFactory.cfc: line 632

Can you not use property elements on factory-bean results?

Kevin Pepperman

unread,
Mar 7, 2010, 4:48:25 AM3/7/10
to coldspri...@googlegroups.com
Working here in Railo, I have not installed CF here on my laptop yet,
but its working on Railo.

The trace returns {'p':'','Property':'400'} from setProperty() in
bean.cfc created by Factory.cfc

cs.xml
<beans>
<bean id="Factory" class="Factory">
</bean>
<bean id="Child" factory-bean="Factory" factory-method="create">


<property name="Property">
<value>400</value>
</property>
</bean>
</beans>

bean.cfc:
<cfcomponent>
<cffunction name="init" access="public">
<cfreturn this>
</cffunction>

<cffunction name="setProperty" access="public">
<cfargument name="p" default="" />
<cftrace var="arguments" />
</cffunction>
</cfcomponent>


Factory.cfc:
<cfcomponent>
<cffunction name="init" access="public">
<cfreturn this>
</cffunction>

<cffunction name="create" access="public">
<cfreturn createObject("component", "bean").init()>
</cffunction>

</cfcomponent>

<cfset cs = createObject("component",
"coldspring.beans.DefaultXmlBeanFactory").init() />
<cfset cs.loadBeansFromXmlFile( beanDefinitionFile: "cs.xml") />
<cfdump eval="cs.getBean('Child')" />


--
/Kevin Pepperman

"They who can give up essential liberty to obtain a little temporary
safety, deserve neither liberty nor safety." - Benjamin Franklin

Kevin Pepperman

unread,
Mar 7, 2010, 5:08:00 AM3/7/10
to coldspri...@googlegroups.com
Just tested CF9, and it works there too..

Property = 400

method setProperty() in bean.cfc called from CS factory-method
"create" in Factory.cfc

<cffunction name="setProperty" access="public">

<cfargument name="Property" default="" />
<cfdump var="#arguments#" />
<cfabort />
</cffunction>

Elliott Sprehn

unread,
Mar 7, 2010, 7:04:39 AM3/7/10
to ColdSpring-Users
On Mar 7, 5:08 am, Kevin Pepperman <chorno...@gmail.com> wrote:
> Just tested CF9, and it works there too..
>
> Property = 400
>
> method setProperty() in bean.cfc called from CS factory-method
> "create" in Factory.cfc
>
>         <cffunction name="setProperty" access="public">
>         <cfargument name="Property" default="" />
>                 <cfdump var="#arguments#" />
>                 <cfabort />
>         </cffunction>
>
> --
> /Kevin Pepperman

Are you running 1.2 or BER? We're on 1.2 and this fails on 2 different
servers.

Elliott Sprehn

unread,
Mar 7, 2010, 7:13:57 AM3/7/10
to ColdSpring-Users

On Mar 7, 5:08 am, Kevin Pepperman <chorno...@gmail.com> wrote:

> Just tested CF9, and it works there too..

http://elliottsprehn.com/personal/coldspringfail.zip

Here's a sample app. It fails in both CF8 and CF9 with the same error
listed above.

Elliott Sprehn

unread,
Mar 7, 2010, 7:37:53 AM3/7/10
to ColdSpring-Users

I just checked out from CVS (following the instructions on the
website) and I still see this failure.

After playing with this some I've found that this does work:

<cffunction name="setProperty" access="public" returntype="void"
output="false">
<cfargument name="property" type="any" required="true">

<cfset variables.property = arguments.property>
</cffunction>

And dumping the arguments shows that too. So CS is passing the
argument name as the name of the property which is totally wrong
instead of using the name of the first argument, or even name="1"
which would work too. Your test case passes because you have
default="" and not required="true".

I tracked that down into BeanProperty.cfc#getArgumentName()

<cffunction name="getArgumentName" access="public" output="false"
returntype="string" hint="I retrieve the Name from this instance's
data">
<cfif structKeyExists(variables.instanceData,"argName")>
<cfreturn variables.instanceData.argName/>
<cfelse>
<cfreturn getName() />
</cfif>
</cffunction>

which is returning getName() if there's no name. It should return "1"
to get the first positional argument.

Kevin Pepperman

unread,
Mar 7, 2010, 7:39:31 AM3/7/10
to coldspri...@googlegroups.com
Try changing the argument name to Property

<cffunction name="setProperty" access="public" returntype="void" output="false">
<cfargument name="property" type="any" required="true">
<cfset variables.property = arguments.property>
</cffunction>

--

Kevin Pepperman

unread,
Mar 7, 2010, 7:46:11 AM3/7/10
to coldspri...@googlegroups.com
I always thought it was supposed to use name based arguments, it may
be because CS cannot depend on the order that it accesses other
components, I could be wrong but I have always used the same name as
the property for the arguments.

I'm sure someone knows more about it than I do and will chime in if it
is an actual bug.

I'm glad you have it working now.

Brian Kotek

unread,
Mar 7, 2010, 9:44:46 AM3/7/10
to coldspri...@googlegroups.com
Since CF only added positional arguments in CF8, this would be screwing over people on earlier versions. That said, I wouldn't care much since 7 is so old and I'd think there are far more people on 8 and 9 than on 7.

Yes, this whole issue was caused by the need for CS to look for "named" arguments on properties and constructors, because until 8 the optimal solution, positional args, weren't there.


--
You received this message because you are subscribed to the Google Groups "ColdSpring-Users" group.
To post to this group, send email to coldspri...@googlegroups.com.
To unsubscribe from this group, send email to coldspring-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/coldspring-users?hl=en.


Elliott Sprehn

unread,
Mar 7, 2010, 1:57:01 PM3/7/10
to ColdSpring-Users
On Mar 7, 9:44 am, Brian Kotek <brian...@gmail.com> wrote:
> Since CF only added positional arguments in CF8, this would be screwing over
> people on earlier versions. That said, I wouldn't care much since 7 is so
> old and I'd think there are far more people on 8 and 9 than on 7.
>
> Yes, this whole issue was caused by the need for CS to look for "named"
> arguments on properties and constructors, because until 8 the optimal
> solution, positional args, weren't there.
>

If you want to maintain that level of backwards compatibility it just
needs to check if the property is real with structKeyExists() (allow
OnMethodMissing) and then use
getMetaData(beanInstance[prop]).parameters[1].name instead of
getArgumentName().

Only lines 939, 945 and 962 of DefaultXmlBeanFactory would need to be
updated. A pretty simple fix. :)

Elliott Sprehn

unread,
Mar 7, 2010, 1:47:32 PM3/7/10
to ColdSpring-Users
On Mar 7, 9:44 am, Brian Kotek <brian...@gmail.com> wrote:
> Since CF only added positional arguments in CF8, this would be screwing over
> people on earlier versions. That said, I wouldn't care much since 7 is so
> old and I'd think there are far more people on 8 and 9 than on 7.
>
> Yes, this whole issue was caused by the need for CS to look for "named"
> arguments on properties and constructors, because until 8 the optimal
> solution, positional args, weren't there.
>

If you wanted to maintain that level of backwards compatibility it
just needs to check if the property is real with structKeyExists() and
then use getMetaData(beanInstance[prop]).parameters[1].name to grab
the name.

Lines 939, 945, and 962 just need to change in DefaultXmlBeanFactory
from using getArgumentName() to using that.

Elliott Sprehn

unread,
Mar 7, 2010, 2:36:30 PM3/7/10
to ColdSpring-Users

On Mar 7, 1:47 pm, Elliott Sprehn <espr...@gmail.com> wrote:
> If you wanted to maintain that level of backwards compatibility it
> just needs to check if the property is real with structKeyExists() and
> then use getMetaData(beanInstance[prop]).parameters[1].name to grab
> the name.
>
> Lines 939, 945, and 962 just need to change in DefaultXmlBeanFactory
> from using getArgumentName() to using that.

Apologies for the dup. Groups said it didn't go through. :/

Reply all
Reply to author
Forward
0 new messages