Copy link to clipboard
Copied
Here's another issue I'm running into with our new CF2021 instance. This function worked fine with CF2016 using Java 11
public date function convertEpochToODBCDate( required numeric ts ){
var objTZ = createObject( "java", "java.util.TimeZone" );
var objDF = createObject( "java", "java.text.SimpleDateFormat" );
var objDate = createObject( "java", "java.util.Date" );
var dte = objDate.init( JavaCast("long",arguments.ts) * 1000 );
var tz = objTZ.getTimeZone( JavaCast("string", 'UTC') );
var outputFormat = objDF.init( javaCast( "string", "yyyy-MM-dd HH:mm:ss" ) );
outputFormat.setTimeZone(tz);
return CreateODBCDateTime( outputFormat.format(dte.getTime()) );
}
Here's the stack trace:
Detail | Either there are no methods with the specified method name and argument types or the init method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 2 methods that match the provided arguments. If this is a Java object and you verified that the method exists, use the javacast function to reduce ambiguity. |
Message | The init method was not found. |
MethodName | init |
StackTrace | coldfusion.runtime.java.MethodSelectionException: The init method was not found. at coldfusion.runtime.java.ObjectHandler.findConstructorUsingCFMLRules(ObjectHandler.java:496) at coldfusion.runtime.java.JavaProxy.CreateObject(JavaProxy.java:222) at coldfusion.runtime.java.JavaProxy.invoke(JavaProxy.java:89) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:4254) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:4217) |
1 Correct answer
Yet another solution:
public date function convertEpochToODBCDate( required numeric ts ){
...
// Use BigDecimal to prevent ColdFusion from automatically
// converting 1646874000000 to 1.646874E+012
var numberAsLong=createobject("java","java.math.BigDecimal").init(arguments.ts*1000).longValue();
var dte = objDate.init( numberAsLong );
...
}
Copy link to clipboard
Copied
And it's specifically failing on
objDate.init( JavaCast("long",arguments.ts) * 1000 );
Copy link to clipboard
Copied
I can't explain why CF2016 and CF2021 would behave differently if both are using Java 11, but my guess would be that by multiplying the casted long value by 1000, it's probably getting converted back to a CF integer, and when that's passed in the constructor call, there are no methods that accept an integer. Multiply by 1000 before JavaCast-ing, see if that works.
var dte = objDate.init( JavaCast("long",arguments.ts * 1000));
Copy link to clipboard
Copied
It's a good thought @TheRealMC - however the error is indicating that the Java Date class does not have an init() method, not that the value is incorrect. With that said, I did what you suggested and got the same error - The init method was not found.
Copy link to clipboard
Copied
That's weird, I just tried this and the function returned the date correctly:
<cfscript>
public date function convertEpochToODBCDate( required numeric ts ){
var objTZ = createObject( "java", "java.util.TimeZone" );
var objDF = createObject( "java", "java.text.SimpleDateFormat" );
var objDate = createObject( "java", "java.util.Date" );
var dte = objDate.init( JavaCast("long",arguments.ts * 1000) );
var tz = objTZ.getTimeZone( JavaCast("string", 'UTC') );
var outputFormat = objDF.init( javaCast( "string", "yyyy-MM-dd HH:mm:ss" ) );
outputFormat.setTimeZone(tz);
return CreateODBCDateTime( outputFormat.format(dte.getTime()) );
}
test = convertEpochToODBCDate(1646874000);
writeDump(test);
</cfscript>
I believe the error message is a little misleading. In addition to getting thrown when a method doesn't exist, I think this exception also gets thrown when the method name does exist but the correctly typed parameter(s) have not been passed.
Copy link to clipboard
Copied
@TheRealMC - I'm currently on patch #3 - 2021.0.03.329779 and Java 11.0.2 - which version did you tested the code?
Copy link to clipboard
Copied
@--jojo--, I tested with 2021.0.03.329779 and Java 11.0.12.
Copy link to clipboard
Copied
And it's specifically failing on
objDate.init( JavaCast("long",arguments.ts) * 1000 );
By --jojo--
I think that ColdFusion is justified in throwing an error on that line. According to the API for java.util.Date, the constructor's argument should be of type long.
Whereas, there is no guarantee that JavaCast("long",arguments.ts) * 1000 is of long type. To make sure it is, you could correct the code to:
public date function convertEpochToODBCDate( required numeric ts ){
var dateAsNumber=arguments.ts*1000;
...
var dte = objDate.init( JavaCast("long",dateAsNumber) );
...
}
Copy link to clipboard
Copied
TLDR: Always explicitely case the entire value.
I recently tweeted about this... casting to a specific data type and then performing any math will cause that variable to lose the explicit type. I've found that IncrementValue() will retain INT type, but only increment a value by 1 and return an INT (identified in the docs), but haven't found any other way to retain value other than consistently and explicitly re-casting after performing math.
By comparison during cross-compatible CFML research, I've noticed that any numeric value in Lucee becomes a DOUBLE if you add 1 to it. When using IncrementValue, Lucee can properly increment a decimal (DOUBLE) value and correctly increments by 1.
Copy link to clipboard
Copied
Please output and tell us the value of your arguments.ts value. The root cause of the error is likely in what's being passed in, rather the init itself. Indeed, you could also try to output or just refer to the JavaCast("long",arguments.ts), alone, to see if THAT is the actual error on that line.
Someone might guess this could have something with the change in how cf 2021 handles date formats with D (vs d), but you don't show doing that in this code. And you're passing in a NUMBER in that ts argument, not a date.
Let us know what you find.
/Charlie (troubleshooter, carehart. org)
Copy link to clipboard
Copied
You can pass any epoch value (e.g. 1646874000) - unfortunately cffidle won't let you instantiate java objects.
Copy link to clipboard
Copied
You can pass any epoch value (e.g. 1646874000) - ...
By --jojo--
But beware. ColdFusion is weakly typed. Under the bonnet, it may make a funky conversion like 1.646874E+012 for 1646874000 * 1000.
Copy link to clipboard
Copied
Yet another solution:
public date function convertEpochToODBCDate( required numeric ts ){
...
// Use BigDecimal to prevent ColdFusion from automatically
// converting 1646874000000 to 1.646874E+012
var numberAsLong=createobject("java","java.math.BigDecimal").init(arguments.ts*1000).longValue();
var dte = objDate.init( numberAsLong );
...
}
Copy link to clipboard
Copied
This solution worked. Thanks @BKBK
Copy link to clipboard
Copied
Also, the actual error on the line is the the "init" method being non-existent or not found.
Copy link to clipboard
Copied
Also, the actual error on the line is the the "init" method being non-existent or not found.
By --jojo--
Here, "init" represents a constructor of java,util.Date.
Suppose, as I had said earlier, that ColdFusion is implicitly converting to Scientific Notation, 1.646874E+012. Then the error message is simply telling you that the Date constructor that can accept 1.646874E+012 as argument does not exist.

