Coldspring confusion

81 views
Skip to first unread message

Eapen

unread,
Mar 18, 2011, 12:04:45 AM3/18/11
to framew...@googlegroups.com
I am trying to use Coldspring in my FW/1 project (coldspring noob) and hit a stumbling block. 

My controller (managed by FW/1) is calling a service (implicit service calls disabled) which in turn calls the gateway - which requires the DSN. But the DSN is not being passed to the gateway.
The ColdSpring bean factory is loaded (I can dump the getBeanFactory().getBean("config") in my view), but I get an error:
"The CONFIG parameter to the init function is required but was not passed in.:"

I initially had my user service bean named as "userService" and then after reading through some of the other posts realized that the suffix of "Service" might be causing some confusion and renamed it to "userSvc". But still no luck...
I am pretty sure I am confused by the "setService" calls and what is handled by ColdSpring and what is being handled by FW/1. I have gone through the Wiki + older posts without any progress and I am pretty brain-dead now. Please let me know if I need to provide any additional info.

Below is a stripped down structure of the code:

wwwroot
--assets
  --coldspring
    --coldspring.xml
--controllers
   --main.cfc
--model
  --gateway
    --user.cfc
  --model
    --user.cfc
  --services
    --user.cfc
--views
  --main
    --default.cfm


Below are the snippets to the relevant parts:

assets/coldspring/coldspring.xml:

<?xml version="1.0" encoding="utf-8"?>
<beans>
<bean id="config" class="coldspring.beans.factory.config.MapFactoryBean">
<property name="SourceMap">
<map>
<entry key="dsn"><value>DATASOURCE</value></entry>
</map>
</property>
</bean>
<bean id="utils" class="cfc.utils.util" />
<bean id="userSvc" class="model.services.user">
<property name="userGateway"><ref bean="userGateway" /></property>
<property name="utils"><ref bean="utils" /></property>
</bean>
<bean id="userGateway" class="model.gateway.user">
<construct-arg name="config"><ref bean="config" /></construct-arg>
</bean>
</beans>

controller/main.cfc:


    <cffunction name="setUserSvc" output="false" access="public" returntype="any">    
     <cfargument name="userSvc" required="true">    
     <cfset variables.userSvc = arguments.userSvc>
    </cffunction>
    
    <cffunction name="setUtils" output="false" access="public" returntype="any">    
     <cfargument name="utils" required="true">    
     <cfset variables.utils = arguments.utils>
    </cffunction>


<cffunction name="default" output="true" hint="Default action">
<cfargument name="rc" type="struct" />
<cfset rc.users = variables.userSvc.doSomething() />
    </cffunction>


model/services/user.cfc:


<cffunction name="init" output="false" access="public">
<cfreturn this />
</cffunction>
<cffunction name="setUserGateway" output="false" access="public" returntype="any">    
     <cfargument name="userGateway" required="true">    
     <cfset variables.userGateway = arguments.userGateway>
    </cffunction>
    
    <cffunction name="setUtils" output="false" access="public" returntype="any">    
     <cfargument name="utils" required="true">    
     <cfset variables.utils = arguments.utils>
    </cffunction>
    <cffunction name="doSomething" output="false" access="public">
<cfset var qUser = variables.userGateway.doSomethingElse( ) />
<cfreturn qUser />
</cffunction>

model/gateway/user.cfc:
<cfset variables.instance = {}>
<cfset variables.instance.dsn = "">
<cffunction name="init" output="false">
<cfargument name="config" required="true">
<cfset variables.instance = arguments.config> <!--- this is where the error occurs--->
<cfreturn this />
</cffunction>


<cffunction name="doSomethingElse" access="public" output="false">
           ....


Thanks for making it to the bottom of the email :-)

Dutch Rapley

unread,
Mar 18, 2011, 9:29:23 AM3/18/11
to framew...@googlegroups.com
From the looks of it, I'm guessing you're on CF8, so you might have to adjust my examples accordingly.
 
I initially had my user service bean named as "userService" and then after reading through some of the other posts realized that the suffix of "Service" might be causing some confusion and renamed it to "userSvc". But still no luck...

If you want to queue up your services with FW/1 fw.service() method, your service bean name will need to be userService - you would queue this up in your controller with fw.service("user.doSomething"). since you have implicit service calls turned off, it's still OK for this bean to be called UserService.

 
Below are the snippets to the relevant parts:

assets/coldspring/coldspring.xml:

<?xml version="1.0" encoding="utf-8"?>
<beans>

I prefer to auto wire:

<beans default-autowire="byName">

When I first started working with ColdSpring, I thought I'd want to explicitly declare constructor and/or property injection so I could look at my config file and know what's going on. Also, I've learned to steer clear of constructor injection. Always do property injection if you can help it.
 
<bean id="config" class="coldspring.beans.factory.config.MapFactoryBean">
<property name="SourceMap">
<map>
<entry key="dsn"><value>DATASOURCE</value></entry>
</map>
</property>
</bean>
 
You don't need the above. Instead, create a Datasource.cfc. I'd place it wwwroot/model/settings/Datasource.cfc

if you're on CF9, it'll look like:

component accessors="true" {
  property name="name"
}

If you're on CF8, you'll need to write the appropriate getter/setter pair.


Your coldspring config file should look like:
 
<?xml version="1.0" encoding="utf-8"?>
<beans default-autowire="byName">
<bean id="datasource" class="model.settings.Datasource">
<property name="name"> <value>DATASOURCE</value> </property>
</bean>
<bean id="utils" class="cfc.utils.util" />
<bean id="userService" class="model.services.user" />
<bean id="userGateway" class="model.gateway.user" />
</beans>

Each CFC should have the following init

function init() {
  return this;
}
 
In your userGateway, you'll need to add getDatasource()/setDatasource(). When you need to call it for cfquery, you can simply do getDatasource().getName().

HTH,
Dutch

Eapen

unread,
Mar 18, 2011, 10:47:06 AM3/18/11
to framew...@googlegroups.com
Dutch - THANK YOU!! 

I am on CF9 and it does look like the "default-autowire" was the issue. I am kicking myself for the hours I wasted trying to figure this out yesterday.  I also appreciate the guidance about using property injection vs constructor injection. 

With great relief,
Eapen. 

--
FW/1 on RIAForge: http://fw1.riaforge.org/
 
FW/1 on github: http://github.com/seancorfield/fw1
 
FW/1 on Google Groups: http://groups.google.com/group/framework-one

Dutch Rapley

unread,
Mar 18, 2011, 10:59:21 AM3/18/11
to framew...@googlegroups.com
I am on CF9 and it does look like the "default-autowire" was the issue.

Since you're on CF9, you don't need the setters/getters for auto wiring in ColdSpring. All you need is to set accessors="true" on your CFC and declare your  properties.

If you want to auto wire your beans into your controllers, you'll have to still write the setters/getters in your controllers (as long as FW/1 is managing your controllers). It has to do with how FW/1 currently finds methods in your controllers and matches them to available services, along with how CF doesn't create "keys" on the cfc for dynamically created getters and setters. I do believe this behavior will change in FW/1 v2 and will work in a similar fashion to how ColdSpring handles it.

-Dutch

Sean Corfield

unread,
Mar 18, 2011, 3:07:56 PM3/18/11
to framew...@googlegroups.com
On Thu, Mar 17, 2011 at 9:04 PM, Eapen <gea...@gmail.com> wrote:
> <bean id="userGateway" class="model.gateway.user">
> <construct-arg name="config"><ref bean="config" /></construct-arg>

This should be <contructor-arg ...>...</constructor-arg>
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

Dutch Rapley

unread,
Mar 18, 2011, 3:19:17 PM3/18/11
to framew...@googlegroups.com
good eye Sean, I suppose I should have looked more closely at the xml instead of pushing my own personal preferences.

Eapen

unread,
Mar 21, 2011, 10:43:08 PM3/21/11
to framew...@googlegroups.com
On Fri, Mar 18, 2011 at 15:07, Sean Corfield <seanco...@gmail.com> wrote:
On Thu, Mar 17, 2011 at 9:04 PM, Eapen <gea...@gmail.com> wrote:
> <bean id="userGateway" class="model.gateway.user">
> <construct-arg name="config"><ref bean="config" /></construct-arg>

This should be <contructor-arg ...>...</constructor-arg>
 
Blimey! Thanks Sean! Weird that it still worked that day when I made the "autowire" edit. Need to look at it again with a clear head tomorrow morning. I suspect some of the code I originally had in the Application scope was interfering with me trying to troubleshoot the problem.

Sean Corfield

unread,
Mar 22, 2011, 12:55:14 PM3/22/11
to framew...@googlegroups.com
On Mon, Mar 21, 2011 at 7:43 PM, Eapen <gea...@gmail.com> wrote:
> Blimey! Thanks Sean! Weird that it still worked that day when I made the
> "autowire" edit.

You probably had a setter in there (which wouldn't have been called
unless you made autowire the default or used a property tag).

FWIW, this is the sort of problem I'm hoping to avoid with DI/1 by
simplifying the number of ways you can wire stuff together. DI/1 won't
be for everyone and it certainly won't be for people who desperately
want absolute control over every aspect of autowiring, but I hope to
get the conventions working well enough for _most_ users and _most_
situations. And there will be no XML (of course).


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

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

World Singles, LLC. -- http://worldsingles.com/
Railo Technologies, Inc. -- http://www.getrailo.com/

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

Reply all
Reply to author
Forward
0 new messages