Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created March 25, 2014 11:00
Instantiating Groovy Classes In The ColdFusion Context
<!--- Import the CFGroovy tag library. --->
<cfimport prefix="g" taglib="./cfgroovy/" />
<!---
The Groovy script tag caches the Java loader in the Server
scope. For testing purposes, we are going to clear it out
(as I think it caches the available classes??).
NOTE: This might be completely wrong!!
--->
<!--- <cfset structDelete( server, "cfgroovy" ) /> --->
<g:script>
<!---
Define the GroovyFactory class. This is the class that
will allow ColdFusion to instantiate Groovy-bound classes
once back inside the ColdFusion context. This is because
Groovy is lexically-bound, meaning that it has access to
the variables / class in the context in which it was
defined. As such, once an instance of this is passed out
of Groovy, it will still have access to this Groovy
context.
--->
class GroovyFactory {
<!---
This method returns a Groovy class proxy using the
given class name such that new instances can be
instantiated in such a manner:
GroovyFactory.get( className ).init( arg, ... arg );
Basically, I just wanted to be able to seperate the
class name from the list of constructor arguments.
--->
public get( String className ){
return(
new GroovyFactoryInstanceProxy(
java.lang.Class.forName(
className,
false,
this.getClass().getClassLoader()
)
)
);
}
}
<!---
Define the Groovy instance proxy class. This class is a
proxy for the constructor of the target class. It
containst the class definition internally such that the
init() method can be called with a list of N arguments.
--->
class GroovyFactoryInstanceProxy {
<!--- Store the class internally. --->
private def targetClass = null;
<!---
This is the constructor for the proxy. It simply
stores the target class definition for use in the
init() method call.
--->
public GroovyFactoryInstanceProxy( Class targetClass ){
this.targetClass = targetClass;
}
<!---
This is the actual factory method for the current
target class. It takes N arguments (max of 10)
arguments, which it converts into an array that will
be used to call the target classes constructor
(using the reflection method - newInstance()).
NOTE: I am using 1-10 here because I could not yet
figure out how to have a variable number of arguments
that did NOT require them to be an array when called
from ColdFusion.
--->
public init(
Object a1 = null,
Object a2 = null,
Object a3 = null,
Object a4 = null,
Object a5 = null,
Object a6 = null,
Object a7 = null,
Object a8 = null,
Object a9 = null,
Object a10 = null
){
<!---
Create a local collection of arguments that we
will use during our constructor call on the
target class.
--->
def arguments = [];
<!---
Loop over each argument that was passed to this
method, and, if it is NOT NULL, then add it to
the collection of arguments we will use to
instantiate the target class.
NOTE: We are using an Closure here who's first
argument is implicit stored in the variable, "it".
--->
[ a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 ].each({
if (it){
arguments.add( it );
}
});
<!---
Return a new instance of the target class using
the mapped arguments array.
--->
return(
this.targetClass.newInstance( arguments.toArray() )
);
}
}
<!---
Store the Groovy Factory instance in the ColdFusion
variables scope so that we can now access this ENTIRE
Groovy context (via the Factory) from ColdFusion.
--->
variables.groovyFactory = new GroovyFactory();
<!--- ------------------------------------------------- --->
<!--- ------------------------------------------------- --->
<!--- Groovy Class Definitions ------------------------ --->
<!--- ------------------------------------------------- --->
<!--- ------------------------------------------------- --->
class Person {
private def name = "";
private def hair = "";
private def gender = "";
public Person(){
<!--- Nothing to do here. --->
}
public Person(
String name,
String hair = null,
String gender = null
){
<!--- Store properties. --->
this.setName( name );
if (hair){
this.setHair( hair );
}
if (gender){
this.setGender( gender );
}
}
public String getName(){
return( this.name );
}
public Object setName( value ){
this.name = value;
return( this );
}
public String getHair(){
return( this.hair );
}
public Object setHair( value ){
this.hair = value;
return( this );
}
public String getGender(){
return( this.gender );
}
public Object setGender( value ){
this.gender = value;
return( this );
}
};
class Relationship {
def private Person person1;
def private Person person2;
public Relationship(
Person person1,
Person person2
){
this.person1 = person1;
this.person2 = person2;
}
public String toString(){
return(
(
person1.getName() +
(
person1.getHair().length() ?
(" (" + person1.getHair() + ") ") :
""
) +
" is dating " +
person2.getName() +
(
person2.getHair().length() ?
(" (" + person2.getHair() + ") ") :
""
) +
" ... awesome!"
)
);
}
};
</g:script>
<!--- Create a girl. --->
<cfset sarah = groovyFactory.get( "Person" ).init(
"Sarah",
"Brunette",
"Female"
) />
<!--- Create a boy (using a slightly different syntax). --->
<cfset ben = groovyFactory.get( "Person" ).init()
.setName( "Ben" )
.setHair( "Brunette" )
.setGender( "Male" )
/>
<!--- Create a relationship. --->
<cfset relationship = groovyFactory.get( "Relationship" ).init(
sarah,
ben
) />
<!--- Output the relationship string. --->
<cfoutput>
#relationship.toString()#<br />
</cfoutput>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment