Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe to call underlying java method on String in ColdFusion?

Tags:

coldfusion

Adobe ColdFusion is built on Java. Almost all simple variables in CFML/CFSCRIPT are java.lang.String until the operation needs it to be of a certain type.

I've always want to use startsWith() in String instead of the more bulky CFML variant.

left(str,4) EQ "test"

However, what's the general consensus of using underlying Java method in ColdFusion?

Would this be any safer to javacast() the var first?

javacast("String",x).startsWith("test");

What if the CF engine is not built on top of Java?

Thanks

like image 756
Henry Avatar asked Jan 23 '23 06:01

Henry


2 Answers

Yes, you can do this with Adobe ColdFusion and other CFML engines that are built on Java. It's actually simpler than you thought.

<cfset str = "hello what's up" />
#str.startsWith("hello")# <!--- returns "YES" --->
<cfif str.startsWith("h")>
  This text will be output
</cfif>

#str.startsWith("goodbye")# <!--- returns "NO" --->
<cfif str.startsWith("g")>
  This text will NOT be output
</cfif>

This is possible because CFML strings in ColdFusion are the same as Java strings. You can use any native string method (Java.lang.String) on a CFML string.

If you haven't guessed, this also works with CFML arrays (some kind of list, probably a java.util.Vector) and structs (probably a java.util.Map). Experiment with data types and the cfdump tag, you will find a lot of secrets.

One word of warning, this is not standard CFML, so if your underlying engine changes, including just upgrading to a new version, there are no guarantees that it will still work.

That said, string.startsWith() is native to Java as well as .NET, so this will also work if your CFML engine is BlueDragon.NET. The only CFML engines it will not work on are ColdFusion 5 and previous.

Is it safe to use? I would say yes. As long as CFML engines run on Java or .NET, it's perfectly safe. It's undocumented, but easy to understand, so I would say use it freely.

like image 100
Nathan Strutz Avatar answered Feb 26 '23 02:02

Nathan Strutz


I have found that using built in cf functions in most cases is faster than leveraging their java counterparts, mainly as it costs so much in cf wrapping the java methods.

If you are using .startsWith(), remember it's case sensitive, whereas cf's eq isn't. Same goes for most of the other java String methods - .endsWith(), .contains() etc.

Unless you can bundle large sets of functionality as roll your own java util classes, mixing cf and java calls seems slow. If you are in some java code, and you have a string, and you call its startsWith() method, it just executes. Done. In cf code, you have to javaCast or blindly hope the variable is in the correct data type, which is risky with things like entirely numeric strings, and when you call a .startsWith(), there is a bunch of cf code that runs before it even gets down to the java level, which is where the slowness lives. Eg. Cf's dynamic arguments means that it has to check if there is a method on the supplied object with that many args, and of those data types (or compatible types). There is just a whole bunch of code that unavoidably runs, bridging the two languages.

But don't trust our experiences, benchmark for yourselves. eg.

<cfscript>
var sys = createObject( 'java', 'java.lang.System' );
var timer = sys.nanoTime();
    // run some code here
timer = sys.nanoTime() - timer;
writeDump( var: timer );
</cfscript>

If you are using the Adobe cf engine, watch out of entirely numeric strings, they bounce between java Doubles and Strings, and don't get me started with serializeJSON()...

like image 45
Mike Causer Avatar answered Feb 26 '23 03:02

Mike Causer