Skip to content

Jafly. Common Client Library

Common Client Library

Call REST, SOAP, and gRPC services through reactive client builders with shared resilience and observability facilities.

Choose the protocol-specific builder, set the remote service endpoint and authentication, and retain the client for reuse. Treat retries and circuit breakers as operation policy: verify whether the remote operation is safe to retry.

Maven artifact Packaging Source project
org.fireflyframework:fireflyframework-client jar modules/client

Part of External services.

In the onboarding service

The service may call a document-verification partner during a later onboarding step. Set the endpoint and authentication on the selected protocol client, and choose retries according to whether that partner operation can safely repeat.

Add the component

Installation and version availability explains source builds and published releases.

<dependency>
    <groupId>org.fireflyframework</groupId>
    <artifactId>fireflyframework-client</artifactId>
    <version>26.10.20-SNAPSHOT</version>
</dependency>

Quick start

The injection examples use Lombok @RequiredArgsConstructor. Add its provided dependency and annotation processor as described in Constructor injection.

The Java examples in this section are API fragments for application code. Use the stated imports and supply the application-owned collaborators described alongside them.

Auto-configuration provides a default RestClientBuilder, CircuitBreakerManager, and tuned WebClient.Builder as soon as the dependency is on the classpath. You can use the ServiceClient static factories directly, or define your own client beans.

REST

import lombok.RequiredArgsConstructor;
import org.fireflyframework.client.RestClient;
import org.fireflyframework.client.ServiceClient;
import reactor.core.publisher.Mono;

import java.time.Duration;

@Configuration
public class ClientConfig {

    @Bean
    public RestClient paymentClient(CircuitBreakerManager circuitBreakerManager) {
        return ServiceClient.rest("payment-service")
            .baseUrl("https://api.payments.com")
            .timeout(Duration.ofSeconds(5))
            .defaultHeader("Accept", "application/json")
            .circuitBreakerManager(circuitBreakerManager)
            .build();
    }
}

@Service
@RequiredArgsConstructor
public class PaymentService {

    private final RestClient paymentClient;



    // Fluent RequestBuilder: set body/params/headers, then execute()
    public Mono<PaymentResponse> charge(PaymentRequest request) {
        return paymentClient.post("/charges", PaymentResponse.class)
            .withBody(request)
            .execute();
    }

    public Mono<Payment> get(String id) {
        return paymentClient.get("/charges/{id}", Payment.class)
            .withPathParam("id", id)
            .execute();
    }
}

SOAP

SoapClient weather = ServiceClient.soap("weather-service")
    .wsdlUrl("https://example.com/weather?wsdl")
    .credentials("user", "secret")     // WS-Security UsernameToken
    .timeout(Duration.ofSeconds(30))
    .build();

Mono<WeatherResponse> forecast = weather.invokeAsync(
    "GetWeatherByCity", new GetWeatherRequest("Madrid"), WeatherResponse.class);

gRPC

GrpcClient<UserServiceGrpc.UserServiceStub> users =
    ServiceClient.grpc("user-service", UserServiceGrpc.UserServiceStub.class)
        .address("localhost:9090")
        .usePlaintext()
        .stubFactory(UserServiceGrpc::newStub)
        .build();

Configuration and wiring

The firefly.service-client namespace is bound by ServiceClientProperties.java. Nested configuration is declared in the linked class. Defaults are the field initializers.

Setting Java type Source default
firefly.service-client.enabled boolean true
firefly.service-client.default-timeout Duration Duration.ofSeconds(30)
firefly.service-client.environment Environment Environment.DEVELOPMENT
firefly.service-client.default-headers Map<String, String> new HashMap<>()
firefly.service-client.rest Rest new Rest()
firefly.service-client.grpc Grpc new Grpc()
firefly.service-client.soap Soap new Soap()
firefly.service-client.sdk Sdk new Sdk()
firefly.service-client.circuit-breaker CircuitBreaker new CircuitBreaker()
firefly.service-client.retry Retry new Retry()
firefly.service-client.metrics Metrics new Metrics()
firefly.service-client.security Security new Security()

Property-based wiring conditions found in this module:

Public API and extension points

Type Contract and responsibility
RestClient REST-specific service client interface with HTTP semantics.
RestClientBuilder Simplified builder for REST service clients.
SoapClient SOAP-specific service client interface with WSDL-based operation invocation.
GrpcClient gRPC-specific service client interface with native gRPC semantics.
ServiceClient Core interface for all service clients providing common lifecycle and health operations.
Related component Why it belongs nearby
Kernel Share a consistent exception vocabulary across application, domain, and infrastructure boundaries.
Observability Provide a common metrics, tracing, health, and context-propagation foundation for framework components.

Build and test

Use Java 25. From the repository root, build this component with its required dependencies:

git clone https://github.com/fireflyframework/fireflyframework-jafly.git
cd fireflyframework-jafly
./mvnw -pl :fireflyframework-client -am verify
./mvnw -pl :fireflyframework-client -am install

verify runs the selected projects' tests. install makes the current build available in your local Maven repository.

Representative test sources:

Test fixture

The shouldRespectMaxCacheSize test demonstrates one concrete behavior. Excerpt from HttpCacheManagerTest.java. The test class supplies its fixtures and imports.

@Test
void shouldRespectMaxCacheSize() {
    // Given
    HttpCacheConfig smallConfig = HttpCacheConfig.builder()
        .enabled(true)
        .maxCacheSize(2)
        .build();

    HttpCacheManager smallCache = new HttpCacheManager(smallConfig);

    // When
    smallCache.put("key1", "value1", null, null);
    smallCache.put("key2", "value2", null, null);
    smallCache.put("key3", "value3", null, null);

    // Then
    assertThat(smallCache.getStatistics().size()).isLessThanOrEqualTo(2);
}

Detailed reference

Configuration

All settings live under the firefly.service-client.* prefix and are bound (and validated) by ServiceClientProperties. Properties are global defaults organized by protocol/concern; per-client overrides are expressed through the builders shown above. Environment-aware defaults are applied automatically based on firefly.service-client.environment (development, testing, production).

firefly:
  service-client:
    enabled: true                 # master switch for the framework
    default-timeout: 30s          # global default for all client operations
    environment: development      # development | testing | production (drives smart defaults)
    default-headers: {}           # headers applied to all REST clients

    rest:
      max-connections: 100        # connection pool size
      max-idle-time: 5m
      max-life-time: 30m
      pending-acquire-timeout: 10s
      response-timeout: 30s
      max-in-memory-size: 1048576 # 1 MB response buffer
      connect-timeout: 10s
      read-timeout: 30s
      follow-redirects: true
      compression-enabled: true
      default-content-type: application/json
      default-accept-type: application/json
      logging-enabled: false
      max-retries: 3

    grpc:
      keep-alive-time: 5m
      keep-alive-timeout: 30s
      keep-alive-without-calls: true
      max-inbound-message-size: 4194304   # 4 MB
      max-inbound-metadata-size: 8192     # 8 KB
      call-timeout: 30s
      retry-enabled: true
      use-plaintext-by-default: true
      compression-enabled: true
      max-concurrent-streams: 100

    soap:
      default-timeout: 30s
      connection-timeout: 10s
      receive-timeout: 30s
      mtom-enabled: false
      schema-validation-enabled: true
      message-logging-enabled: false
      max-message-size: 10485760          # 10 MB
      ws-addressing-enabled: false
      ws-security-enabled: false
      soap-version: "1.1"                 # 1.1 or 1.2
      wsdl-cache-enabled: true
      wsdl-cache-expiration: 1h
      follow-redirects: true

    sdk:
      default-timeout: 45s
      auto-shutdown-enabled: true
      max-concurrent-operations: 50
      logging-enabled: false

    circuit-breaker:
      enabled: true
      failure-rate-threshold: 50.0        # percent
      wait-duration-in-open-state: 60s
      sliding-window-size: 10
      minimum-number-of-calls: 5
      slow-call-rate-threshold: 100.0     # percent
      slow-call-duration-threshold: 60s
      permitted-number-of-calls-in-half-open-state: 3
      call-timeout: 30s
      automatic-transition-from-open-to-half-open-enabled: true

    retry:
      enabled: true
      max-attempts: 3
      wait-duration: 500ms
      exponential-backoff-multiplier: 2.0
      max-wait-duration: 10s
      jitter-enabled: true

    metrics:
      enabled: true
      detailed-metrics: false
      export-interval: 1m
      histogram-enabled: true
      tags: {}

    security:
      enabled: true
      default-auth-type: NONE             # NONE | BASIC | BEARER | OAUTH2 | CUSTOM
      ssl-validation-enabled: true
      request-signing-enabled: false

Key properties

Property Default Purpose
firefly.service-client.enabled true Master switch; when false, no client beans are auto-configured.
firefly.service-client.environment development Selects environment-aware defaults (e.g. relaxed SSL and verbose logging in development, hardened defaults in production).
firefly.service-client.default-timeout 30s Fallback timeout for all client operations.
firefly.service-client.rest.max-connections 100 Reactor Netty connection-pool size for REST.
firefly.service-client.circuit-breaker.failure-rate-threshold 50.0 Percentage of failures within the sliding window that opens the breaker.
firefly.service-client.retry.max-attempts 3 Maximum retry attempts (with exponential backoff + optional jitter).
firefly.service-client.grpc.use-plaintext-by-default true Whether new gRPC channels default to plaintext (forced to TLS in production).
firefly.service-client.metrics.enabled true Enables ServiceClientMetrics Micrometer integration (auto-disabled in testing).

Note: environment-aware defaults only override values you have not set explicitly, so any property you configure always wins.

Continue the application

Use the Orchestration guide for the next part of this integration. The runnable submission/query service is in Getting started.

Source and further reading