Are there any CF-->Java gurus here? I have what "s...
# cfml-general
s
Are there any CF-->Java gurus here? I have what "seems" like a simple project, take the java example here (the simplest demo function), and port it to CF: https://github.com/nayuki/QR-Code-generator/blob/master/java/QrCodeGeneratorDemo.java#L35. I'm looking at the doBasicDemo(). While I do have a use for the QR code generation, I'm more interested on how to have CF speak Java.
s
What specific questions do you have?
What Java interop are you familiar with? Do you know how to create Java objects?
d
Let's start simple:
Copy code
String text = "Hello, world!";          // User-supplied Unicode text
This declares a variable "text" that is of type String. Since CF is a typeless language, the type of the variable does not matter. So that line can be translated to CFML as:
Copy code
var text = "Hello, world!";
Let's take a look at the next line:
Copy code
QrCode.Ecc errCorLvl = QrCode.Ecc.LOW;  // Error correction level
Once again, the type (e.g. QrCode.Ecc) is irrelevant to CFML, so ignore it on our CFML code. The
QrCode
is a reference to the
io.nayuki.qrcodegen.QrCode
class defined in one of the
import
statements. So this line can be translated to something like:
Copy code
# this emulates the "import" line
var QrCode = createObject("java", "io.nayuki.qrcodegen.QrCode");
# now we can use our imported class
var errCorLvl = QrCode.Ecc.LOW;
Now, let's move to a line with a constructor:
Copy code
File svgFile = new File("hello-world-QR.svg");
Once again, we can ignore the type declaration. So now do we emulate the constructor? CFML uses the same pattern as components to pass in the constructor arguments, so that line can be translated to:
Copy code
var svgFile = createObject("java", "java.io.File").init("hello-world-QR.png");
That should be enough to get you started...
šŸ‘ 1
s
QrCode.Ecc
is a nested class so I don't think your
errCorLvl
assignment will work... I can't remember how CFML handles nested classes but it need:
Copy code
var QrCodeEcc = createObject("java", "io.nayuki.qrcodegen.QrCode$Ecc");
var errCorLvl = QrCodeEcc.LOW;
(different languages handle interop with nested classes differently but most use
Outer$Inner
as the reference)
šŸ‘ 1
s
That is the nitty-gritty details I was looking for. I've had spotty results in the past converting a chunk of java code like this. I'll give it a try...
@seancorfield, your version worked. I start getting lost with how you came up with QrCode$Ecc. Next, the sample java code simply starts using
QrCode qr = QrCode.encodeText(text, errCorLvl);
and I don't see a constructor. Yet the javadoc shows a constructor of
*QrCode*(int ver, *QrCode.Ecc* ecl, byte[] dataCodewords, int msk)
Refs: • https://github.com/nayuki/QR-Code-generator/blob/master/java/QrCodeGeneratorDemo.java?ts=4 • https://www.nayuki.io/res/qr-code-generator-library/javadoc/io/nayuki/qrcodegen/QrCode.html BTW, I started this path because the latest Java broke the google QR generation library which had CF examples. (Unable to make public final java.nio.file.Path sun.nio.fs.UnixFileSystem.getPath(java.lang.String,java.lang.String[]) accessible: module java.base does not opens sun.nio.fs to unnamed module...) I should suggest a class on this at the CF summit. @Mark Takata (Adobe) ^^
s
It's a static method -- off the class -- so no constructor is needed.
And
QrCode.Ecc.LOW
told me it was the
LOW
static field of the class
Ecc
nested inside the class
QrCode
and Java encodes nested classes in bytecode as top-level classes but with the name
Outer$Inner
.
For static methods and fields, you just need
createObject("java", "the.package.for.TheClass")
without calling
.init()
to run a constructor.
f
FYI there is a guide on cfdocs https://cfdocs.org/java which covers some of the common conversion scenarios
ā¤ļø 1
šŸ‘ 1
s
Thank you. Proceeding forward...
I somehow got it working with this dialog as my primer. I did come across an instance where there was a similar QrCode.Ecc.LOW usage, this time BufferedImage.TYPE_INT_RGB
var TYPE_INT_RGB = createObject("java", "java.awt.image.BufferedImage$TYPE_INT_RGB");
did not work, instead I used
var TYPE_INT_RGB = createObject("java", "java.awt.image.BufferedImage").TYPE_INT_RGB;
I know there is probably a valid reason for the discrepancy, but this is where I struggle with Java-->CF conversion.
Here is the meat of my first iteration of working code. The toImage() function is coded this way just to be somewhat inline with the original java code I was porting. The width, height, margin parameters of createQRCode_QRCodeGen() are not yet functional, but they will eventually. I have 3 other createQRCode_xxx function using various services and libraries.
s
BufferedImage.TYPE_INT_RGB
indicates a static field in a class, not a nested class. you can tell from the context of the Java code (or the docs)
Glad you got it all working!