Using dynamically generated setters inside a dynamic Java proxy using createDynamicProxy()

Posted by Dan on Nov 19, 2014 @ 12:08 PM

There's not a ton of information out there on using ColdFusion Components from within Java, so I wanted to document a problem I was having. I'm in the process of evaluating using Drools as a Rules Engine to use within ColdFusion. One of the problems you face in using Drools, is you need to represent your CFC in a way that Drools can work with it. This means you need to do a couple of things:

  1. Create a proxy to the CFC which can be used by Java. This can be done in ColdFusion 10 using the createDynamicProxy() function, but it requires that you build an Java Interface that represents your CFC.
  2. Create a Java proxy class, which is used by Drools.

Setting all this up was pretty straight forward.

The problem that I was running into, was I could never successfully call the "setter" on a CFC object that was created dynamically using the "accessors='true'" option on my CFC.

Here was my very simple CFC:

component output="false" persistent="false" accessors="true" {
  property
    name="name"
    type="string"
  ;

  property
    name="age"
    type="numeric"
    default="-1"
  ;

  property
    name="valid"
    type="boolean"
    default="true"
  ;
}

The problem is, every time I'd try to call the setter on my dynamic proxy item, I'd see an like "java.lang.ClassCastException: coldfusion.runtime.TemplateProxy".

The Java interface I was using, looked like this:

public interface ApplicantInterface {
  public String getName();
  // automatic setters, return "this" which is a reference to the proxy object
  public void setName(String name);

  public int getAge();
  // automatic setters, return "this" which is a reference to the proxy object
  public void setAge(int age);

  public boolean getValid();
  // automatic setters, return "this" which is a reference to the proxy object
  public void setValid(boolean valid);
}

Accessing the getters() worked as expected, so I knew there was something in the way the setters were working that was causing a problem.

After dumping out the metadata for my CFC, I finally discovered the issue.

When CF10 automatically creates setters, the return type on the objects is not void, but instead is a references to the CFC itself.

There are two ways to resolve the problem:

  1. Manually create your setter methods. You can do this by adding the "setter='false'" hint to your parameter and then manually creating all the setters.
  2. Change your interface return type from "void" to "coldfusion.runtime.TemplateProxy".

I decided to use option #2. Here's what my final interface looked like:

public interface ApplicantInterface {
  public String getName();
  // automatic setters, return "this" which is a reference to the proxy object
  public coldfusion.runtime.TemplateProxy setName(String name);

  public int getAge();
  // automatic setters, return "this" which is a reference to the proxy object
  public coldfusion.runtime.TemplateProxy setAge(int age);

  public boolean getValid();
  // automatic setters, return "this" which is a reference to the proxy object
  public coldfusion.runtime.TemplateProxy setValid(boolean valid);
}

In order to use a return type of "coldfusion.runtime.TemplateProxy", you'll need to make sure to add the cfusion.jar to the classpath when compiling your code. For example:

javac -g  -cp {{ColdFusion 10 Install Folder}}\cfusion\lib\cfusion.jar -d ./bin/ ./src/*.java

Hope this helps someone else in the future!

Categories: HTML/ColdFusion, Java

Comments for this entry have been disabled.