HTTP client abstraction for LangChain4j with synchronous/asynchronous execution and Server-Sent Events (SSE) streaming support
This guide covers configuring connect and read timeouts for HTTP client instances.
import dev.langchain4j.http.client.*;
import java.time.Duration;
HttpClientBuilder builder = HttpClientBuilderLoader.loadHttpClientBuilder();
HttpClient client = builder
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(30))
.build();The connect timeout determines the maximum time to wait when establishing a connection to the server.
Includes:
When exceeded:
RuntimeException is thrown from execute() methodsSocketTimeoutExceptionRecommended values:
The read timeout determines the maximum time to wait between receiving data packets from the server.
Important: For each chunk of data received, the timeout is reset. This is NOT the total time for the request.
When exceeded:
RuntimeException is thrown from execute() methodsServerSentEventListener.onError() is called with the timeout exceptionRecommended values:
HttpClient client = builder
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(10))
.build();HttpClient client = builder
.connectTimeout(Duration.ofSeconds(15))
.readTimeout(Duration.ofMinutes(5)) // Allow 5 minutes between events
.build();HttpClientBuilder builder = HttpClientBuilderLoader.loadHttpClientBuilder();
// Check current configuration
Duration currentConnectTimeout = builder.connectTimeout();
Duration currentReadTimeout = builder.readTimeout();
System.out.println("Connect timeout: " + currentConnectTimeout);
System.out.println("Read timeout: " + currentReadTimeout);
// Modify if needed
if (currentReadTimeout.compareTo(Duration.ofSeconds(30)) < 0) {
builder.readTimeout(Duration.ofSeconds(30));
}
HttpClient client = builder.build();// Read timeouts from environment or use defaults
String connectTimeoutEnv = System.getenv("HTTP_CONNECT_TIMEOUT_SECONDS");
int connectTimeoutSeconds = connectTimeoutEnv != null
? Integer.parseInt(connectTimeoutEnv)
: 10;
String readTimeoutEnv = System.getenv("HTTP_READ_TIMEOUT_SECONDS");
int readTimeoutSeconds = readTimeoutEnv != null
? Integer.parseInt(readTimeoutEnv)
: 30;
HttpClient client = builder
.connectTimeout(Duration.ofSeconds(connectTimeoutSeconds))
.readTimeout(Duration.ofSeconds(readTimeoutSeconds))
.build();public class HttpClientFactory {
public static HttpClient createDefault() {
return HttpClientBuilderLoader.loadHttpClientBuilder()
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(30))
.build();
}
public static HttpClient createForStreaming() {
return HttpClientBuilderLoader.loadHttpClientBuilder()
.connectTimeout(Duration.ofSeconds(15))
.readTimeout(Duration.ofMinutes(5))
.build();
}
public static HttpClient createForRest() {
return HttpClientBuilderLoader.loadHttpClientBuilder()
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(30))
.build();
}
}HttpClientBuilder builder = HttpClientBuilderLoader.loadHttpClientBuilder();
// Create client with short timeout
HttpClient fastClient = builder
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(10))
.build();
// Create another client with long timeout
HttpClient slowClient = builder
.connectTimeout(Duration.ofSeconds(30))
.readTimeout(Duration.ofMinutes(2))
.build();Note: The behavior of builder reuse depends on the specific implementation. Some implementations may share state between builds, while others create independent configurations.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpClientConfiguration {
@Value("${http.connect.timeout.seconds:10}")
private int connectTimeoutSeconds;
@Value("${http.read.timeout.seconds:30}")
private int readTimeoutSeconds;
@Bean
public HttpClient httpClient() {
return HttpClientBuilderLoader.loadHttpClientBuilder()
.connectTimeout(Duration.ofSeconds(connectTimeoutSeconds))
.readTimeout(Duration.ofSeconds(readTimeoutSeconds))
.build();
}
}http.connect.timeout.seconds=10
http.read.timeout.seconds=30HttpClient strictClient = builder
.connectTimeout(Duration.ofSeconds(3))
.readTimeout(Duration.ofSeconds(10))
.build();HttpClient lenientClient = builder
.connectTimeout(Duration.ofSeconds(30))
.readTimeout(Duration.ofSeconds(120))
.build();HttpClient streamingClient = builder
.connectTimeout(Duration.ofSeconds(15))
.readTimeout(Duration.ofMinutes(10))
.build();When multiple HTTP client implementations are available in the classpath:
# Specify which HTTP client implementation to use
java -Dlangchain4j.http.clientBuilderFactory=com.example.MyHttpClientFactory ...If not specified and multiple implementations exist, an IllegalStateException is thrown.
public class MyHttpClientFactory implements HttpClientBuilderFactory {
@Override
public HttpClientBuilder create() {
return new MyHttpClientBuilder();
}
}Register via META-INF/services/dev.langchain4j.http.client.HttpClientBuilderFactory:
com.example.MyHttpClientFactorySet appropriate timeouts: Always configure timeouts based on your use case. Default timeouts may not be suitable for all scenarios.
Longer timeouts for streaming: SSE and streaming APIs require longer read timeouts since there may be delays between events.
Shorter timeouts for internal APIs: Internal services typically have faster response times and should use shorter timeouts to fail fast.
Consider network conditions: Mobile and remote users may need longer timeouts than local network users.
Test timeout behavior: Verify that your timeout settings work correctly for both successful requests and timeout scenarios.
Document timeout choices: Make timeout configurations visible and document why specific values were chosen.
Install with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-http-client