Question

I apologise if this is a duplicate(link please?)

I am getting runtime errors like these:

E/AndroidRuntime(26112): FATAL EXCEPTION: AsyncTask #3

E/AndroidRuntime(26112): java.lang.RuntimeException: An error occured while executing doInBackground()

E/AndroidRuntime(26112):    
at android.os.AsyncTask$3.done(AsyncTask.java:299)

E/AndroidRuntime(26112):    
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)

E/AndroidRuntime(26112):    
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)

E/AndroidRuntime(26112):    
at java.util.concurrent.FutureTask.run(FutureTask.java:239)

E/AndroidRuntime(26112):    
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)

E/AndroidRuntime(26112):    
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)

E/AndroidRuntime(26112):    
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)

E/AndroidRuntime(26112):    
at java.lang.Thread.run(Thread.java:856)

E/AndroidRuntime(26112): 
Caused by: org.scribe.exceptions.OAuthException: Problems while creating connection.

E/AndroidRuntime(26112):    
at org.scribe.model.Request.send(Request.java:70)

E/AndroidRuntime(26112):    
at org.scribe.model.OAuthRequest.send(OAuthRequest.java:12)

E/AndroidRuntime(26112):    
at com.notbyimgur.imguraffe.ImageGridActivity$getAccountData.doInBackground(ImageGridActivity.java:1091)

E/AndroidRuntime(26112):    
at com.notbyimgur.imguraffe.ImageGridActivity$getAccountData.doInBackground(ImageGridActivity.java:1)

E/AndroidRuntime(26112):    
at android.os.AsyncTask$2.call(AsyncTask.java:287)

E/AndroidRuntime(26112):    
at java.util.concurrent.FutureTask.run(FutureTask.java:234)

E/AndroidRuntime(26112):    ... 4 more

E/AndroidRuntime(26112): Caused by: java.io.EOFException

E/AndroidRuntime(26112):    at libcore.io.Streams.readAsciiLine(Streams.java:203)

E/AndroidRuntime(26112):    at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573)

E/AndroidRuntime(26112):    at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821)

E/AndroidRuntime(26112):    
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283)

E/AndroidRuntime(26112):    
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:495)

E/AndroidRuntime(26112):    
at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)

E/AndroidRuntime(26112):    at org.scribe.model.Response.<init>(Response.java:28)

E/AndroidRuntime(26112):    at org.scribe.model.Request.doSend(Request.java:110)

E/AndroidRuntime(26112):    at org.scribe.model.Request.send(Request.java:62)

E/AndroidRuntime(26112):    ... 9 more

Code:

Have only posted the part with issue. There are multiple OAuth requests(all in separate asynctask classes) in same activity which are probably being executed simultaneously, if that is significant.

public class getAccountData extends AsyncTask<Void, Void, dataModels.Account>
    {
        private String url = "";
        private String accessToken = "";    
        private Client_IDs CLID= new Client_IDs();
        public getAccountData(String urlin, AuthenticationToken autht)
        { 
            url = urlin;
            accessToken = autht.accessToken;
        }

        @Override
        protected dataModels.Account doInBackground(Void... params) {

            OAuthService service = new ServiceBuilder()
                            .provider(ImgUr3Api.class)
                            .apiKey(CLID.CLIENT_ID)
                            .apiSecret(CLID.CLIENT_SECRET)
                            .debug()
                            .build();
            OAuthRequest request = new OAuthRequest(Verb.GET, url);
            request.setConnectionKeepAlive(true);
            service.signRequest(new Token(accessToken, null), request);
            Response response = request.send();

            if(response.getBody() != null)
            {   String body = response.getBody();
                dataModels.Account account = new dataModels.Account();
                JSONObject rawData;
                try {
                    rawData = new JSONObject(body);
                    if(rawData.getBoolean("success"))
                    {
                        JSONObject data = rawData.getJSONObject("data");
                        account.id = data.getInt("id");
                        account.bio = data.getString("bio");
                        account.url = data.getString("url");
                        account.reputation = (int)data.getDouble("reputation");
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return account;
            }
            return null;
        }
        @Override
        protected void onPostExecute(dataModels.Account account)
        {
            if(account !=null)
            {               
                userAcc.id = account.id;
                userAcc.bio = account.bio;
                userAcc.reputation = account.reputation;
                userAcc.url = account.url;
                if(!isCancelled())
                finalizeSlider(true);
            }
        }
    }

I have tried toggling request.setConnectionKeepAlive(true/false) without any positive results. Apart from that I am clueless on what else to try. Please advise.

This is the code from org.scribe.model.Request class (Scribe library)

package org.scribe.model;

import java.io.*;
import java.net.*;
import java.nio.charset.*;
import java.util.*;
import java.util.concurrent.*;

import org.scribe.exceptions.*;

/**
 * Represents an HTTP Request object
 * 
 * @author Pablo Fernandez
 */
public class Request
{
  private static final String CONTENT_LENGTH = "Content-Length";
  private static final String CONTENT_TYPE = "Content-Type";
  private static RequestTuner NOOP = new RequestTuner() {
    @Override public void tune(Request _){}
  };
  public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";

  private String url;
  private Verb verb;
  private ParameterList querystringParams;
  private ParameterList bodyParams;
  private Map<String, String> headers;
  private String payload = null;
  private HttpURLConnection connection;
  private String charset;
  private byte[] bytePayload = null;
  private boolean connectionKeepAlive = false;
  private boolean followRedirects = true;
  private Long connectTimeout = null;
  private Long readTimeout = null;

  /**
   * Creates a new Http Request
   * 
   * @param verb Http Verb (GET, POST, etc)
   * @param url url with optional querystring parameters.
   */
  public Request(Verb verb, String url)
  {
    this.verb = verb;
    this.url = url;
    this.querystringParams = new ParameterList();
    this.bodyParams = new ParameterList();
    this.headers = new HashMap<String, String>();
  }

  /**
   * Execute the request and return a {@link Response}
   * 
   * @return Http Response
   * @throws RuntimeException
   *           if the connection cannot be created.
   */
  public Response send(RequestTuner tuner)
  {
    try
    {
      createConnection();
      return doSend(tuner);
    }
    catch (Exception e)
    {
      throw new OAuthConnectionException(e);
    }
  }

  public Response send()
  {
    return send(NOOP);
  }

  private void createConnection() throws IOException
  {
    String completeUrl = getCompleteUrl();
    if (connection == null)
    {
      System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false");
      connection = (HttpURLConnection) new URL(completeUrl).openConnection();
      connection.setInstanceFollowRedirects(followRedirects);
    }
  }

  /**
   * Returns the complete url (host + resource + encoded querystring parameters).
   *
   * @return the complete url.
   */
  public String getCompleteUrl()
  {
    return querystringParams.appendTo(url);
  }

  Response doSend(RequestTuner tuner) throws IOException
  {
    connection.setRequestMethod(this.verb.name());
    if (connectTimeout != null) 
    {
      connection.setConnectTimeout(connectTimeout.intValue());
    }
    if (readTimeout != null)
    {
      connection.setReadTimeout(readTimeout.intValue());
    }
    addHeaders(connection);
    if (verb.equals(Verb.PUT) || verb.equals(Verb.POST))
    {
      addBody(connection, getByteBodyContents());
    }
    tuner.tune(this);
    return new Response(connection);
  }

  void addHeaders(HttpURLConnection conn)
  {
    for (String key : headers.keySet())
      conn.setRequestProperty(key, headers.get(key));
  }

  void addBody(HttpURLConnection conn, byte[] content) throws IOException
  {
    conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(content.length));

    // Set default content type if none is set.
    if (conn.getRequestProperty(CONTENT_TYPE) == null)
    {
      conn.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
    }
    conn.setDoOutput(true);
    conn.getOutputStream().write(content);
  }

  /**
   * Add an HTTP Header to the Request
   * 
   * @param key the header name
   * @param value the header value
   */
  public void addHeader(String key, String value)
  {
    this.headers.put(key, value);
  }

  /**
   * Add a body Parameter (for POST/ PUT Requests)
   * 
   * @param key the parameter name
   * @param value the parameter value
   */
  public void addBodyParameter(String key, String value)
  {
    this.bodyParams.add(key, value);
  }

  /**
   * Add a QueryString parameter
   *
   * @param key the parameter name
   * @param value the parameter value
   */
  public void addQuerystringParameter(String key, String value)
  {
    this.querystringParams.add(key, value);
  }

  /**
   * Add body payload.
   * 
   * This method is used when the HTTP body is not a form-url-encoded string,
   * but another thing. Like for example XML.
   * 
   * Note: The contents are not part of the OAuth signature
   * 
   * @param payload the body of the request
   */
  public void addPayload(String payload)
  {
    this.payload = payload;
  }

  /**
   * Overloaded version for byte arrays
   *
   * @param payload
   */
  public void addPayload(byte[] payload)
  {
    this.bytePayload = payload.clone();
  }

  /**
   * Get a {@link ParameterList} with the query string parameters.
   * 
   * @return a {@link ParameterList} containing the query string parameters.
   * @throws OAuthException if the request URL is not valid.
   */
  public ParameterList getQueryStringParams()
  {
    try
    {
      ParameterList result = new ParameterList();
      String queryString = new URL(url).getQuery();
      result.addQuerystring(queryString);
      result.addAll(querystringParams);
      return result;
    }
    catch (MalformedURLException mue)
    {
      throw new OAuthException("Malformed URL", mue);
    }
  }

  /**
   * Obtains a {@link ParameterList} of the body parameters.
   * 
   * @return a {@link ParameterList}containing the body parameters.
   */
  public ParameterList getBodyParams()
  {
    return bodyParams;
  }

  /**
   * Obtains the URL of the HTTP Request.
   * 
   * @return the original URL of the HTTP Request
   */
  public String getUrl()
  {
    return url;
  }

  /**
   * Returns the URL without the port and the query string part.
   * 
   * @return the OAuth-sanitized URL
   */
  public String getSanitizedUrl()
  {
    return url.replaceAll("\\?.*", "").replace("\\:\\d{4}", "");
  }

  /**
   * Returns the body of the request
   * 
   * @return form encoded string
   * @throws OAuthException if the charset chosen is not supported
   */
  public String getBodyContents()
  {
    try
    {
      return new String(getByteBodyContents(),getCharset());
    }
    catch(UnsupportedEncodingException uee)
    {
      throw new OAuthException("Unsupported Charset: "+charset, uee);
    }
  }

  byte[] getByteBodyContents()
  {
    if (bytePayload != null) return bytePayload;
    String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString();
    try
    {
      return body.getBytes(getCharset());
    }
    catch(UnsupportedEncodingException uee)
    {
      throw new OAuthException("Unsupported Charset: "+getCharset(), uee);
    }
  }

  /**
   * Returns the HTTP Verb
   * 
   * @return the verb
   */
  public Verb getVerb()
  {
    return verb;
  }

  /**
   * Returns the connection headers as a {@link Map}
   * 
   * @return map of headers
   */
  public Map<String, String> getHeaders()
  {
    return headers;
  }

  /**
   * Returns the connection charset. Defaults to {@link Charset} defaultCharset if not set
   *
   * @return charset
   */
  public String getCharset()
  {
    return charset == null ? Charset.defaultCharset().name() : charset;
  }

  /**
   * Sets the connect timeout for the underlying {@link HttpURLConnection}
   * 
   * @param duration duration of the timeout
   * 
   * @param unit unit of time (milliseconds, seconds, etc)
   */
  public void setConnectTimeout(int duration, TimeUnit unit)
  {
    this.connectTimeout = unit.toMillis(duration);
  }

  /**
   * Sets the read timeout for the underlying {@link HttpURLConnection}
   * 
   * @param duration duration of the timeout
   * 
   * @param unit unit of time (milliseconds, seconds, etc)
   */
  public void setReadTimeout(int duration, TimeUnit unit)
  {
    this.readTimeout = unit.toMillis(duration);
  }

  /**
   * Set the charset of the body of the request
   *
   * @param charsetName name of the charset of the request
   */
  public void setCharset(String charsetName)
  {
    this.charset = charsetName;
  }

  /**
   * Sets whether the underlying Http Connection is persistent or not.
   *
   * @see http://download.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html
   * @param connectionKeepAlive
   */
  public void setConnectionKeepAlive(boolean connectionKeepAlive)
  {
    this.connectionKeepAlive = connectionKeepAlive;
  }

  /**
   * Sets whether the underlying Http Connection follows redirects or not.
   *
   * Defaults to true (follow redirects)
   *
   * @see http://docs.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#setInstanceFollowRedirects(boolean)
   * @param followRedirects
   */
  public void setFollowRedirects(boolean followRedirects)
  {
    this.followRedirects = followRedirects;
  }

  /*
   * We need this in order to stub the connection object for test cases
   */
  void setConnection(HttpURLConnection connection)
  {
    this.connection = connection;
  }

  @Override
  public String toString()
  {
    return String.format("@Request(%s %s)", getVerb(), getUrl());
  }
}
Was it helpful?

Solution

That error almost drove me to insanity when I struggled with it, I (think) solved the problem by making minor changes in my code. Hope it helps you too.

  1. If your httpurlconnection request is a POST request remove this line conn.setDoOutput(true);

  2. Before getting the outputStream call to conn.connect()

  3. Finally I removed http.keepAlive sentece at all.

No more random EOF so far (since i've changed it last week).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top