mirror of
https://github.com/TeamPiped/reqwest4j.git
synced 2024-08-14 23:54:39 +00:00
Use a CompletableFuture instead of blocking the JVM thread.
This commit is contained in:
parent
75cfd8dadd
commit
eb46230403
2 changed files with 64 additions and 44 deletions
|
@ -60,48 +60,67 @@ pub extern "system" fn Java_rocks_kavin_reqwest4j_ReqwestUtils_fetch(
|
||||||
request.body(body)
|
request.body(body)
|
||||||
};
|
};
|
||||||
|
|
||||||
// send request
|
// `JNIEnv` cannot be sent between threads safely
|
||||||
let response = RUNTIME.block_on(async {
|
let jvm = env.get_java_vm().unwrap();
|
||||||
request.send().await
|
|
||||||
|
// 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
|
||||||
|
let response = RUNTIME.block_on(async {
|
||||||
|
request.send().await
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut env = jvm.attach_current_thread().unwrap();
|
||||||
|
|
||||||
|
if let Err(error) = response {
|
||||||
|
let error = error.to_string();
|
||||||
|
let error = env.new_string(error).unwrap();
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// get response
|
||||||
|
let status = response.status().as_u16() as i32;
|
||||||
|
|
||||||
|
let headers = env.new_object("java/util/HashMap", "()V", &[]).unwrap();
|
||||||
|
let headers: JMap = JMap::from_env(&mut env, &headers).unwrap();
|
||||||
|
|
||||||
|
response.headers().iter().for_each(|(key, value)| {
|
||||||
|
let key = env.new_string(key.as_str()).unwrap();
|
||||||
|
let value = env.new_string(value.to_str().unwrap()).unwrap();
|
||||||
|
headers.put(&mut env, &JObject::from(key), &JObject::from(value)).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let final_url = response.url().to_string();
|
||||||
|
let final_url = env.new_string(final_url).unwrap();
|
||||||
|
|
||||||
|
let body = RUNTIME.block_on(async {
|
||||||
|
response.bytes().await.unwrap_or_default().to_vec()
|
||||||
|
});
|
||||||
|
|
||||||
|
let body = env.byte_array_from_slice(&body).unwrap();
|
||||||
|
|
||||||
|
// return response to CompletableFuture
|
||||||
|
let response = env.new_object("rocks/kavin/reqwest4j/Response", "(ILjava/util/Map;[BLjava/lang/String;)V", &[
|
||||||
|
status.into(),
|
||||||
|
(&headers).into(),
|
||||||
|
(&body).into(),
|
||||||
|
(&final_url).into(),
|
||||||
|
]).unwrap();
|
||||||
|
|
||||||
|
let future = future.as_obj();
|
||||||
|
env.call_method(future, "complete", "(Ljava/lang/Object;)Z", &[(&response).into()]).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(error) = response {
|
return _future.into_raw();
|
||||||
let error = error.to_string();
|
|
||||||
env.throw_new("java/lang/RuntimeException", error).unwrap();
|
|
||||||
return JObject::null().into_raw();
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = response.unwrap();
|
|
||||||
|
|
||||||
// get response
|
|
||||||
let status = response.status().as_u16() as i32;
|
|
||||||
|
|
||||||
let headers = env.new_object("java/util/HashMap", "()V", &[]).unwrap();
|
|
||||||
let headers: JMap = JMap::from_env(&mut env, &headers).unwrap();
|
|
||||||
|
|
||||||
response.headers().iter().for_each(|(key, value)| {
|
|
||||||
let key = env.new_string(key.as_str()).unwrap();
|
|
||||||
let value = env.new_string(value.to_str().unwrap()).unwrap();
|
|
||||||
headers.put(&mut env, &JObject::from(key), &JObject::from(value)).unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
let final_url = response.url().to_string();
|
|
||||||
let final_url = env.new_string(final_url).unwrap();
|
|
||||||
|
|
||||||
let body = RUNTIME.block_on(async {
|
|
||||||
response.bytes().await.unwrap_or_default().to_vec()
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
let body = env.byte_array_from_slice(&body).unwrap();
|
|
||||||
|
|
||||||
// return response
|
|
||||||
let response = env.new_object("rocks/kavin/reqwest4j/Response", "(ILjava/util/Map;[BLjava/lang/String;)V", &[
|
|
||||||
status.into(),
|
|
||||||
(&headers).into(),
|
|
||||||
(&body).into(),
|
|
||||||
(&final_url).into(),
|
|
||||||
]).unwrap();
|
|
||||||
|
|
||||||
response.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 a new issue