Language_And_Syntax_Differences - getrailo/railo GitHub Wiki

Table of Contents

Architecture

Adobe ColdFusion (ACF) is configured in a way that only one single web context is available for a server instance. This means that if you do not secure your single applications they might become vulnerable, you will have to use sandbox security, single instances, etc... This and the fact that you do not have the ability to configure individual CF settings for each virtual host are the major disadvantages of this setup. A big advantage however is the fact that a virtual host only needs to be defined in the web server configuration in order to properly be picked up by ACF.

When setting up Railo Server in an older configuration the definition of the virtual host always had to be done in two places, the web server and application server configuration. The biggest downside was that specific application servers always had to be restarted (like Tomcat or JBoss) in order for the changes to be initiated. Other application servers like Jetty and Resin accepted the new virtual host without requiring a restart. This simply depends on the application server implementation.

With the introduction of mod_cfml for Tomcat these changes in the server.xml configuration file do not have to be made anymore, therefore restarting Tomcat is no longer necessary. The changes will be picked up automatically when the web server sends an unknown host to Tomcat with the corresponding root directory.

Administration

In terms of administration, the biggest difference between Railo Server and ACF is that Railo Server has an individual administrator for each virtual host definition and a server administrator for global definition or defaults. ACF only has one, which approximately correlates to the server administrator in Railo Server.

Auto include files

Railo Server will not search auto include files (Application.cf*, onRequestEnd.cfm, etc...) outside of the web root. Depending on a setting in the administrator, ACF can search for auto include files up to the root of the drive the requested file is located on. If there is a virtual mapping that points to a different drive than the drive the web root lies on, ACF will crawl up the entire directory tree in order to find any auto include files.

Relative paths

In Railo Server relative paths can be used in any file related operation. With ACF it can end up starting at the directory root. Have a look at the following example:

We assume that the web root is located in the folder D:\project\myWebRoot\.

<cfdirectory action="list" directory="/" name="get"> <cfdump var="#get#">

The result will contain all files in the directory D:\project\myWebRoot\ in Railo Server and in ACF all files located under D:\.

Mappings

In Railo Server mappings can be made web accessible. This is necessary since the Railo administrator is delivered from a compiled archive (Railo archive) which is not really physically accessible to the application server or even the web server. This is not possible in ACF. Therefore if you define a mapping in Railo and you want to have it available through the web server, just tick the checkbox in the corresponding detail page of the respective mapping.

Tags

Not supported tags

  • cfapplet
  • cfgrid*
  • cfreport*
  • cftree
  • cfformitem
  • cfformgroup
  • cfexchange*
  • cfpresent*
  • cfpod
  • cfprint
  • cfslider
  • cfsprydataset
  • cftooltip
  • cfcalendar
  • cfpdfform
  • cfpdfformparam
  • cfpdfsubform

Tags supported with limitations

cfapplication
The value "registry" is not supported for the attribute "clientstorage", but Railo Server supports the value "file" (which stores the client variables in the local file system) or a cache name (both not supported by ACF)
cfchart
No support for the attributes gridlines, seriesPlacement, styles, tipbgcolor, tipstyle, xAxisType and yAxisType
Combined charts are not possible yet.
The tag CFChart is under work at the moment. In addition there are several client side charting libraries available for Railo.
cfcache
No support for the attributes username and password
cfcomponent
No support for the attributes style, namespace, serviceportname, serviceaddress, porttypename, wsdlfile and alias
cfdocument
No support for the attributes backgroundvisible, fontembed, scale and evalAtPrint
There are some things in CFDocument that rely on the underlying Java library that each CFML engine uses. Therefore formatting issues can occur.
cferror
Only supports type "exception".
cffeed
No support for the attribute columnMap.
No support for the attribute escapeChars.
cfform
No support for the attributes preserveData, archive, codebase, skin, with, height, preloader, timeout and wMode
Accessible restricted support for attribute format, only the value "html" is supported.
No automatic creation of ID attribute on rendered HTML when tag doesn't define an ID
cfindex
No support for the attributes prefix and throwontimeout.
cfinput
No support for the attributes validateAt, enabled, visible and tooltip.
No support for xml and flash controls.
No automatic creation of ID attribute on rendered HTML when tag doesn't define an ID
cfinvoke
No support for the attributes servicePort and timeout.
cfinvokeargument
No support for the attribute omit.
cfldap
No support for the attribute rebind.
cflogin
No support for the attributes idletimout, applicationtoken and cookiedomain.
cfobject
No support for CORBA and EJB.
cfmail
No support for the attributes maxrows, query, group, startrow and priority.
cfpdf
No support for the attributes ddxfile, action="extractText", flatten, inputfiles, isbase64, order, outputFiles, saveOption and showOnPrint.
cfpop
No support for the attribute debug.
cfsearch
No support for the attribute previousCriteria.
cfselect
No support for the attributes label, height, width, tooltip, visible and editable.
No automatic creation of ID attribute on rendered HTML when tag doesn't define an ID
cftextarea
No support for the attribute basepath, value, validate, tooltip, validateAt, html, richtext, skin, templatesXML, toolbar, toolbarOnFocus and wrap.
No automatic creation of ID attribute on rendered HTML when tag doesn't define an ID
AJAX tags
Many of the AJAX tags have been implemented, but there might be some limitations regarding functionality. These tags are implemented as requested.
We always recommend using JS tools instead of these tags and functions since the built-in AJAX functions are based on the version of the framework that ships with the version of the Railo Server you are working with.

Functions

Unsupported functions

  • isDDX
  • isPDFFile
  • getPrinterInfo
  • queryConvertForGrid
  • verifyClient
  • dotNetToCFType

Supported functions with limitations

createObject
No support for type CORBA and .net.
rand
No support for the "IBMSecureRandom" algorithm.
serializeJSON()
Railo Server has a much closer format handling in JSON than ACF.

Web Services

Since ACF is running on AXIS2 there could be some incompatibilities in a small number of cases with complex web services. Railo is currently changing it's underlying web service model to CFX which is a new project for web services to replace AXIS2 as the AXIS2 project is more or less discontinued. This web service implementation will be completely compatible to the functionality that AXIS2 implements.

Language & syntax differences

Below all deviations from CFML standard syntax as well as the different runtime behaviours are described.

Date comparison

The CFML Standard determines, that a string comparison in "if" clauses always has to be checked, whether the two compared strings could be date values, for example:

<cfif "01/01/2000" EQ "01.01.00">

Railo only checks if both strings are dates if on at least one side of a comparison there is a date value. This checking is done at compile time. For example:

<cfif query.lastAccess EQ "01.01.00">

The reason for this is that only in rare cases the two strings contain date values. To check these strings for date values is very time consuming and only done if desired.

If you nevertheless want to check whether the two strings contain date values, you should use the function parseDateTime to translate a variable or a string into a date value. For example

<cfif parseDateTime(strDate) EQ parseDateTime("01.01.00")>

Date parsing

Railo does not support implicit parsing of a date value in the locale format, for example:

<cfif now() EQ "Wednesday, January 30, 2002 7:02:12 AM PST">

In order to achieve this you have to use the function parseDateTime, for example:

<cfif now() EQ parseDateTime("Wednesday, January 30, 2002 7:02:12 AM PST")>

Again the reason for this is, that implicit parsing of strings to locale date formats is very time consuming.

Boolean values converted into a string

If you convert a boolean value into a string Railo generates the following values:

  • true into "true"
  • false into "false"
In the CFML standard a boolean will be converted into the above values only in compile time. At runtime boolean values are converted as follows:
  • true into "Yes"
  • false into "No"
Example:
<cfoutput>#true#</cfoutput>
  • Output Railo and CFML Standard: true
<cfoutput>#1 EQ 1#</cfoutput>
  • Output Railo: true
  • Output CFML Standard: Yes

Switch/case in cfscript

ACF allows the omitting of spaces between the case statement and the value in parenthesis. So the following code will break in Railo Server:

<cfscript>
	switch(arguments.action) {
		case("caseA"): {
			doSomething;
			break;
		}
		case("caseB"): {
			doSomethingElse;
			break;
		}
		default: {
		//no action
		}
	}
</cfscript>

Railo assumes case() is a function and therefore generates a syntax error message. This behaviour has changed in Railo 4.2 since with the new tag notation in cfscript, the above example will now work.

Searching CFCs & in the Custom Tag directory

In ACF CFC's are searched for inside all the defined custom tag directories as well. In addition they are searched for recursively in the sub directories of all the custom tag directories.

By default and for performance reasons, this is not supported by Railo Server, however you can define individual directories where Railo Server searches for CFCs, as well as being able to enable deep search, including sub directories. To do this simply add the custom tag directories under the setting component in the Railo Server administrator.

Keys containing dots

If a variable key has a dot in ACF it allows you to address this variable as if you had 2 keys, for example:

variables["a.b.c"]="Susi";
writedump(variables["a.b.c"]); // This works in ACF and Railo Server
writedump(variables.a.b.c); // This works in ACF but fails in Railo Server, because there is no key "a" in the variables scope!

The following construct also works in ACF:

1: variables["request.susi"]="Susi";
2: writedump(request.susi); // This works in ACF even though there is no key "susi" in the request scope! 

Railo Server does not support implicit addressing of keys. The reason for this is the fact that the above code can be completely misread and that programmers might have the, absolutely legitimate, impression that there should be a key called "susi" in the request scope, if they only looked at line 2.

To make handling these issues easier, Railo Server has a built-in-function called structKeyTranslate() that converts a variable which contains dots in its name into cascading structures, for example:

variables["a.b.c"]="Susi";
structKeyTranslate(variables, true, true);
dump(variables);

The above will generate a structure like this:

{a:{b:{c:"Susi"}}, "a.b.c":"Susi"}

Annotations

In cfscript annotations can be used in order to "decorate" functions and their arguments. Unlike ACF, Railo Server never overwrites attributes that change the behaviour of the function itself. So attributes like output, returntype, returnformat can not be set using annotations. These annotations will be ignored in Railo Server.

Example:

/**
* my Hint
* @prop1 Property 1
* the rest of the hint
*/ function test(arg1){ }

Now if you call getMetaData(test) you will get a struct that contains additional keys (in this case prop1). Other implementations allow you to define each possible argument of a function in annotation style, just like this:

/**
*
* @returntype string
*/
function test(arg1) { }

This notation and thus the functionality behind it means, that comments are affecting the code's behaviour, which Railo Server does NOT support. The following example will throw a compiler error:

/**
* @returntype string
*/

public int function test(arg1) {
}

ACF throws the following error:

Attribute validation error. A duplicate attribute RETURNTYPE has been encountered. Attributes with the same name cannot be provided more than once.

Railo will simply ignore the parts of the comment if it affects the code execution at runtime. In our opinion you should never receive a compiler error because of a comment you have made in your code. In ACF even the following would throw an error, which is wrong since it IS just a comment:

/**
* please never ever use the comment
@returntype since this might crash
something in the compiler.
*/
public int function test(arg1) {
}

Railo Server always ignores definitions which contain doc comments that might interfere with allowed arguments of a function definition (like output, returntype etc.).

Railo Server will also never throw an exception if something is wrong in the doc comment or meta data for a param which is defined inside the comment and also within the statement.

In short, the doc comments will only provide data for the return of the function getMetadata() and nothing else.

Scope names cannot be overwritten

In ACF you can overwrite scope names as follows (this will only work inside UDF's):

function test(string url){
    writeDump(arguments.url);// outputs the string passed in Railo Server and ACF
    writeDump(url);// in ACF outputs the string passed, in Railo Server the url scope
}

test("http://getRailo.org");
url="http://getRailo.org"; // same as variables.url="http://getRailo.org"; in Railo Server and ACF

qry=querynew('url');
queryAddrow...
querySetCell...
<cfloop query="qry">
   <cfset _url=qry.url> <!--- in Railo Server and ACF qry.url is invoked  ---> 
   <cfset _url=url> <!--- in ACF qry.url is invoked in Railo Server the url scope ---> 
...

In Railo Server scope names are always invoked first. This means they are basically reserved words. Railo Server intentionally does not follow ACF here because the ACF behaviour is inconsistent and makes it impossible to access the underlying scopes in the function example above.

Passing array arguments to UDF's "by value"

In ACF arrays are duplicated before they are passed to a UDF, this is referred to as "pass by value". This is the only complex datatype that is passed by value instead of by reference. This is inconsistent as to built-in-function's ACF always passes the arguments by reference, otherwise functions like arrayAppend() would not work, so why not follow the same rule with UDF’s as well?

Passing by value is not only inconsistent, it is also slower, so Railo Server does not follow ACF here on purpose.

Example:

function test(arr){
   arr[1]="Two";
}
arr=["One"];
test(arr); // in ACF the passed array is not touched and still contains the value "One" at position 1.

If you need Railo to behave like ACF, you can use the cfargument attribute "passby" in order to pass a copy of the array to the function.

Example:

<cffunction name="test">
<cfargument name="x" type="array" passby="value">
...

Query of Query (QoQ)

There are several differences in using QoQ due to the underlying SQL engine used in the different CFML engines. These differences occur more often in complex SQL statements, for example when using grouping functions, etc. A small rewrite of the SQL code used should fix any issues you find.

Indifference between the dot and bracket notation

ACF makes a difference when it comes to accessing variables either through bracket or dot notation. In order to make this difference between ACF and Railo Server a little clearer, have a look at this example:

function test(argNotPassed){
    var x=arguments['argNotPassed']; // assigns null to x in Railo Server and ACF
    var x=arguments.argNotPassed; // assigns null to x in Railo Server and throws an exception in ACF
}
test();

From our perspective it makes absolutely no sense to handle dot and bracket notations in a different way. Therefore this is a deliberate incompatibility between ACF and Railo Server

Simple type literals are not stored as strings internally

A literal is a final value which does not change at runtime or is not a variable. So literals can be:

b=true;
n=1234.5678;

ACF internally stores these two literals as strings, Railo Server stores them as a Boolean and as a double. Railo Server tries to store variables always in the format the user has defined them in the code, for the following reasons:

Logic
The user expects it to be stored in this format in most cases
Performance
The chances are high that the same value type is used for mathematical or Boolean operations later. If converted to a string, it needs to be converted back to the appropriate type at runtime as necessary which has a negative effect on performance.
Example:
max=1000000;
for(1=0;i<max;i++); // ACF makes 1000000 string to number conversions in this case, Railo Server not a single one.

It is much faster to convert a variable from a Boolean/double into a string than the other direction.

Format
If you convert these values into something else where the format is important, you get the wrong result, for example:
serializeJSON(123); // outputs "123" in ACF, and not 123 like in Railo Server.
⚠️ **GitHub.com Fallback** ⚠️