Odd Autowire Error with ORM integration

I'm getting the following error when I have a property defined in a
component with the same name as another model (full stack trace
below).

Application Execution Exception
Error Type: Application : [N/A]
Error Messages: Entity has incorrect type for being called as a
function.
The symbol you provided setTEST2 is not the name of a function.

Here is the test case:

Models:

// test.cfc
  component persistent="true" accessors="true" {

  property name="test2";

  }

// test2.cfc
component {}

// coldbox.cfc settings:
    interceptors = [
      {class="coldbox.system.interceptors.Autowire",
       properties={entityInjection=true}
      } ];

I traced the issue through ColdBox it's picking up on the generated
getTest2 accessor as a setterInjector and is throwing the error when
calling the method with CFINVOKE. (MethodInjector.invokerMixin())

Some observations:

+ If I define an explicit setter for the setTest2 property there is no
error.
+ In MethodInjector.cfc If I use evaluate instead of cfinvoke I don't
get an error
   <cfset refLocal.results = evaluate
( "#arguments.method#( argumentCollection =
arguments.argCollection )" ) />

Any thoughts on this one? Latest SVN ColdBox, CF 9.0.1

thanks,

.brett

Full Stack Trace:
ID: CFINVOKE
LINE: 190
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system\plugins
\MethodInjector.cfc
ID: CFINVOKE
LINE: 1176
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system\plugins
\BeanFactory.cfc
ID: CF_UDFMETHOD
LINE: 661
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system\plugins
\BeanFactory.cfc
ID: CF_UDFMETHOD
LINE: 277
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system\plugins
\BeanFactory.cfc
ID: CF_TEMPLATEPROXY
LINE: 107
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system
\FrameworkSupertype.cfc
ID: CF_UDFMETHOD
LINE: 19
Template: E:\web\sites\cf9.local\webapps\ROOT\sampleapp\modules
\module1\handlers\Handler1.cfc
ID: CFINVOKE
LINE: 629
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system\web
\Controller.cfc
ID: CF_UDFMETHOD
LINE: 520
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system\web
\Controller.cfc
ID: CF_TEMPLATEPROXY
LINE: 210
Template: E:\web\sites\cf9.local\webapps\ROOT\coldbox\system
\Coldbox.cfc
ID: CF_UDFMETHOD
LINE: 45
Template: E:\web\sites\cf9.local\webapps\ROOT\sampleapp
\Application.cfc

Brett,

Did you setup an eventHandler in your ORM settings?
<cfset this.ormsettings = {
eventhandling=true,
eventhandler="model.ORMEventHandler"}

model.ORMEventHandler Example

/**
* @hint The ORM event handler. If using the entity injector and you
override a postLoad() handler, then you must
* call the super.postLoad(arguments.entity) manually.
* @output false
* @injector true
* @injectorInclude ''
* @injectorExclude ''
*/
component extends="coldbox.system.orm.hibernate.EventHandler"{

  public void function postLoad(any Entity){
    // call super method to activate injector
    super.postLoad(entity);
    // Use logbox to log some debug messages
    getLogger(this).debug("post load an entity:
#getMetaData(entity).name#");
  }

  public void function postUpdate(any Entity){
    // Use logbox to log some debug messages
    getLogger(this).debug("post update an entity:
#getMetaData(entity).name#");
    // Use the coldbox interceptors to announce AOP style
updates, so all AOP listners do audit
  
announceInterception("entityAudit",{entity=entity,auditType="update"});
  }
}

Curt Gratz
Computer Know How

Hey Curt,

Yes I am using the Coldbox Event Handler.

  this.ormEnabled = true;
  this.ormsettings = {
    datasource="mysampleApp",
    dbcreate="update",
    eventhandling=true,
    eventhandler = "coldbox.system.orm.hibernate.EventHandler",
    flushAtRequestEnd=false,
    logsql=true,
    cfclocation = ["model", "modules"] };

.brett

Is setter injection enabled on the autowire interceptor?

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Hi Luis - Setter injection is enabled by default so I don't have to
explicitly set this.

Hmm, I believe setter injection is turned off by default though

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

// enableSetterInjection
if(NOT propertyExists(“enableSetterInjection”) OR
NOT isBoolean(getProperty(‘enableSetterInjection’)) ){
setProperty(“enableSetterInjection”,‘false’);
}

Autowire.cfc

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

hmmm, let me trace why it is on here.

Either way the issue exists if you turn it on....

You are right, it is off by default, I had overlooked I turned it on
in my model config when I was debugging.

So the error originally reported occurs only when you have
setterInjection turned on.

.brett

Ok, so basically the problem is that the setter injection detects it and tries to set something on it but cfinvoke fails on cf9 orm auto-generated setters? That sounds like a bug to me on CF also.

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Yeah that is basically what is happening. I didn't test cfinvoke on a
generated setter outside of ColdBox to see if it was a CF specific
issue so I am not sure if it is ColdBox or ColdFusion

Hmm, seems cfinvoke does work, are you sure it is not something else?
Maybe the setter is being called for something that does not exist?
Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

I'm pretty sure. I tore all the code out of my models to isolate it
(code in the first post). I could bundle up the app and send it to
you if that would be an easier way to reproduce.

Yea send it over!
Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

I posted a sample here: http://drop.io/cbormissue/asset/sampleapp-zip

Call the following URL to see the error:

http://localhost/sampleapp/index.cfm?event=test:home.index

let me know that you see the issue.

thanks,

.brett

To get things moving on your end, have you tried ‘setter=false’ on that property?

Also, the new setter injection in wirebox will need the annotation as well. I prefer this approach if not ALL setter are inspected and is not congruent and a waste of time in my opinion. So it will follow the same pattern of property injection, in which only setters with the @inject annotation will be autowired.

THis will have to be the explicit case of ORM entities as they cannot be constructed from scratch as CF provides the entities for us, we can only intercept them. Does this make sense?

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Does the @inject annotation work in M5?

ACtually yes, the inject annotation works on :

  • cfproperty
  • constructor arguments
  • setter methods

However, right now it allows for setters without the annotation also. So the idea is to make them strict and only autowire annotated setters. That is the ticket.

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

I'm following ya Louis. Do you have any insight into what the error
was from?

Aaron - Yeah the work around was to not have a generated setter or
create an explicit setter in the component. I'm looking forward to
seeing the ticket closed sooner than latter though because I'm bad at
remembering to go back and refactor my code after issues are fixed.

.brett