Używam google-api-client-java 1.2.1-alpha do wykonania żądania POST i otrzymuję następujący ślad stosu, gdy wykonuję () HttpRequest.
Dzieje się tak natychmiast po tym, jak wychwycę i zignoruję błąd 403 z poprzedniego POST pod tym samym adresem URL i ponownie wykorzystam transport dla kolejnego żądania. (Jest w pętli wstawiającej wiele wpisów do tego samego źródła ATOM).
Czy jest coś, co powinienem zrobić, aby „posprzątać” po 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)
Dlaczego poniższy kod miałby próbować uzyskać nowe połączenie?
java
httpclient
google-api-java-client
David Bullock
źródło
źródło
Odpowiedzi:
Musisz wykorzystać treść odpowiedzi, zanim będzie można ponownie użyć połączenia dla innego żądania. Powinieneś nie tylko czytać status odpowiedzi, ale w
InputStream
pełni czytać odpowiedź do ostatniego bajtu, przy czym po prostu ignorujesz odczytane bajty.źródło
google-api-java-client
, oznaczało to złapanieIOException
rzuconego przezHttpResponse.execute()
, przetestowanie / rzucenie goHttpResponseException
, uzyskanie dostępu doresponse
członka, a następnie wywołanieparaseAsString()
go. (Co i tak okazało się użyteczną informacją: -)HttpRequest.execute()
automatycznie wyczyści te zasoby, jeśli metoda nie zwróciHttpResponse
obiektu. Co więcej, JavaDoc odHttpResponse
teraz zaleca wywołanieresponse.disconnect()
w przypadku niepełnego odczytania treści odpowiedzi HTTP (wfinally
bloku).Miałem podobny problem podczas używania HttpClient z Jetty do tworzenia struktury testowej. Musiałem utworzyć wiele żądań do Servelet od mojego klienta, ale dawał ten sam wyjątek podczas wykonywania.
Znalazłem alternatywę pod adresem http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html
Możesz również użyć poniższej metody, aby utworzyć wystąpienie klienta.
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; }
źródło
Podobny komunikat o wyjątku (od przynajmniej Apache Jarkata Commons HTTP Client 4.2) to:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.
Ten wyjątek może wystąpić, gdy dwa lub więcej wątków współdziała z pojedynczym
org.apache.http.impl.client.DefaultHttpClient
.Jak utworzyć
DefaultHttpClient
ochronę wątków w instancji 4.2 ( Threadafe w tym sensie, że dwa lub więcej wątków mogą z nią współdziałać bez wyświetlania powyższego komunikatu o błędzie)? Zapewnij pulęDefaultHttpClient
połączeńClientConnectionManager
w postaciorg.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); } } }
źródło
To jest często zadawane pytanie. Odpowiedź BalusC jest poprawna. Proszę złapać HttpReponseException i wywołać HttpResponseException. odpowiedź . ignoruj (). Jeśli chcesz przeczytać komunikat o błędzie, użyj odpowiedzi. parseAsString (), jeśli nie znasz typu zawartości odpowiedzi, w przeciwnym razie, jeśli znasz typ zawartości, użyj odpowiedzi. parseAs (MyType.class).
Prosty fragment kodu z YouTubeSample.java w youtube-jsonc-sample (choć zazwyczaj będziesz chciał zrobić coś mądrzejszego w prawdziwej aplikacji):
} catch (HttpResponseException e) { System.err.println(e.response.parseAsString()); }
Pełne ujawnienie: jestem właścicielem projektu google-api-java-client .
źródło
Miałem ten sam problem z obiektem jax-rs (resteasy)
Response
w moich testach jednostkowych. Rozwiązałem to za pomocą wywołaniaresponse.releaseConnection();
metody releaseConnection () - Metoda jest tylko naClientResponse
obiekcie resteasy , więc musiałem dodać rzut odResponse
doClientResponse
.źródło
Spróbuj tego
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"); }
źródło
Ok, mam podobny problem, wszystkie te rozwiązania nie działają, testowałem na jakimś urządzeniu, problem był datowany w urządzeniu, to był rok 2011 zamiast 2013, sprawdź też to może pomóc.
źródło
Przeczytaj InputStream w ten sposób:
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() + "" ); } }
źródło
po prostu skonsumuj odpowiedź jak poniżej, aby rozwiązać problem
źródło