More native way to use Java

The topic “rename JavaNew” raised some more general questions about how we could use Java in Lucee.
Why not support the same syntax for invoking Java classes as we use for components?

Str=new java.lang.String();
String::valueOf(123);

Lucee would simple check first for components and then for classes

1 Like

Good idea.

What are the edge cases here though that could create awkward behaviour?

Thinking of questions like:

  • Is there a way to import a package/class so that I don’t have to do “new java.lang.String()”
  • Can the default search hierarchy always be overwritten by explicitly referring to a class with the full package path?
1 Like

we already have a similar behaviour for dialects.
Let’s say you do:

new Test();

inside a CFML file, then Lucee first check for a Test.cfc following all the rules apply, if not found it looks for a Test.lucee following the same search rules.
So java could be the 3th in line, but of course this means that it take longer to load because it first is wasting time on components. the other problem it is not clear to someone readying the code that this is laoding Java.
An other solution could be to use a new operator for this something like:

java:new java.lang.String();

and for static method calls we could do

java:java.lang.String.valueOf(123);

for import

java:import java.lang.String;

Please at least make sure that any native Java calls still adhere to the sandbox settings, as this has also been a major security issue with CF, as soon as you drop into Java you can simply bypass all sandbox rules and do whatever you like on the server.

I like the first suggestion with class lookup for it’s agnostic approach. It fits with the potential future use case of being able to “extend” java classes with Lucee classes. However, it is additional processing, and I’m not sure how you’d get it to work with the OSGi stuff.

If you did tagging, I would think it would be better to keep the tag with the class name:

new java:java.lang.String();
import java:java.lang.String();

Just some brainstorming, you could possibly both and extend it beyond java…

s = new java.lang.String() // look for cfc, then lucee, then java
s = new java:java.lang.String() // skip straight to java
s = java:java.lang.String::valueOf(123); // I don't know, but this seems like it might be difficult to work into the compiler

// very much an edge case, but lets say both my/Object.cfc and my/Object.lucee 
// exist in the same folder. you could use tagging to pick specifically which one
// you want to use?
c = new cfc:my.Object()
c = new lucee:my.Object()

I don’t have anything to add except:

I think it’d be OK if this syntax didn’t support the OSGi variations, and just uses the “default” (whatever dictates the default) class. Or second the job of identifying which implementation of the given class to an import statement earlier in the file?

Not all syntax has to support all options. Especially if that would make something short and sweet be less short. Or less sweet.

I like the general idea though.


Adam

agreed

If you need a specific version you can still do JavaNew (or whatever we will call it)

Personally I don’t favor this approach. I always like to have only one way to do things. It feels more solid and less confusing.

So my suggestion would be to only have the following syntax:

s = new java:java.lang.String();

This way you always know by the first look that you initialize a native java object. After all, you don’t initialize native java objects all the time in lucee, so the extra “java:” won’t be that bad regarding the extra typing.

2 Likes