java 11

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

java 11

daniel szmulewicz
Hi,

I wrote my first Kawa script, yay!
I wanted to explore Java interop, so the following script does a http
request with the new HttpClient that ships in Java 11. However, as you can
see, some methods needed to be fully qualified in order to make it work. Is
this a case of reflection not working with the new Java modules? Am I
missing something? Thank you!

-- Code below this line
(import (class java.net URI))
(import (class java.net.http HttpClient HttpRequest HttpResponse))

(define uri (URI:create "
http://cr.openjdk.java.net/~chegar/httpclient/02/javadoc/api/java.net.http/java/net/http/HttpClient.html
"))
(define body-handler (HttpResponse:BodyHandlers:ofString))
(define client (*:build (HttpClient:newBuilder)))
(define request (*:build (*:uri (HttpRequest:newBuilder) uri)))
(define response (java.net.http.HttpClient:send client request
body-handler))
(display (java.net.http.HttpResponse:body response))
Reply | Threaded
Open this post in threaded view
|

Re: java 11

Per Bothner
On 12/2/18 3:00 PM, daniel szmulewicz wrote:
> Hi,
>
> I wrote my first Kawa script, yay!
> I wanted to explore Java interop, so the following script does a http
> request with the new HttpClient that ships in Java 11. However, as you can
> see, some methods needed to be fully qualified in order to make it work. Is
> this a case of reflection not working with the new Java modules? Am I
> missing something? Thank you!

Works for me (using openjdk 11.0.1).

Your problem may be that you're running the script using load,
or using the -f command-line flag.  That reads, compiles, and evaluates
each line one-by-one which is undesirable for a number of reasons.
For one it hurts various optimizations and requires more reflection.

Instead run the script directly from the command line:

     $ kawa my-script.scm

(without using the -f option).

If using the REPL, you can use require instead of load:

     $ kawa
     #|kawa:3|# (require  "my-script.scm")

Note that "load" is a procedure that reads the file line-by-line,
while "require" is syntax (a macro) that reads the file at "compile-time".
     
It will also work better (no warnings) if you stick to using
the CLASS_NAME:METHOD_NAME syntax for static methods.  For instance methods
we prefer INSTANCE:METHOD_NAME.

Specifically, replace the last two lines by:

     (define response (client:send request body-handler))
     (display (response:body))
--
        --Per Bothner
[hidden email]   http://per.bothner.com/
Reply | Threaded
Open this post in threaded view
|

Re: java 11

Per Bothner
On 12/2/18 5:49 PM, Per Bothner wrote:
> On 12/2/18 3:00 PM, daniel szmulewicz wrote:
> Your problem may be that you're running the script using load,
> or using the -f command-line flag.  That reads, compiles, and evaluates
> each line one-by-one which is undesirable for a number of reasons.
> For one it hurts various optimizations and requires more reflection.

It is possible to get the script running using load or the -f flag,
however, run-time method lookup and selection do not work as well as
doing it at compile-time, so you want to help the type-inference.

The trick is to replace 'define' by 'define-constant' or the '!' short-hand syntax:

     (define-constant client (*:build (HttpClient:newBuilder)))
or:
     (! client (*:build (HttpClient:newBuilder)))
or use an explicit type specifier:
     (define client ::HttpClient (*:build (HttpClient:newBuilder)))

The reason plain define (without a type-specifier) doesn't work
is because the Kawa type inference engine can't know if client
is *always* an HttpClient - a later set! might change its value.
When working file-at-a-time (rather than line-at-a-time) Kawa
knows there is no later set!.
--
        --Per Bothner
[hidden email]   http://per.bothner.com/