I am still spinning up on the Azure Storage Java SDK 10 and its use of reactive programming the paradigm. I wrote the following method to asynchronously download a blob to a byte stream as fast as possible. When I use the synchronous version (below), it works properly. When I comment out the blockingAwait() and uncomment the subscribe, the write and the doOnComplete never are executed... Basically, the run just falls out of the bottom of the method back to the caller. I am sure that I have made an asynchronous processing mistake, and hope that someone can steer me in the correct direction. By the way, I was surprised to find that there are very few samples of downloading to a stream rather than to a file... Hopefully, this posting will help others.
Thank you for your time and interest in my problem...
override fun downloadBlob(url: String, downloadStream: OutputStream) {
BlockBlobURL(URL(url), pipeline)
.download(null, null, false, null)
.flatMapCompletable { response ->
FlowableUtil.collectBytesInBuffer(response.body(null))
.map {
Channels.newChannel(downloadStream).write(it)
}.toCompletable()
}.doOnComplete {
println("The blob was downloaded...")
}.blockingAwait()
//.subscribe()
}
Here is the code that is calling the above method:
fun getAerialImageBlobStream(aerialImageUrl: String): MapOutputStream {
val aerialImageStream = MapOutputStream()
blobStorage.downloadBlob(aerialImageUrl, aerialImageStream)
return aerialImageStream
}
Related
Apologies if what I am asking has been asked before, however despite much searching I have not been able to find any possible explanation to the issue I am experiencing.
I am developing an Android application, which communicates with a BLE Device (CC2541). I am able to write data from Android to BLE device without issues. However issues start when trying to read data from the BLE device in the Android.
I am using Kotlin, and I am trying to "enable" notifications for the particular GATT Characteristic which I want to read, and I do so by setting the descriptor to the following UUID
00002902-0000-1000-8000-00805f9b34fb
And for doing so I have the following code:
private suspend fun setNotification(
char: BluetoothGattCharacteristic,
descValue: ByteArray,
enable: Boolean
) {
val desc = char.getDescriptor(UUID_CLIENT_CHAR_CONFIG)
?: throw IOException("missing config descriptor on $char")
val key = Pair(char.uuid, desc.uuid)
if (descWriteCont.containsKey(key))
throw IllegalStateException("last not finished yet")
if (!gatt.setCharacteristicNotification(char, enable))
throw IOException("fail to set notification on $char")
return suspendCoroutine { cont ->
descWriteCont[key] = cont
desc.value = descValue
if (!gatt.writeDescriptor(desc))
cont.resumeWithException(IOException("fail to config descriptor $this"))
}
}
However it just so happens that the following method returns false all the time:
gatt.writeDescriptor(desc)
Does anyone have any idea what could be causing this issue? Apologies in advance if it's a silly question whose answer I have overlooked. I am new to Kotlin and coroutines, and in fact I suspect this issue has to do with how I am using suspend functions.
I have fixed the issue.
Upon much debugging, I discovered that for some estrange reason (I'm not very experience with Kotlin or Android, so I don't know this reason), the method gatt.writeDescriptor() returns 3 times, (in my case, at least). And only the last time does it return true and the descriptor actually gets written.
So because my code only checked whether it returned true or false the first time, it was obviously failing.
I have now modified my code, to make it wait until it returns true which happens always on the third time it returns.
private suspend fun setNotification(
char: BluetoothGattCharacteristic,
descValue: ByteArray,
enable: Boolean
) {
val desc = char.getDescriptor(UUID_CLIENT_CHAR_CONFIG)
?: throw IOException("missing config descriptor on $char")
val key = Pair(char.uuid, desc.uuid)
if (descWriteCont.containsKey(key))
throw IllegalStateException("last setNotification() not finish")
if (!gatt.setCharacteristicNotification(char, enable))
throw IOException("fail to set notification on $char")
return suspendCoroutine { cont ->
descWriteCont[key] = cont
desc.value = descValue
while (!gatt.writeDescriptor(desc)) {
}
}
}
Now I have successfully subscribed for notifications, and can read data from the BLE Device without much issues.
Thanks to all who helped by offering some input, and I hope this will hopefully help someone in the future facing the same situation.
I have never used a RESTful API. I want to use this API to get historical weather data, but I can't find a simple tutorial taking me from end to end making an app that uses a RESTful API in Java. I'm not sure what steps I should take to get the data.
The steps listed on the getting started page are not Java specific, so I'm not sure how to use that info. I have requested a token and got it, so I'm good on that front.
What I need help with is getting a minimal example showing how, with just a token and formatted URL, you can get JSON data from the API.
Some things I've looked into are javax.ws.rs and jersey client, but I'm not sure how to use those either.
Thanks in advance :)
Using Fetch you can do:
fetch(url, {options})
.then(data => {
// Do some stuff here
})
.catch(err => {
// Catch and display errors
})
Where the url is the one from the getting started page.
And you can get whatever data you need from data.
Say you need to save just the name in a local var, then you do:
.then(data => {
name = data.name
})
In vertx guides, the sequential composition for chaining async calls is shown below:
FileSystem fs = vertx.fileSystem();
Future<Void> startFuture = Future.future();
Future<Void> fut1 = Future.future();
fs.createFile("/foo", fut1.completer());
fut1.compose(v -> {
// When the file is created (fut1), execute this:
Future<Void> fut2 = Future.future();
fs.writeFile("/foo", Buffer.buffer(), fut2.completer());
return fut2;
}).compose(v -> {
// When the file is written (fut2), execute this:
fs.move("/foo", "/bar", startFuture.completer());
},
// mark startFuture it as failed if any step fails.
startFuture);
Is it just me or is this code really cumbersome and hard to read?
There should be another way without falling into the callback hell.
It's a pity there are so few blog posts on vertx, any ideas are much appreciated.
these days the de facto library for writing asynchronous, non-blocking code on the JVM is RxJava. if you're not familiar i'd say it's highly worth your while to take a look as one of the many benefits is the ability to write "flows" as compositional streams that aren't quite as callback hell-y as the JDK's Futures were.
luckily, Vert.x is integrated with RxJava. as an example, here is your snippet rewritten using RxJava artifacts:
#Override
public void start(Future<Void> startFuture) throws Exception {
final FileSystem fs = vertx.fileSystem();
fs.rxCreateFile("/foo")
.andThen(fs.rxWriteFile("/foo", Buffer.buffer()))
.andThen(fs.rxMove("/foo", "/bar"))
.subscribe(
() -> {
startFuture.complete();
},
error -> {
startFuture.fail(error);
}
);
}
much more concise and readable.
note:
use RxJava 2 as it has superceded RxJava 1
...both versions, however, are supported in Vert.x, with their respective artifacts living in separate namespaces:
io.vertx.rxjava for version RxJava 1 artifacts
io.vertx.reactivex for version RxJava 2 artifacts
hope that helps!
Disclaimer: I work on a non-traditional project, so don't be shocked if some assumptions seem absurd.
Context
I wish to create a stream reader for integers, strings, and the other common types in Scala, but to start with I focus only on integers. Also note that I'm not interesting in handling exception at the moment -- I'll deal with them in due time and this will be reflected in the API and in the meantime I can make the huge assumption that failures won't occur..
The API should be relatively simple, but due to the nature of the project I'm working on, I can't rely on some feature of Scala and the API needs to look something like this (slightly simplified for the purpose of this question):
object FileInputStream {
def open(filename: String): FileInputStream =
new FileInputStream(
try {
// Check whether the stream can be opened or not
val out = new java.io.FileReader(filename)
out.close()
Some[String](filename)
} catch {
case _: Throwable => None[String]
}
)
}
case class FileInputStream(var filename: Option[String]) {
def close: Boolean = {
filename = None[String]
true // This implementation never fails
}
def isOpen: Boolean = filename.isDefined
def readInt: Int = nativeReadInt
private def nativeReadInt: Int = {
??? // TODO
}
}
object StdIn {
def readInt: Int = nativeReadInt
private def nativeReadInt: Int = {
??? // TODO
}
}
Please also note that I cannot rely on additional fields in this class, with the exception of Int variables. This (probably) implies that the stream has to be opened and closed for every operations. Hence, it goes without saying that the implementation will not be efficient, but this is not an issue.
The Question
My goal is to implement the two nativeReadInt methods such that the input stream gets consumed by only one integer if one is available straight away. However, if the input doesn't start (w.r.t. the last read operation) with an integer then nothing should be read and a fixed value can be returned, say -1.
I've explored several high level Java and Scala standard APIs, but none seemed to offer a way to re-open a stream to a given position trivially. My hope is to avoid implementing low level parsing based solely on java.io.InputStream and its read() and skip(n) methods.
Additionally, to let the user read from the standard input stream, I need to avoid using scala.io.StdIn.readInt() method because it reads "an entire line of the default input", therefore trashing some potential data.
Are you aware of a Java or Scala API that could do the trick here?
Thank you
I'm successfully using Play 1.2.4 to serve large binary file downloads to users using the renderBinary() method.
I'd like to have a hint of when the user actually completes the download. Generally speaking, I know this is somewhat possible as I've done it before. In an old version of my website, I wrote a simple servlet that served up binary file downloads. Once that servlet finished writing out the contents of the file, a notification was sent. Certainly not perfect, but useful nonetheless. In my testing, it did provide an indication of how long the user took to download a file.
Reviewing the Play source, I see that the play.mvc.results.RenderBinary class has a handy apply() method that I could use. I wrote my own version of RenderBinary so I could send the notification after the apply() method finished writing out the file contents.
The problem I found is that calls to response.out.write() obviously cache the outgoing bytes (via Netty?), so even though I am writing out several megabytes of data, the calls to play.mvc.Http.Response.out.write() complete in seconds, even though it takes the downloader a couple minutes to download the file.
I don't mind writing custom classes, although I'd prefer to use a stock Play 1.2.4 distribution.
Any ideas on how to get a notification of when the end of a file download is pushed out towards the user's browser?
It seems this may help you, as it tackles a somehow similar problem:
Detect when browser receives file download
I'm not sure you'll eb able to do it via renderBinary nor an #After annotation in the controller. Some browser-side detection of the download and then a notification to the server (pinging the download's end) would work.
There may be an alternative: using WebSockets (streaming the file via the socket and then having teh client to answer) but it may be overkill for this :)
you can use ArchivedEventStream.
first create a serializable ArcivedEventStream class..
public class Stream<String> extends ArchivedEventStream<String> implements Serializable{
public Stream(int arg0) {
super(arg0);
}
}
then on your controller...
public static void downloadPage(){
Stream<String> userStream = Cache.get(session.getId(),Stream.class);
if( userStream == null){
userStream = new Stream<String>(5);
Cache.add(session.getId(), userStream);
}
render();
}
public static void download(){
await(10000);// to provide some latency. actually no needed
renderBinary(Play.getFile("yourfile!"));
}
public static void isDownloadFinished(){
Stream<String> userStream = Cache.get(session.getId(),Stream.class);
List<IndexedEvent<String>> list = await(userStream.nextEvents(0));
renderJSON(list.get(0).data);
}
#After(only="download")
static void after(){
Stream<String> userStream = Cache.get(session.getId(),Stream.class);
userStream.publish("ok");
}
on your html...
#{extends 'main.html' /}
#{set title:'downloadPage' /}
download
<script>
$(document).ready(function(){
$.ajax('/application/isDownloadFinished',{success:function(data){
if(data){
console.log("downloadFinished");
}
}});
});
</script>
when your download finished, the original page will retrieve the notification.
This code is just a sample. You could read the api of ArchivedEventStream and make your own implementation..