in my android app I have an AsyncTask which downloads photos from my server. If I get an exception (mainly for connection time out) I show the user a message. My problem is that my code works MOST of the times, (meaning there are times when I interrupt the WiFi connection that I get an exception shown in my logcat but the message won't appear so I ended it up thinking that there might be an exception that I don't handle ) and I can't figure out the exact reason. I'll post the code run in my AsyncTask and the function that does the essential work. Hope you spot out something I'missing
#Override
protected String doInBackground(String... args) {
JSONParser jParser = new JSONParser();
JSONObject jsonObj = jParser.getJSONFromUrl(url);
Log.d("check1",url);
try {
list.addAll(processJsonData(jsonObj));
} catch (JSONException e) {
e.printStackTrace();
onDownloadFailed(this);
return "failed";
} catch (SocketException e) {
Log.e("Exception", e.getLocalizedMessage());
onDownloadFailed(this);
return "failed";
} catch (IOException e) {
Log.e("Exception", e.getLocalizedMessage());
onDownloadFailed(this);
return "failed";
}finally {
jsonObj=null;
}
return "done";
}
process JsonData is actually bigger that's the part for downloading the photos, the other part is about mapping string to an large Json File
private ArrayList<Monument> processJsonData(JSONObject jsonObj) throws IOException, SocketException, JSONException{
if(attachments!=null){
int lengthSize;
if(attachments.length()<3)
lengthSize=attachments.length();
else
lengthSize=3;
for(int j=0;j<lengthSize;++j){
JSONObject atta = attachments.getJSONObject(j);
JSONObject images = atta.optJSONObject(TAG_IMAGES);
if(images!=null){
JSONObject medium = images.getJSONObject(TAG_MEDIUM);
String url_image = medium.getString(TAG_URL_IMAGE);
String id = atta.getString("id");
String filename =title.replace(" ","")+id+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
URL url = new URL (url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
}
}
}
Maybe you could name the actual exception that is beeing thrown?
It might be a RuntimeException and therefore unchecked.
For further information about checked/unchecked exceptions see: Oracle Docs - Exceptions
The API for InteruptedException says the following;
Thrown when a thread is waiting, sleeping, or otherwise occupied, and
the thread is interrupted, either before or during the activity.
Occasionally a method may wish to test whether the current thread has
been interrupted, and if so, to immediately throw this exception.
As described in the comments of the question, cancelling your AsyncTask only after checking that it has finished should prevent this issue.
Alternatively (but I would recommend against it), you could catch the InteruptedException in the method that cancels your AsyncTask to define your custom catch behavior there. Using catch to work around program logic flaws should only really be a last resort after reconsidering the logical flow of your code.
Related
I have an Android app written in Java, and recently noticed many crash reports occurring in an AsyncTask. The stack trace makes no sense, as it is inside a try/catch so there is no way for the exception to be thrown. How can a caught exception cause an app crash?
13: public class HttpGoogleSignInAction...
#Override
protected String doInBackground(Void... voids) {
try {
// Check if user exists
UserConfig user = null;
31: user = MainActivity.connection.fetch(this.config);
if (user == null) {
} else {
// User exists, try to sign in user
this.config = MainActivity.connection.connect(this.config);
}
} catch (Exception userDoesNotExist) {
try {
// User does not exist, try to create user
this.config = MainActivity.connection.create(this.config);
} catch (Exception exception) {
this.exception = exception;
}
}
return "";
}
public String POST(String url, String xml) {
if (this.debug) {
System.out.println("POST: " + url);
System.out.println("XML: " + xml);
}
String result = "";
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
StringEntity content = new StringEntity(xml, "utf-8");
content.setContentType("application/xml");
httpPost.setEntity(content);
HttpResponse response = httpClient.execute(httpPost, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, HTTP.UTF_8);
}
if ((response.getStatusLine().getStatusCode() != 200) && (response.getStatusLine().getStatusCode() != 204)) {
this.exception = new SDKException(""
+ response.getStatusLine().getStatusCode()
+ " : " + result);
2205: throw this.exception;
}
} catch (Exception exception) {
if (this.debug) {
exception.printStackTrace();
}
this.exception = new SDKException(exception);
2213: throw this.exception;
}
return result;
}
The stack trace shows the crash occurring in the line,
user = MainActivity.connection.fetch(this.config);
It is a normal RuntimeException subclass exception being thrown, which should be caught. If I try to force an exception to test it the try/catch works fine and no crash, but in 1% of users using the app I am seeing crashes, others it works fine.
Makes no sense.
This is the stack trace from Google Play, SDKException is a subclass of RuntimeException, the line of code it occurs in is inside try/catch
org.botlibre.sdk.SDKException:
at org.botlibre.sdk.SDKConnection.POST (SDKConnection.java:2213)
at org.botlibre.sdk.SDKConnection.fetch (SDKConnection.java:259)
at ...HttpGoogleSignInAction.doInBackground (HttpGoogleSignInAction.java:31)
at ...HttpGoogleSignInAction.doInBackground (HttpGoogleSignInAction.java:13)
at android.os.AsyncTask$3.call (AsyncTask.java:394)
at java.util.concurrent.FutureTask.run (FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
at java.lang.Thread.run (Thread.java:923)
Caused by: org.botlibre.sdk.SDKException:
at org.botlibre.sdk.SDKConnection.POST (SDKConnection.java:2205)
org.botlibre.sdk.SDKException:
at org.botlibre.sdk.SDKConnection.POST (SDKConnection.java:2213)
at org.botlibre.sdk.SDKConnection.fetch (SDKConnection.java:259)
Shows that you're throwing the exception captured here in doInBackground():
try {
// User does not exist, try to create user
this.config = MainActivity.connection.create(this.config);
} catch (Exception exception) {
**this.exception = exception;**
}
}
Even though this execption is within a catch block, since it's persisted and then thrown later it is now outside of a try-catch block and can crash the app. That is
try {
...
} catch (Exception exception) {
if (this.debug) {
exception.printStackTrace();
}
this.exception = new SDKException(exception);
// This line will throw an execption that will have the message from the original exception.
2213: throw this.exception;
}
The source for SDKException's single exception constructor shows it reuses the message from the exception parameter.
You are very clearly re-throwing the caught exception on line 2213. If you throw an exception from a catch block, it escapes the try/catch because you are throwing it from a scope of code that is not surrounded by try { }.
As for why fetch() might be throwing, we would have to see the code to be able to guess.
Even though you have your code wrapped in try catch, there is a possibility of a crash if different threads are involved. try catch does not catch exceptions from child threads, so if any of your methods(like .fetch or .connect) used in doInBackground are internally using/creating different threads and an exception is thrown within that thread it might cause the app to crash. Looking at the logs, it is possible the .fetch method is asynchronous and performing operations in a different thread.
I'm developing an Android printing application. A part of my application is a local server that receive files from the users.
I implemented the server in Tomcat Java servlet.
My problem is that when two devices sending 2 files instantaneously to the server, there is two possible results:
1. One client receives a good response, and the second client receives an empty response.
2. One client receives a response of the second client and vise versa.
Here is my servlet code:
protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
new Runnable() {
#Override
public void run() {
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
response.setCharacterEncoding("UTF-8");
try {
writer = response.getWriter();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
// get access to file that is uploaded from client
Part p1 = request.getPart("File");
InputStream is = p1.getInputStream();
// read filename which is sent as a part
Part p2 = request.getPart("MetaData");
Scanner s = new Scanner(p2.getInputStream());
String stringJson = s.nextLine(); // read filename from stream
s.close();
json = new JSONObject(stringJson);
fileName = new String(json.getString("FileName").getBytes("UTF-8"));
fileDirectory = BASE + request.getSession().getId();
File dir = new File(fileDirectory);
dir.mkdir();
// get filename to use on the server
String outputfile = BASE + dir.getName() + "/" + fileName; // get path on the server
FileOutputStream os = new FileOutputStream (outputfile);
// write bytes taken from uploaded file to target file
byte[] buffer = new byte[1024];
int ch = is.read(buffer);
while (ch != -1) {
os.write(buffer);
ch = is.read(buffer);
}
os.close();
is.close();
}
catch(Exception ex) {
writer.println("Exception -->" + ex.getMessage());
}
finally {
try {
myRequest = request;
try {
printFile(request.getSession().getId());
} catch (IOException e) {
// TODO Auto-generated catch block
writer.println("Exception -->" + e.getMessage());
}
writer.close();
} catch (InterruptedException e) {
writer.println("Exception -->" + e.getMessage());
}
}
}
}.run();
}
The tomcat server is running over Ubuntu 13.04 as a virtual machine.
Any idea?
I don't think the use of Runnable makes a difference but it's kind of pointless. I can't see where you declared your writer. If that's an instance variable of the servlet (i.e. not in the post method) then that one is prone to session swapping when used by two sessions at the same time. Try declaring it within the post method.
You need not to implement Runnable. By default Servlets are thread safe, which means a new thread is created for each of the request. If you are using some static variables then make sure you use them in a thread safe way. I think your thread creation may be troubling the tomcat/container to send the response in an incorrect way. In short I believe you are doing more than is required, container is there for your rescue.
Any web container manages multi-threading of servlets. You need not implement your own thread. Remove the multi-threading from your code and it will work perfectly.
I am trying to send the object from applet to struts action class
using object output stream but it gives me a exception java.net.ProtocolException: Cannot write output after reading input.
I created a new instance of URLConnection to giving specific url
and tried to write object in url to send the struts action class from applet
i am calling this method on save button click of applet
public saveDesign()
{
try
{
HttpURLConnection urlConnection = getServletConnection(CallServletConnection.SAVE_DESIGN, null);
// Pragma = no-cache; should be null
if(urlConnection != null && urlConnection.getHeaderFields().get("Pragma") != null)
return false;
OutputStream outstream = urlConnection.getOutputStream();//Exception occur here
ObjectOutputStream objectoutstream = new ObjectOutputStream(outstream);
objectoutstream.writeObject("abc");
objectoutstream.flush();
objectoutstream.close();
System.out.println("vctObjectDetails is write ");
}
catch (MalformedURLException exception) {
exception.printStackTrace();
}
catch(ConnectException exception) {
exception.printStackTrace();
}
catch (IOException exception) {
exception.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
but it doesn't work.
Please gives me some tips if anyone knows how to handle this exception.
It all has to do with the lifecycle of an HTTP request (which is what HttpURLConnection abstracts) - once the request has been sent, you cannot modify it any further - in case you have more data to send, you just make another one.
What is happening underneath is that once you call getHeaderFields() (the response header fields), the 'HttpURLConnection' sends the request and makes the response available.
I don't know what is in 'getServletConnection()', but you could try using 'doOutput()' and not reading from the response, until you have finished writing to the request.
I have code that looks something like:
public static void func(Reader r){
int c = r.read();
...
}
and the compiler tells me that r.read() might throw an IOException. Under what circumstances might this happen? It seems clear that something like FileNotFoundException is thrown when a file is not found, but an IOException is rather vague.
Edit:
In case it is of interest to anyone, I asked this question because I thought there must be a better way of handling the situation than just printStackTrace. However, without knowing what might cause the exception, I wasn't really sure how it should be done.
Lots of things can cause an IOException. When it gets thrown, you can print it out or check the message (Exception.getMessage()) to see what caused it.
A FileNotFoundException is a subclass of IOException, you can check the "known subclasses" list for others.
For example:
public void load(InputStream inputStream) throws IOException {
this.inputStream = inputStream;
this.properties.load(this.inputStream);
this.keys = this.properties.propertyNames();
inputStream.close();
}
I think that's when you have problem with input / output (connections) because of security or for example not opening the stream.
Code source: stackoverflow
It can throw an IOException when the either the stream itself is corrupted or some error occurred during reading the data i.e. Security Exceptions, Permission Denied etc and/or a set of Exceptions which are derived from IOEXception.
IOException is superclass of many exceptions like CharConversionException, CharacterCodingException and EOFException.
If the method listed all these exceptions then caller would have to catch all of them. So for convenience having IOException in throws clause helps callers to avoid multiple catch blocks. User can still handle specific exception if they desire so by checking for instance of or exception.getMessage().
If you want to know the specifics, in your catch block do this:
catch (IOException e)
{
e.printStackTrace();
}
This code will help you to debug and to see the IOException thrown:
String NL = System.getProperty("line.separator");
String line;
FileInputStream in;
try {
fileName = choose.getSelectedFile().getCanonicalPath();
} catch (IOException e) {
e.printStackTrace(); //This doesn't matter, see the second IOException catch.
}
try {
in = new FileInputStream(choose.getSelectedFile());
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
StringBuffer content=new StringBuffer("");
while((line = reader.readLine()) != null){
content.append(line+NL);
}
textArea.setText(content.toString());
reader.close();
reader.readLine();
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(new JFrame(), "The file does not exist!", "Error", JOptionPane.WARNING_MESSAGE);
} catch (IOException e) {
JOptionPane.showMessageDialog(new JFrame(), "There was an error in reading the file.", "Error", JOptionPane.WARNING_MESSAGE);
}
Good luck.
I have several questions about best use of exceptions in Java.
Consider the code below:
private String doHttpGetRequest(String url) throws IOException {
...
}
private Photo processJson(String json) throws JSON Exception{
...
}
private Photo getPhoto() throws IOException, JSON Exception {
String url = "http://...";
String response = doHttpGetRequest(url);
Photo photo = processJson(response);
photo.downloadImage();
return photo;
}
public static void main(String args[]) {
Photo p = null;
try {
p = getPhoto();
} catch( JSONException j ) {
// Re-try a few times, then display user alert
} catch( IOException e ) {
// Re-try a few times, then display user alert
}
if( p!=null)
// now display photo
}
This code is for an android app where the connection may not be very reliable, so I would like to re-try the getPhoto() method a few times to see if it will work, then fail and alert the user.
My questions:
I am opening an InputStream in doHttpGetRequest() and that method is throwing an IOException. How do I close the InputStream if it has thrown the exception? Without a finally block within the method that would allow me to close resources, i'm confused.
In main(), I'm only interested in whether getPhoto() works or does not work. Would I be better to surround statements inside getPhoto() with a try/catch block and catch the JSONException, throwing a new IOException when it is caught? This would lead to only having to catch one kind of exception in main(), leading to simpler code and not having duplicate functionality.
If p.getPhoto() throws an exception, I want to re-try it (possibly twice) and then display a user alert if this fails. Is there a common programming structure to doing this?
doHttpGetRequest() should be in charge of closing the inputstream. Finally-block there would be suitable for closing (why don't you want finally block?).
Do you have to pass any exceptions to the main method. You could surround doHttpGetRequest(url) with try{} and surround processJson with another (I quess this one doesn't benefit from retries). This would make the main() method cleaner.
If you go with my suggestion on 2. you could do the retrying like this:
String response = null;
for (int i = 0; i < RETRY_COUNT && response == null; i++){
try {
response = doHttpGetRequest(url);
} catch (IOException e){
// Possibly log the error here
}
}
if (response == null) return null;
EDIT: Bugfix
You can catch the exception, clean up and re-throw it. Why are you avoiding using finally block? It looks like it would fit there very well.
It will probably be more code than handling those two exception separately.
Put it in a for loop, continue if there was an exception and break if not.
You should still use try-finally block so you are able to close the resources. The block is used like this:
InputStream is;
try {
is = openStream(); //This is a sample code, which
//Do something with the stream
} finally {
if (is != null) is.close();
}
This way if an exception is thrown, the stream will be closed anyway, and the exception will be handled elsewhere.
I suggest you creating your own exception (say, PhotoReadingException) and throw it from getPhoto(), but setting its cause to the original exception via the initCause(Throwable cause) method.
Certainly, you can use a loop and a variable which shows if the operation was successful.
Photo p = null;
Exception ex = null;
for (int tries = 0; tries < MAX_TRIES; tries++) {
try {
p = getPhoto();
break;
} catch (PhotoReadingException photoException) {
ex = photoException;
}
}
if (ex != null) reportException(ex);