Using Lucee in Java

Using Lucee within Java

While Lucee allows you to do almost everything your web application will need to do by using CFML code, there may be times when you will need to use Lucee from Java applications.

Since Lucee is written in Java and is running inside a Java Virtual Machine (JVM), using Lucee from your Java applications is very easy.

Adding Lucee to your Java Project

The first thing you will need to do is to add lucee.jar to your classpath, so that you will have access to the classes and interfaces that Lucee provides. If you are using an IDE like Eclipse or Netbeans, then you simply add the lucee.jar library to your project.

Once you added lucee.jar to your project, you should have access to all of Lucee's public classes and interfaces. In order to access them you will need to add the import statement to the top of your class file. Be sure to add an import statement for each of the classes / interfaces that you plan to use in that class. You can review the Lucee JavaDoc files.

Using Lucee from your Java code

There are two cases in which you might want to use Lucee from your Java code:

  • When your Java code is loaded into the JVM through Lucee.
  • In a standalone application detached from a Lucee web app.

When your Java code was loaded by Lucee

The easiest way to use Lucee from your Java code is when your Java code was loaded by Lucee. This is a common case when, for example, your CFML code creates a Java object, and then that Java object creates Lucee objects and calls CFC methods.

Your interaction with Lucee should start via an object that implements the lucee.loader.engine.CFMLEngine interface and the lucee.runtime.PageContext object. Since Lucee loaded your Java code, and it will be running in that very same JVM, you can get a reference to a CFMLEngine object by calling the getInstance() static method of the lucee.loader.engine.CFMLEngineFactory object.

import	lucee.loader.engine.*;
...
public class MyClass {
<span class="n">CFMLEngine</span>	<span class="n">engine</span>	<span class="o">=</span> <span class="n">CFMLEngineFactory</span><span class="o">.</span><span class="na">getInstance</span><span class="o">();</span>
<span class="n">PageContext</span> 	<span class="n">pc</span> 	<span class="o">=</span> <span class="n">engine</span><span class="o">.</span><span class="na">getThreadPageContext</span><span class="o">();</span>
<span class="o">...</span>

}

in the following examples in this document "engine" will refer to a lucee.loader.engine.CFMLEngine object, and "pc" will refer to a lucee.runtime.PageContext object.

When Lucee does not load your Java code

Lucee 5

With Lucee 5 doing this is a lot easier now.

CFMLEngine engine = CFMLEngineFactory.getInstance();
		// cookies for this simulated request, can also be null
		javax.servlet.http.Cookie[] cookies = new Cookie[]{new Cookie("myCookie","myCookieValue")};
	<span class="c1">// headers for this simulated request</span>
	<span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">headers</span><span class="o">=</span><span class="k">new</span> <span class="n">HashMap</span><span class="o">();</span>
	<span class="n">headers</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">&quot;accept&quot;</span><span class="o">,</span><span class="s">&quot;text/html&quot;</span><span class="o">);</span>
	<span class="c1">// headers for this simulated request, can also be null</span>
	<span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">parameters</span><span class="o">=</span><span class="k">new</span> <span class="n">HashMap</span><span class="o">();</span>
	<span class="c1">// headers for this simulated request, can also be null</span>
	<span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">attributes</span><span class="o">=</span><span class="k">new</span> <span class="n">HashMap</span><span class="o">();</span>
	<span class="n">PageContext</span> <span class="n">pc</span> <span class="o">=</span> <span class="n">engine</span><span class="o">.</span><span class="na">createPageContext</span><span class="o">(</span>
			 <span class="s">&quot;localhost&quot;</span> <span class="c1">// host</span>
			<span class="o">,</span><span class="s">&quot;/index.cfm&quot;</span> <span class="c1">// script name</span>
			<span class="o">,</span><span class="s">&quot;test=1&quot;</span> <span class="c1">// query string</span>
			<span class="o">,</span><span class="n">cookies</span>
			<span class="o">,</span><span class="n">headers</span>
			<span class="o">,</span><span class="n">parameters</span>
			<span class="o">,</span><span class="n">attributes</span>
			<span class="o">,</span><span class="n">System</span><span class="o">.</span><span class="na">out</span> <span class="c1">// response stream where the output is written to</span>
			<span class="o">,</span><span class="mi">50000</span> <span class="c1">// timeout for the simulated request in milli seconds</span>
			<span class="o">,</span><span class="kc">true</span> <span class="c1">// register the pc to the thread</span>
			<span class="o">);</span>
	<span class="k">try</span><span class="o">{</span>
		<span class="c1">// use the pc</span>
	<span class="o">}</span>
	<span class="k">finally</span><span class="o">{</span>
		<span class="n">engine</span><span class="o">.</span><span class="na">releasePageContext</span><span class="o">(</span><span class="n">pc</span><span class="o">,</span> <span class="kc">true</span><span class="cm">/* unregister the pc from the thread*/</span><span class="o">);</span>
	<span class="o">}</span>

Using the Lucee objects from Java

once you have a reference to the CFMLEngine and the PageContext objects, you can easily interact with Lucee from your code. Here is an example on how to get / set Lucee values from within your Java code:

// get a reference to the Application Scope:
Scope	appScope	=	pc.applicationScope();

// get a value from the Application Scope: String appName1 = appScope.get( "ApplicationName" );

// you can also get the value from the PageContext directly: String appName2 = pc.getVariable( "Application.ApplicationName" );

if ( !appName1.equals( appName2 ) ) throw CFMLEngineFactory.getInstance().getExceptionUtil().createApplicationException( "WTF?!@#" );

you can also set variables in a similar manner:

// this is the Java equivalent of <cfset Application.javaTime = getTickCount()>
pc.setVariable( "Application.javaTime", System.currentTimeMillis() );

then in your CFML code, you can use this value like so:

<cfoutput>The Tick Count set from Java was: #Application.javaTime#</cfoutput>

in the same way you can get a reference to other objects in the different scopes. For example, if in onApplicationStart() (of Application.cfc) your Lucee code creates somewhere a component and sets a reference to it in Application.myCfc

<cffunction name="onApplicationStart">
<span class="nb">&lt;cfset</span> <span class="nv">Application.myCfc</span> <span class="o">=</span> <span class="nf">createObject</span><span class="p">(</span> <span class="s2">&quot;component&quot;</span><span class="p">,</span> <span class="s2">&quot;my.lib.Comp&quot;</span> <span class="p">)</span><span class="nb">&gt;</span>

</cffunction>

then you can get a reference to it in Java like this:

Component cfc = (Component) pc.getVariable( "Application.myCfc" );

if ( cfc != null ) { ... do something with cfc ... }

alternatively, if you want to create a new CFC in your Java code, you can use the PageContext's loadComponent method:

// this will cause Lucee to search it's component mapping paths for my.lib.Comp and create a new component
Component cfc = pc.loadComponent( "my.lib.Comp" );

// set it to a variable in the Application scope pc.setVariable( "Application.myCfc", cfc );

Calling CFC Methods from Java

once you have a reference to a CFC you can invoke its methods by using the call() or callWithNamedValues() methods:

calling method with no arguments

// call the CFC's function getLastName with no args (empty array):
String lastName = (String) cfc.call( pc, "getLastName", new Object[0] );

calling method with ordered arguments

// execute the cfc with ordered arguments
cfc.call( pc, "setLastName", new Object[]{ "Smith" } );

calling method with named arguments

// execute the cfc with named arguments
Struct	args	=	engine.getCreationUtil().createStruct();
args.set( "name", "Smith" );
cfc.callWithNamedValues( pc, "setLastName", args );

Other Useful Methods of the PageContext class

Get Lucee Scopes

Scope varialbesScope	= pc.variablesScope();

Scope requestScope = pc.requestScope();

Scope sessionScope = pc.sessionScope();

Scope applicationScope = pc.applicationScope();

Get/Set Variables

// get variable by using its fully qualified name
String username = (String) pc.getVariable( "session.username" );

// set variable by using its fully qualified name pc.setVariable( "session.username", "Susanne" );

// get variable from scope obtained earlier String username = (String) sessionScope.get( "username" );

// set variable in scope obtained earlier sessionScope.set( "username", "Susanne" );

(of course, as with your CFML code, you should only set values to shared objects in a synchronized manner)

Create CF Objects

// get a reference to the creation utility class
Creation	creationUtil		=	engine.getCreationUtil();

// create CF Array lucee.runtime.type.Array cfArray = creationUtil.createArray();

// create CF Struct lucee.runtime.type.Struct cfStruct = creationUtil.createStruct();

// create CF Query named qNames with two columns (firstName and lastName) and 1 row lucee.runtime.type.Query cfQuery = creationUtil.createQuery( new String[]{ "firstName","lastName" }, 1, "qNames" );

Decision Util

Decision decisionUtil = engine.getDecisionUtil();

if ( decisionUtil.isDate( obj, false ) || decisionUtil.isStruct( obj ) );

Operations Util

Operation opUtil = engine.getOperatonUtil();
int c = opUtil.compare( left, right );	// cfml comparison rules
if ( c < 0 ) {
	// negative value = "left" is Less Than "right"
} else if ( c > 0 ) {
	// positive value = "left" is Greater than "right"
} else {
	// zero = "left" Equals "right"
}

Casting

Cast castUtil	=	engine.getCastUtil();
castUtil.toArray( obj );
castUtil.toStruct( obj );

Exceptions Util

Excepton exp = engine.getExceptionUtil();

if ( doAbort ) throw exp.createAbort(); else throw exp.createApplicationException( "this is wrong", "you cannot ..." );

Evaluate

Object	obj =	pc.evaluate( "url.test=len( 'Lucee is awesome!' )" );	// same as function evaluate(string)

Serialize

String str = pc.serialize( obj ); // same as function serialize(object)