I'm trying to create an instance of Java 11's Http...
# lucee
d
I'm trying to create an instance of Java 11's HttpClient. When I execute the following code:
Copy code
httpClient = createObject("java", "java.net.http.HttpClient").newBuilder()
	.build()
;
I get the following exception:
Copy code
Unable to make public java.net.http.HttpClient jdk.internal.net.http.HttpClientBuilderImpl.build() accessible: module java.net.http does not "exports jdk.internal.net.http" to unnamed module @12212325
What I notice is when I dump out
createObject("java", "<http://java.net|java.net>.http.HttpClient")
, it's showing that almost all the methods have duplicate method signatures, but with different return types. Is this just a bug in Lucee or is there something I'm missing?
I will add that the class instance returned by
newBuilder()
is
<http://jdk.internal.net|jdk.internal.net>.http.HttpClientBuilderImpl
and I think that relates to the issue, because the object returned is from the internals.
👀 1
So it seems if I update Tomcat so that it adds the
--add-opens=<http://java.net|java.net>.http/jdk.internal.net.http=ALL-UNNAMED
argument to my
CATALINA_OPTS
arguments, this resolves the issue. However, should this be necessary?
a
That's pretty much how modularization of the JDK/JVM works these days. Generally it's advised to not use stuff from
jdk.internals
directly, but I can't really speak about the specifics of the Java HttpClient and why the builder is returning what it's returning though. I've had plenty of similar issues around having to open up modules on the JVM level when doing Android as well as in the Java/CFML world directly.
d
@agentk That's the odd part, I'm not using the internals directly, it's just wants being returned from the builder objects. For as much documentation I'm finding on the the HttpClient (which was introduced in Java 9), I was not finding anything about the issue I was having, which made me wonder if maybe it's a classing loading issue within Lucee, because I just am not seeing people saying they have to ad the
--add-opens=<http://java.net|java.net>.http/jdk.internal.net.http=ALL-UNNAMED
JVM arguments in order to use the HttpClient JDK. You don't need it to just use HttpClient in native Java.
a
Would you have a sample ready-to-run file with your setup to play with?
d
I can create one!
On my agenda today is to just create a Java wrapper for the builder calls. I'm curious if it will work correctly if I create the instances from Java. I never got around to trying that, because I was trying to get all the functionality working first and figure out exactly all the build APIs I was going to need to call.
Ok, so interesting results. If I create a Java class to act as a proxy to the Java methods I'm using, everything works. However, if I try to use any methods of the objects called directly from my CFML, it will throw the
opens jdk.internal.net.http
. So if I would move all my logic into a Java class helper, it appears to work fine. This would lead me to believe that there's a problem with the way that Lucee's classloaders are working. @zackster Do you have any ideas?
@agentk, So if you try the following CFML in Lucee 5.3, it will error:
Copy code
var httpClient = createObject("java", "java.net.http.HttpClient").newBuilder()
	.followRedirects(createObject("java", "java.net.http.HttpClient$Redirect")[arguments.followRedirects ? "NORMAL" : "NEVER"])
	.connectTimeout(Duration.ofMillis(this.getConnectTimeout()))
	.build()
;
However. if I create a simple Java class and then create an instance of it from createObject(), I can create an instance of the builder object:
Copy code
package HttpClient;

import java.net.http.HttpClient;
import java.time.Duration;

public final class HttpClientProxy {

	public static final HttpClient createHttpClient(boolean followRedirects, long connectTimeout){
		return HttpClient.newBuilder()
			.followRedirects(followRedirects ? HttpClient.Redirect.NORMAL : HttpClient.Redirect.NEVER) 
			.connectTimeout(Duration.ofMillis(connectTimeout))
			.build()
		;
	}
}
In doing some more reading, I think this may have to do with the version of Felix being used by Lucee.
a
Oh man, this is so interesting and weird at the same time 🤣