Я использую google-api-client-java 1.2.1-alpha для выполнения запроса POST и получаю следующую трассировку стека, когда выполняю () HttpRequest.
Это происходит сразу после того, как я перехватываю и игнорирую ошибку 403 из предыдущего запроса POST по тому же URL-адресу и повторно использую транспорт для последующего запроса. (Это цикл, в котором несколько записей вставляются в один канал ATOM).
Что я должен сделать, чтобы «очистить» после 403?
Exception in thread "main" java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:199)
at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:173)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:390)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at com.google.api.client.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:47)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:207)
at au.com.machaira.pss.gape.RedirectHandler.execute(RedirectHandler.java:38)
at au.com.machaira.pss.gape.ss.model.records.TableEntry.executeModification(TableEntry.java:81)
Почему приведенный ниже код пытается установить новое соединение?
java
httpclient
google-api-java-client
Дэвид Баллок
источник
источник
Ответы:
Вам необходимо использовать тело ответа, прежде чем вы сможете повторно использовать соединение для другого запроса. Вы должны не только прочитать статус ответа, но и
InputStream
полностью прочитать ответ до последнего байта, при этом вы просто игнорируете прочитанные байты.источник
google-api-java-client
, это означало уловитьIOException
брошенный объектHttpResponse.execute()
, протестировать / преобразовать егоHttpResponseException
, получить доступ кresponse
члену и затем вызватьparaseAsString()
его. (Что в любом случае оказалось полезной информацией: -)HttpRequest.execute()
автоматически очищает эти ресурсы, если метод не может вернутьHttpResponse
объект. Кроме того, JavaDoc наHttpResponse
данный момент рекомендует вызыватьresponse.disconnect()
в случае неполного чтения содержимого HTTP-ответа (вfinally
блоке).Я столкнулся с аналогичной проблемой при использовании HttpClient с Jetty для создания тестовой среды. Мне пришлось создать несколько запросов к сервлету от моего клиента, но он давал то же исключение при выполнении.
Я нашел альтернативу на http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html
Вы также можете использовать этот следующий метод для создания экземпляра клиента.
public static DefaultHttpClient getThreadSafeClient() { DefaultHttpClient client = new DefaultHttpClient(); ClientConnectionManager mgr = client.getConnectionManager(); HttpParams params = client.getParams(); client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()), params); return client; }
источник
Аналогичное сообщение об исключении (по крайней мере, поскольку HTTP-клиент Apache Jarkata Commons 4.2):
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.
Это исключение может произойти, когда два или более потока взаимодействуют с одним
org.apache.http.impl.client.DefaultHttpClient
.Как сделать
DefaultHttpClient
экземпляр 4.2 потокобезопасным ( потокобезопасным в том смысле, что два или более потока могут взаимодействовать с ним, не получая вышеуказанного сообщения об ошибке)? ОбеспечьтеDefaultHttpClient
пул соединенийClientConnectionManager
в видеorg.apache.http.impl.conn.PoolingClientConnectionManager
!/* using <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.2.2</version> </dependency> */ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.params.HttpConnectionParams; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.http.impl.conn.SchemeRegistryFactory; import org.apache.http.params.HttpParams; import org.apache.http.client.methods.HttpGet; public class MyComponent { private HttpClient client; { PoolingClientConnectionManager conMan = new PoolingClientConnectionManager( SchemeRegistryFactory.createDefault() ); conMan.setMaxTotal(200); conMan.setDefaultMaxPerRoute(200); client = new DefaultHttpClient(conMan); //The following parameter configurations are not //neccessary for this example, but they show how //to further tweak the HttpClient HttpParams params = client.getParams(); HttpConnectionParams.setConnectionTimeout(params, 20000); HttpConnectionParams.setSoTimeout(params, 15000); } //This method can be called concurrently by several threads private InputStream getResource(String uri) { try { HttpGet method = new HttpGet(uri); HttpResponse httpResponse = client.execute(method); int statusCode = httpResponse.getStatusLine().getStatusCode(); InputStream is = null; if (HttpStatus.SC_OK == statusCode) { logger.debug("200 OK Amazon request"); is = httpResponse.getEntity().getContent(); } else { logger.debug("Something went wrong, statusCode is {}", statusCode); EntityUtils.consume(httpResponse.getEntity()); } return is; } catch (Exception e) { logger.error("Something went terribly wrong", e); throw new RuntimeException(e); } } }
источник
Это часто задаваемый вопрос. Ответ BalusC правильный. Пожалуйста, перехватите HttpReponseException и вызовите HttpResponseException. ответ . игнорировать (). Если вам нужно прочитать сообщение об ошибке, используйте ответ. parseAsString (), если вы не знаете тип содержимого ответа, иначе, если вы знаете, что тип содержимого использует ответ. parseAs (MyType.class).
Простой фрагмент кода из YouTubeSample.java в youtube-jsonc-sample (хотя обычно вам нужно сделать что-то более умное в реальном приложении):
} catch (HttpResponseException e) { System.err.println(e.response.parseAsString()); }
Полное раскрытие: я являюсь владельцем проекта google-api-java-client .
источник
У меня была такая же проблема с объектом jax-rs (resteasy)
Response
в моих модульных тестах. Я решил это с помощью вызоваresponse.releaseConnection();
ReleaseConnection () - Method только дляClientResponse
объекта resteasy , поэтому мне пришлось добавить приведение изResponse
вClientResponse
.источник
Попробуй это
HttpResponse response = Client.execute(httpGet); response.getEntity().consumeContent(); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { //task Log.i("Connection", "OK"); }else{ Log.i("Connection", "Down"); }
источник
Хорошо, у меня аналогичная проблема, все эти решения не работают, я тестировал на каком-то устройстве, проблема была в дате на устройстве, это был 2011 год, а не 2013, проверьте, также это может помочь.
источник
Прочтите InputStream следующим образом:
if( response.getStatusLine().getStatusCode() == 200 ) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); try { sb = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( content ), 8 ); String line; while( ( line = bufferedReader.readLine() ) != null ) { sb.append( line ); } bufferedReader.close(); content.close(); } catch( Exception ex ) { Log.e( "statusCode", ex.getMessage() + "" ); } }
источник
просто используйте ответ, как показано ниже, это решит проблему
источник