Keine Verbindung, wenn dabei mehrere Anrufe mit jersey ApacheHttpClient
Ich habe Probleme mit nicht immer-verbindungen beim Aufruf einer rest-api, die mit com.Sonne.jersey.client.apache.ApacheHttpClient und Frühjahr. Ein paar Anrufe erhalten, ist durch, aber plötzlich bekomme ich einen:
DEBUG (org.apache.commons.httpclient.MultiThreadedHttpConnectionManager:501) : - Unable to get a connection, waiting..., hostConfig=HostConfiguration[host=www.dummyapi.com]`
thats it. Nichts mehr!
Das ist mein applicationContext.xml:
<bean id="customHttpClient" class="com.sun.jersey.client.apache.ApacheHttpClient">
<constructor-arg>
<bean class="com.sun.jersey.client.apache.ApacheHttpClientHandler" >
<constructor-arg>
<bean class="org.apache.commons.httpclient.HttpClient" >
<constructor-arg>
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager" >
<property name="params">
<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
<property name="defaultMaxConnectionsPerHost" value="10" />
</bean>
</property>
</bean>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</constructor-arg>
<constructor-arg ref="customClientConfiguration" />
</bean>
<bean id="customRestClient" class="com.custom.web.service.common.RestClient" >
<constructor-arg ref="customHttpClient" />
<constructor-arg value="${my.service.url}" />
</bean>
Das sind meine Klassen:
import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
public class CustomApacheHttpClientConfig extends DefaultApacheHttpClientConfig {
/**
* Constructor with username and password.
* @param username
* @param password
*/
public CustomApacheHttpClientConfig(final String username, final String password) {
getClasses().add(JacksonJsonProvider.class);
getProperties().put(PROPERTY_PREEMPTIVE_AUTHENTICATION, Boolean.TRUE);
getState().setCredentials(null, null, -1, username, password);
}
}
package com.custom.web.service.common;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
public class RestClient {
private static final Logger LOG = Logger.getLogger(RestClient.class);
private final String baseUrl;
private final Client client;
private final ObjectMapper objectMapper;
public RestClient(final String baseUrl, final Client client) {
this.baseUrl = baseUrl;
this.client = client;
this.objectMapper = new ObjectMapper();
this.objectMapper.getDeserializationConfig().set(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public RestClient(final String baseUrl, final Client client, final ObjectMapper objectMapper) {
this.baseUrl = baseUrl;
this.client = client;
this.objectMapper = objectMapper;
}
public String getBaseUrl() {
return baseUrl;
}
public Client getClient() {
return client;
}
public ObjectMapper getObjectMapper() {
return objectMapper;
}
}
Der Aufruf:
public void do() {
UriBuilder uriBuilder = UriBuilder.fromUri(
String.format(
this.customRestClient.getBaseUrl(),
"SE")).
path(SOME_UNIT_PATH_PARAM).
path(id).
path(SOME_OTHER_PATH_PARAM);
ClientResponse response = this.customRestClient.getClient().resource(uriBuilder.build()).get(ClientResponse.class);
if (response.getClientResponseStatus().getStatusCode() != 200) {
throw new CustomRestClientException(String.format("Something went wrong when getting stuff from rest api for id: %s %d %s ",
id, response.getClientResponseStatus().getStatusCode(),
" reasonPhrase: " + response.getClientResponseStatus().getReasonPhrase()));
}
String json = response.getEntity(String.class);
Stuff[] stuff = null;
try {
stuff = this.customRestClient.getObjectMapper().readValue(json, Stuff[].class);
} catch (IOException e) {
throw new CustomRestClientException(
String.format("Something went wrong when reading json value for stuff from api: %s %s %d %s ",
id, json, response.getClientResponseStatus().getStatusCode(), " reasonPhrase: " + e.getMessage()));
}
List<Stuff> stuffList = new ArrayList<Stuff>();
stuffList.addAll(Arrays.asList(stuff));
}
Wie man sehen kann habe ich nicht explizit schließen Sie die Verbindung nach jeder Anfrage, das überlasse ich den ApacheHttpClientHandler. Ich habe versucht, zu erhöhen defaultMaxConnectionsPerHost, aber kein Glück gibt. Ich habe auch gestöbert, um das web und nur Beispiele gefunden, wo Leute instanziieren, Ihre client-code und dann zerstört Sie es auch. Bitte helfen Sie mir, dies herauszufinden, weil ich gegen eine Wand geprallt, die auf dieser.
Bezug
Jakob!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gefunden, der Grund für meine Probleme:
Es scheint, dass ich vergaß, um die soTimeout und connectionTimeout. Die Dokumentation klar:
soTimout:
Definiert die Standard-socket-timeout (SO_TIMEOUT) in Millisekunden, die der timeout für das warten auf die Daten. Ein timeout-Wert von null interpretiert wird, als ein unendliches timeout.
und
connectionTimout:
Bestimmt den timeout, bis eine Verbindung gerufenen. Ein Wert von null bedeutet, dass der timeout nicht benutzt. Der Standardwert ist null.
Also alles, was ich zu tun hatte, ist zu definieren:
Voila! Alles funktioniert wie ein Charme!
Danke skaffman Sie wies mich in die richtige Richtung!
Müssen Sie noch schließen Sie Ihre verbindungen der Verbindungs-manager nicht für Sie tun. Der manager ist verantwortlich für die Bündelung der Anschlüsse, es hat keine übersicht, Wann bist du fertig mit Ihnen.
Wenn Sie nicht schließen Sie dann den Verbindungs-manager denkt immer noch, Sie sind mit Ihnen, und werde es so schnell erschöpft.