1

I have Android application, which pulls xml from server.

public class FeedParser {

    private final URL mURL;

    public FeedParser(String feedUrl) {
        try {
            mURL = new URL(feedUrl);
        } catch (MalformedURLException e) {
            throw new RuntimeException();
        }
    }

    private InputStream getInputStream() throws IOException {
        return mURL.openConnection().getInputStream();
    }

    public FeedItem parseFeed() {
        // SAX stuff here

        try {
            Xml.parse(getInputStream(), Xml.Encoding.UTF_8,
                    root.getContentHandler());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

Sometimes, when XML.parse(...) executes, I get exception:

 AndroidRuntime: java.lang.RuntimeException: An error occured while executing doInBackground()
 AndroidRuntime:    at android.os.AsyncTask$3.done(AsyncTask.java:200)
 AndroidRuntime:    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
 AndroidRuntime:    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
 AndroidRuntime:    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
 AndroidRuntime:    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
 AndroidRuntime:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
 AndroidRuntime:    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
 AndroidRuntime:    at java.lang.Thread.run(Thread.java:1019)
 AndroidRuntime: Caused by: java.lang.AssertionError: java.net.SocketException: Connection reset by peer
 AndroidRuntime:    at android.util.Xml.parse(Xml.java:89)
 AndroidRuntime:    at com.packagename.FeedParser.parseFeed(FeedParser.java:60)
 AndroidRuntime:    at com.packagename.UpdateService$FeedLookupTask.doInBackground(UpdateService.java:84)
 AndroidRuntime:    at com.packagename.UpdateService$FeedLookupTask.doInBackground(UpdateService.java:1)
 AndroidRuntime:    at android.os.AsyncTask$2.call(AsyncTask.java:185)
 AndroidRuntime:    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
 AndroidRuntime:    ... 4 more
 AndroidRuntime: Caused by: java.net.SocketException: Connection reset by peer
 AndroidRuntime:    at org.apache.harmony.luni.platform.OSNetworkSystem.read(Native Method)
 AndroidRuntime:    at dalvik.system.BlockGuard$WrappedNetworkSystem.read(BlockGuard.java:273)
 AndroidRuntime:    at org.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:458)
 AndroidRuntime:    at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:85)
 AndroidRuntime:    at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:65)
 AndroidRuntime:    at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:140)
 AndroidRuntime:    at java.io.BufferedInputStream.read(BufferedInputStream.java:225)
 AndroidRuntime:    at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.readLine(HttpURLConnectionImpl.java:660)
 AndroidRuntime:    at org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream.readChunkSize(ChunkedInputStream.java:77)
 AndroidRuntime:    at org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream.read(ChunkedInputStream.java:45)
 AndroidRuntime:    at java.io.InputStream.read(InputStream.java:157)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:516)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:479)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:318)
 AndroidRuntime:    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:275)

How do I handle such error?

EDIT Knowing that catching errors is bad programming style, I seek for more elegant solution.

Igor Filippov
  • 14,641
  • 17
  • 81
  • 155
  • 1
    retry the parsing/fetching? Basically an exception isn't bad, it just shows that something went wrong. So just think of a way to retry it and your done (don't retry forever! make a retry counter that limits it)... – WarrenFaith Mar 09 '12 at 14:52
  • I heard that it's bad idea to catch Errors. To do so I'll need to write catch(Throwable)? – Igor Filippov Mar 09 '12 at 14:54
  • No, you don't. catch(AssertionError e) is sufficient. – Kirill Rakhman Mar 09 '12 at 15:03
  • You could further guard against the pitfalls of catching errors by only handling AssertionErrors whose cause is a SocketException, rethrowing any other errors. – Mutant Platypus Mar 18 '12 at 00:37

2 Answers2

1

Connection reset by peer means the remote server you're reading from is closing the connection and then you're trying to read from it again. It's not necessarily a network error for the remote side to do this--it could do it for any number of reasons. Without knowing the protocol of your server, it's hard to know the exact reason.

You can set up your code to catch and retry a limited number of times, as suggested above. It's not a bad idea to catch errors.

Another possibility, depending on the size of your xml, is to to read it into a string buffer and then parse it. With large data, this reduces the likelihood of a reset since your server connections will be much shorter than when you're parsing as you go. I'm thinking here of a scenario where the tcp window is closed down for a long time while you're parsing and eventually the other side decides you're dead and resets the connection.

cben
  • 21
  • 6
  • 1
    @JarleHansen Why is it a bad idea to catch errors? If it's an exception you can handle, why not catch it, retry x times, and re-throw if it still fails? – ebaxt Mar 17 '12 at 18:02
  • @JarleHansen Of course, it is a "serious problem" that the remote hung up on the client, but perhaps the server was busy just then? It is eminently a good idea to catch the error in this case and retry a sensible number of times. – alphazero Mar 18 '12 at 00:26
  • You guys are right, seems like this is a case where you actually need to catch the AssertionError. My mistake on this issue. – Jarle Hansen Mar 18 '12 at 01:14
0

AssertionError provides a standard way to warn that an assertion that the programmer has made is incorrect.

So when well used, they are saying "there is a coding bug here" (because you throw them in places that you assert are unreacheable), and that is the reason why AssertionError is an (extends) Error and not an Exception: they inform about a non recoverable (at runtime) failure (since you have to recode the algorithm).

Other usages of this error are just wrong because they are violating its contract.

So, answering your question, you can handle it in to ways:

  • If the code throwing the error is yours (I doubt this is the case given your question, but in the future should be): Review and correct your algorithm.
  • If it is from a third-party library: Register the bug to its author (or try to solve it by your own)

But you should not handle it in your code.

As an additional note: your case makes me doubt about if android.util.Xml.parse() is making a correct usage of it. It is very strange that an AssertionError having a cause (having been constructed from another Throwable), so that is another option to have in mind: maybe this library is not well implemented...

idelvall
  • 1,378
  • 13
  • 25