Use a CompletableFuture instead of blocking the JVM thread.
This commit is contained in:
parent
75cfd8dadd
commit
eb46230403
|
@ -60,15 +60,31 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_fetch(
|
||||||
request.body(body)
|
request.body(body)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// `JNIEnv` cannot be sent between threads safely
|
||||||
|
let jvm = env.get_java_vm().unwrap();
|
||||||
|
|
||||||
|
// create CompletableFuture
|
||||||
|
let _future = env.new_object("java/util/concurrent/CompletableFuture", "()V", &[]).unwrap();
|
||||||
|
let future = env.new_global_ref(&_future).unwrap();
|
||||||
|
|
||||||
|
RUNTIME.spawn_blocking(move || {
|
||||||
// send request
|
// send request
|
||||||
let response = RUNTIME.block_on(async {
|
let response = RUNTIME.block_on(async {
|
||||||
request.send().await
|
request.send().await
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut env = jvm.attach_current_thread().unwrap();
|
||||||
|
|
||||||
if let Err(error) = response {
|
if let Err(error) = response {
|
||||||
let error = error.to_string();
|
let error = error.to_string();
|
||||||
env.throw_new("java/lang/RuntimeException", error).unwrap();
|
let error = env.new_string(error).unwrap();
|
||||||
return JObject::null().into_raw();
|
// create Exception
|
||||||
|
let exception = env.new_object("java/lang/Exception", "(Ljava/lang/String;)V", &[
|
||||||
|
(&error).into(),
|
||||||
|
]).unwrap();
|
||||||
|
// pass error to CompletableFuture
|
||||||
|
env.call_method(future, "completeExceptionally", "(Ljava/lang/Throwable;)Z", &[(&exception).into()]).unwrap();
|
||||||
|
return ();
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = response.unwrap();
|
let response = response.unwrap();
|
||||||
|
@ -92,10 +108,9 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_fetch(
|
||||||
response.bytes().await.unwrap_or_default().to_vec()
|
response.bytes().await.unwrap_or_default().to_vec()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let body = env.byte_array_from_slice(&body).unwrap();
|
let body = env.byte_array_from_slice(&body).unwrap();
|
||||||
|
|
||||||
// return response
|
// return response to CompletableFuture
|
||||||
let response = env.new_object("rocks/kavin/reqwest4j/Response", "(ILjava/util/Map;[BLjava/lang/String;)V", &[
|
let response = env.new_object("rocks/kavin/reqwest4j/Response", "(ILjava/util/Map;[BLjava/lang/String;)V", &[
|
||||||
status.into(),
|
status.into(),
|
||||||
(&headers).into(),
|
(&headers).into(),
|
||||||
|
@ -103,5 +118,9 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_fetch(
|
||||||
(&final_url).into(),
|
(&final_url).into(),
|
||||||
]).unwrap();
|
]).unwrap();
|
||||||
|
|
||||||
response.into_raw()
|
let future = future.as_obj();
|
||||||
|
env.call_method(future, "complete", "(Ljava/lang/Object;)Z", &[(&response).into()]).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
return _future.into_raw();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class ReqwestUtils {
|
public class ReqwestUtils {
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ public class ReqwestUtils {
|
||||||
System.load(nativeFile.getAbsolutePath());
|
System.load(nativeFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native Response fetch(String url, String method, byte[] body,
|
public static native CompletableFuture<Response> fetch(String url, String method, byte[] body,
|
||||||
Map<String, String> headers);
|
Map<String, String> headers);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue