Cancel Google Drive upload possible? - java

I have written an app using the official API to upload to Google drive, this works perfectly. However I can't find anyway to cancel an upload. I'm running it in an ASyncTask, so far I have tried making the drive object, the file path, the token and a few other variables none. I've also tried to invalidate the token however it seems this only removes it from the cache and doesn't actually invalidate it server side. I've called cancel on the ASyncTask however if it is cancelled once the upload has started there seems to be no way to stop it.
My issue is if a user starts uploading a 100mb file there's no way for them to cancel it other then turning their internet connection on and off which isn't practical. This is my upload code:
java.io.File jFile = new java.io.File(path); //Does not get file just info
File body = setBody(jFile, mimeType);
try
{
java.io.File mediaFile = new java.io.File(path);
InputStreamContent mediaContent =
new InputStreamContent(mimeType,
new BufferedInputStream(new FileInputStream(mediaFile)));
mediaContent.setLength(mediaFile.length());
request = drive.files().insert(body, mediaContent);
request.getMediaHttpUploader().setProgressListener(new CustomProgressListener());
File file = request.execute();
Surely there is a way to cancel an upload?

Great question! I filed a feature request for the ability to cancel a media upload request:
https://code.google.com/p/google-api-java-client/issues/detail?id=671
However, this may a difficult feature to implement based on the current design of that library.
Another option to consider is to not use AsyncTask and instead implementing the multi-threading yourself and abort the running Thread. Not pleasant, but may be your only option for doing this now.

In a comment I have said that putting the request in a thread and call interrupt is not working. So I was searching another way of doing it.
I have finally found one, an ugly one: Close the InputStream of the uploaded file!
I initialize with:
mediaContent = new InputStreamContent(NOTE_MIME_TYPE,new BufferedInputStream(new FileInputStream(fileContent)));
mediaContent.setLength(fileContent.length());
And in a stop listener I have :
IOUtils.closeQuietly(mediaContent.getInputStream());
For sure it should be possible to do it in a better way!
Regards

I've been looking for an answer for a long time as well. The following is the best I could come up with.
Store the Future object anywhere you want (use Object or Void):
Future<Object> future;
Call this code (Java 8):
try
{
ExecutorService executor = Executors.newSingleThreadExecutor();
future = (Future<Object>) executor.submit(() ->
{
// start uploading process here
});
future.get(); // run the thread (blocks)
executor.shutdown();
}
catch (CancellationException | ExecutionException | InterruptedException e)
{}
To cancel, call:
future.cancel(true);
This solution hasn't produced any nasty side effects so far, unlike stopping a thread (deprecated), and guarantees a cancel, unlike interrupting.

I've found a nasty way to do it.
I am developing an android app, but I assume similar logic can apply to other platforms
I've set a progressListener to the upload request:
uploader.setProgressListener(new MediaHttpUploaderProgressListener() {
#Override
public void progressChanged(MediaHttpUploader uploader) throws IOException {
if (cancelUpload) {
//This was the only way I found to abort the download
throw new GoogleDriveUploadServiceCancelException("Upload canceled");
}
reportProgress(uploader);
}
});
As you can see, I've used a boolean member that is set from outside when I need to abort the upload.
If this boolean is set to true, then on the next update of the upload progress I will crash, resulting in the abortion of the request.
Again, very ugly, but that was the only way I found to make it work

Related

How to stop uninterruptible job in Java

Currently, I use a SDK to upload images. However, the upload method have not provided timeout option. Therefore I need to set timeout manually. One option is :
public static String uploadImg(String imgStream) {
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<String> future = executor.submit(new uploadableTask(imgStream));
try {
final String res = future.get(500, TimeUnit.SECONDS);
return res;
} catch (final TimeoutException e) {
future.cancel(true);
executor.shutdownNow();
return null;
} catch (final InterruptedException e) {
return null;
} catch (final ExecutionException e) {
return null;
}
}
However, future.cancel(true); probably will not work. It depends on the implementation of upload method of SDK in uploadableTask class(ex. If the interrupt flag will not be checked, the upload method cannot stop). Anyone know other solutions to do that?
... probably will not work ...
is a rather unproductive way of reasoning. Why not just test it? It might probably work!!
But yes, i also believe that probably it wont work. In that case question is do you really need to cancel it? It is an upload process anyway. What harm can it do™? Also remember, even if everything inside java works just fine, you still have no deterministic way to cancel the upload itself. Due to the very nature of http and networks in general, (assuming it is an http upload) there is no deterministic way to cancel once the data leaves the jvm - which it does pretty fast. Jvm is just waiting for acknowledgement of receipt, not actual transmission. So, do you really need to cancel it?
If you do, then the only answer is that threads are an unsuitable choice for cancellable and rather long running activities. If you are ready to pay the price, you can choose to fork out a separate process - which can be deterministically killed. Go for ProcessBuilder and carve out the upliad code in a different jar. An http upload is still not guranteed to die.

How Do I periodically Check For Updates on a Parse Server? [duplicate]

This question already has an answer here:
How to call asyncTasks periodically
(1 answer)
Closed 8 years ago.
Helly Community. I´m fairly new to Android and probably the biggest noob when it comes to networking and backend.
Right now I´m having following problem.
I´m building a simple chatting application and want my app to check the Parse server for a specific message parseobject.
Getting the Objects, working with them and deleting them works fine.
If i do it only once.
This is how I get messages from the Cloud and add them to my App Layout.
ParseQuery<ParseObject> query = ParseQuery.getQuery("message");
query.whereEqualTo("recipient", getRemote_id());
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> messages, ParseException e) {
if(messages != null){
Iterator itr = messages.iterator();
while(itr.hasNext()){
ParseObject message = (ParseObject)itr.next();
addMessageToLayout(message.getString("text"), "in", "new", "");
try {
message.delete();
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
});
I want my app to check for new messages the whole time.
Ive tried with AsyncTask and a while(true) loop. The loop constantly creates new asynctask objects.
As result the app doesn´t react anymore and crashes.
When I use an instance of the runnable class im getting following error: NetworkOnMainThreadException, and the App crashes.
Because of this error i tried using asynctask in the first place. Isn´t a runnably object running on a different thread than the main thread as well?
I tried putting the thread to sleep for some seconds, still the app crashes in case of the async task.
Could the Problem be following: Im using anoher runnable object to update some animation in my app.
I also tried not using any kind of threading as the parse methods already work in background so they probably dont even need one. Again the app crashes because of an NetworkOnMainThreadException.
///_////
The weirdest thing comes now. If i´m not using a loop, and just check for messages when i enter the activity at first i´m getting an NetworkOnMainThreadException, but then the application somehow recovers into the newly opened activity and loads my messages from the server.
During that time of course the UI is blocked though. Still, thats the only way i can get it to work right now.
Doing it with a Handler and the TimerTask works, I can´t seem to close the thread when i exit the Activity though.
Here my code:
public void startLookingForMessages(){
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
new GetMessagesTask().execute();
}
});
}
};
timer.schedule(task, 0, 1000);
}
I found out that im getting the NetworkOnMainThreadException only if i´m trying to shut down the thread or close the while loop when calling onStop(). If I let the thread do its own thing, that means not putting in any code to stop it any time, my app works fine.
How could i overcome this problem?
I know this is getting kinda long. But maybe someone has the same Problem and can get some Info here.
Thanks you for your help already =)
Don't do it this way. Just don't.
Think about it: you're calling an AsyncTask to check periodically if something is there. Now, that gets to be quite expensive. Think about the battery and network resources you waste if that message is not there. Therefore, you waste a lot of resources. It's not a good idea to do it like this. You waste the user's resources. In addition, you also need a service to run in the background, as your app will not always be running.
A good way to solve this is to use Google Cloud Messaging. So what Google Cloud Messaging does is it "pings" a device every time there's an update. This makes life easier on you, as you only need to check if your app has received one of these pings, and it also saves battery and network resources.
If you're using PHP for your server-side application, you can use this to get started with GCM and PHP: GCM with PHP (Google Cloud Messaging)
This page on Google's website should also help with implementing it.
By using GCM, you'll also avoid having infinite loops or checking for more information every x minutes. You don't have to check yourself if new information is available; it'll ping you when it's available.

Interrupt a long running Jersey Client operation

I am using the Oracle Jersey Client, and am trying to cancel a long running get or put operation.
The Client is constructed as:
JacksonJsonProvider provider = new JacksonJsonProvider(new ObjectMapper());
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getSingletons().add(provider);
Client client = Client.create(clientConfig);
The following code is executed on a worker thread:
File bigZipFile = new File("/home/me/everything.zip");
WebResource resource = client.resource("https://putfileshere.com");
Builder builder = resource.getRequestBuilder();
builder.type("application/zip").put(bigZipFile); //This will take a while!
I want to cancel this long-running put. When I try to interrupt the worker thread, the put operation continues to run. From what I can see, the Jersey Client makes no attempt to check for Thread.interrupted().
I see the same behavior when using an AsyncWebResource instead of WebResource and using Future.cancel(true) on the Builder.put(..) call.
So far, the only solution I have come up with to interrupt this is throwing a RuntimeException in a ContainerListener:
client.addFilter(new ConnectionListenerFilter(
new OnStartConnectionListener(){
public ContainerListener onStart(ClientRequest cr) {
return new ContainerListener(){
public void onSent(long delta, long bytes) {
//If the thread has been interrupted, stop the operation
if (Thread.interrupted()) {
throw new RuntimeException("Upload or Download canceled");
}
//Report progress otherwise
}
}...
I am wondering if there is a better solution (perhaps when creating the Client) that correctly handles interruptible I/O without using a RuntimeException.
I am wondering if there is a better solution (perhaps when creating the Client) that correctly handles interruptible I/O without using a RuntimeException.
Yeah, interrupting the thread will only work if the code is watching for the interrupts or calling other methods (such as Thread.sleep(...)) that watch for it.
Throwing an exception out of listener doesn't sound like a bad idea. I would certainly create your own RuntimeException class such as TimeoutRuntimeException or something so you can specifically catch and handle it.
Another thing to do would be to close the underlying IO stream that is being written to which would cause an IOException but I'm not familiar with Jersey so I'm not sure if you can get access to the connection.
Ah, here's an idea. Instead of putting the File, how about putting some sort of extension on a BufferedInputStream that is reading from the File but also has a timeout. So Jersey would be reading from the buffer and at some point it would throw an IOException if the timeout expires.
As of Jersey 2.35, the above API has changed. A timeout has been introduces in the client builder which can set read timeout. If the server takes too long to respond, the underlying socket will timeout. However, if the server starts sending the response, it shall not timeout. This can be utilized, if the server does not start sending partial response, which depends on the server implementation.
client=(JerseyClient)JerseyClientBuilder
.newBuilder()
.connectTimeout(1*1000, TimeUnit.MILLISECONDS)
.readTimeout(5*1000, TimeUnit.MILLISECONDS).build()
The current filters and interceptors are for data only and the solution posted in the original question will not work with filters and interceptors (though I admit I may have missed something there).
Another way is to get hold of the underlying HttpUrlConnection (for standard Jersey client configuration) and it seems to be possible with org.glassfish.jersey.client.HttpUrlConnectorProvider
HttpUrlConnectorProvider httpConProvider=new HttpUrlConnectorProvider();
httpConProvider.connectionFactory(new CustomHttpUrlConnectionfactory());
public static class CustomHttpUrlConnectionfactory implements
HttpUrlConnectorProvider.ConnectionFactory{
#Override
public HttpURLConnection getConnection(URL url) throws IOException {
System.out.println("CustomHttpUrlConnectionfactory ..... called");
return (HttpURLConnection)url.openConnection();
}//getConnection closing
}//inner-class closing
I did try the connection provider approach, however, I could not get that working. The idea would be to keep reference to the connection by some means (thread id etc.) and close it if the communication is taking too long. The primary problem was I could not find a way to register the provider with the client. The standard
.register(httpConProvider)
mechanism does not seem to work (or perhaps it is not supposed to work like that) and the documentation is a bit sketchy in that direction.

Run a java program after final web page

I hava an app on JSF where I upload a file. Very basic. The question is, is there a way to launch (or keep executing) another java program when I reach the last page of my app? That is:
UploadFile.xhtml -> receiveFile.java -> Thanks.xhtml (user will close this the browser) -> another program make some processing on the recently uploaded file (even if user shutsdown the PC)
I thought using a daemon program that keeps checking if a new file arrived, but I want to know if there's a way to keep executing things even if the user closes the browser.
Thanks.
Certainly the best way to do this is to have a scheduler that will look for certain files every x time interval and do something with it within a thread.
Advice, make sure you shut down the scheduler on context unload. Here is an example on how to use a SchedulerService.
You would want to do something like in a context listener.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable handler = new Runnable() {
public void run() {
// handle file
}
};
scheduler.scheduleAtFixedRate(handler, 10, 10, SECONDS);
Firstly, after receiving file from client, even when client had closed their browser, file is now on the server, and you can process it free (not depend on client now) :-D
As your question, you want to launch something right after page closed. How about using annotation #PreDestroy or #PostContructor with bean scope #ViewScoped in JSF?
(in my mind, you can do this right after receiving file uploaded from client)
A reliable way to implement this would be is to have some form of meta data saved in the database after the file upload is done.
And a separate listener like Quartz to read the meta data periodically and do the post processing.
The same metadata can contain more status flags for that meta data to avoid conflicts during file processing.
Again this would depend upon the complexity of your rrquirements.

two serial tasks slower than parallel

Hi I have a webapp - and in one method I need to encrypt part of data from request and store them on disk and return response.
Response is in no way related to encryption.
The encryption is quite time demanding however. How to make threads or so properly in this problem?
I tried something like
Thread thread ...
thread.start();
or
JobDetail job = encryptionScheduler.getJobDetail(jobDetail.getName(), jobDetail.getGroup());
encryptionScheduler.scheduleJob(jobDetail,TriggerUtils.makeImmediateTrigger("encryptionTrigger",1,1)
I tried servlet where before encryption I close the outpuStream.
or: Executors.newFixedThreadPool(1);
But whatever I tried a client has to wait longer.
btw: why is that so? Can it be faster?
I haven't tried to start thread after context initalization and wait somehow for method needing encryption.
how to speed up this?
thank you
--------------EDIT:
//I use axis 1.4, where I have Handler, which in invoke method encrypt a value:
try {
LogFile logFile = new LogFile(strategy,nodeValue,path, new Date());
LogQueue.queue.add(logFile);
}
catch (Exception e) {
log.error(e.getMessage(),e);
}
EExecutor.executorService.execute(new Runnable() {
public void run() {
try {
LogFile poll = LogQueue.queue.poll();
String strategy = poll.getStrategy();
String value = poll.getNodeValue();
value = encrypt(strategy,value);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(poll.getPath(), true )),"UTF-8"));
writer.print(value);
writer.close();
}catch (IOException e ) {
log.error(e.getMessage(),e);
}
}
});
} catch (Throwable e ) {
log.error(e.getMessage(),e);
}
//besides I have executor service
public class EExecutor { public static ExecutorService executorService = Executors.newCachedThreadPool();}
//and what's really interesting.. when I move encryption from this handler away into another handler which is called
last when I send response! It's faster. But when I leave it in one of the first handlers when I receive request. It's even slower without using threads/servlet etc.
Threads only help you if parts of your task can be done in parallel. It sounds like you're waiting for the encryption to finish before returning the result. If it's necessary for you to do that (e.g., because the encrypted data is the result) then doing the encryption on a separate thread won't help you here---all it will do is introduce the overhead of creating and switching to a different thread.
Edit: If you're starting a new thread for each encryption you do, then that might be part of your problem. Creating new threads is relatively expensive. A better way is to use an ExecutorService with an unbounded queue. If you don't care about the order in which the encryption step happens (i.e., if it's ok that the encryption which started due to a request at time t finishes later than one which started at time t', and t < t'), then you can let the ExecutorService have more than a single thread. That will give you both greater concurrency and save you the overhead of recreating threads all the time, since an ExecutorService pools and reuses threads.
The proper way to do something like this is to have a message queue, such as the standard J2EE JMS.
In a message queue, you have one software component whose job it is to receive messages (such as requests to encrypt some resource, as in your case), and make the request "durable" in a transactional way. Then some independent process polls the message queue for new messages, takes action on them, and transactionally marks the messages as received.

Categories

Resources