Skip to content

Architecture Overview ​

CoApi's architecture is designed to provide a seamless, type-safe HTTP client framework that integrates deeply with Spring ecosystem while maintaining flexibility for various deployment scenarios. The architecture addresses the common challenges of REST API client development by providing automatic discovery, configuration management, and support for both reactive and synchronous programming models.

Overview ​

CoApi exists to solve the fundamental problem of creating type-safe HTTP clients in Spring applications without the boilerplate code typically associated with manual HTTP client configuration. By leveraging Spring's auto-configuration capabilities and annotation-driven programming model, CoApi reduces the complexity of integrating with external services while providing enterprise-grade features like load balancing, circuit breaking, and configuration management.

The architecture follows a modular design that separates concerns across three main layers: the API layer (for interface definitions), the Spring integration layer (for dependency injection and lifecycle management), and the Spring Boot integration layer (for auto-configuration and sensible defaults).

At-a-Glance ​

ComponentResponsibilityKey FeaturesSource
@CoApiInterface definition and configurationType-safe HTTP clients, service discovery, load balancingCoApi.kt
AbstractCoApiRegistrarBase registration logicClient mode inference, factory registrationAbstractCoApiRegistrar.kt
CoApiRegistrarIndividual client registrationBean definition creation, factory bean registrationCoApiRegistrar.kt
CoApiFactoryBeanProxy creationJDK proxy generation, service proxy factoryCoApiFactoryBean.kt
HttpClientFactoryBeanHTTP client configurationWebClient/RestClient creation, filter applicationWebClientFactoryBean.kt

Module Architecture ​

mermaid
graph TB
    subgraph "CoApi Module Architecture"
        subgraph "API Layer"
            A["@CoApi Annotation"]
            B[CoApiDefinition]
            C[HttpExchangeAdapter]
        end
        
        subgraph "Spring Integration Layer"
            D[AbstractCoApiRegistrar]
            E[CoApiRegistrar]
            F[CoApiFactoryBean]
            G[WebClientFactoryBean]
            H[RestClientFactoryBean]
            I[HttpExchangeAdapterFactory]
        end
        
        subgraph "Spring Boot Integration Layer"
            J[AutoCoApiRegistrar]
            K[EnableCoApiRegistrar]
            L[CoApiProperties]
            M[ApiClientScanner]
        end
        
        subgraph "Client Adapters"
            N[ReactiveHttpExchangeAdapterFactory]
            O[SyncHttpExchangeAdapterFactory]
        end
        
        subgraph "HTTP Clients"
            P[WebClient]
            Q[RestClient]
        end
    end
    
    A --> B
    B --> C
    D --> E
    E --> F
    F --> G
    F --> H
    G --> I
    H --> I
    J --> D
    K --> D
    L --> J
    L --> K
    M --> J
    M --> K
    I --> N
    I --> O
    N --> P
    O --> Q

Registration Flow ​

The registration process is the heart of CoApi's architecture, automatically discovering and configuring HTTP clients based on annotations and configuration. This sequence diagram illustrates the complete registration flow:

mermaid
sequenceDiagram
    participant U as User Code
    participant A as CoApi Annotation
    participant B as AutoCoApiRegistrar
    participant C as AbstractCoApiRegistrar
    participant D as CoApiRegistrar
    participant E as CoApiFactoryBean
    participant F as WebClientFactoryBean
    participant G as RestClientFactoryBean
    participant H as HttpServiceProxyFactory
    participant I as JDK Proxy
    
    autonumber
    
    U->>A: @CoApi(baseUrl, serviceId, name)
    A->>B: Interface discovery
    B->>C: registerBeanDefinitions()
    C->>C: inferClientMode()
    C->>C: registerHttpExchangeAdapterFactory()
    C->>D: CoApiRegistrar(registry, clientMode)
    D->>D: register(coApiDefinitions)
    D->>F: registerWebClient() or registerRestClient()
    D->>E: registerApiClient()
    F->>G: getObject()
    E->>H: createClient()
    H->>I: create JDK Proxy
    I->>U: Return typed interface

Bean Lifecycle ​

The Spring bean lifecycle is carefully managed to ensure proper initialization and dependency injection:

mermaid
sequenceDiagram
    participant C as Spring Context
    participant R as Bean Definition Registry
    participant F as FactoryBean
    participant A as Application Context
    participant L as Load Balancer
    
    autonumber
    
    C->>R: registerBeanDefinitions()
    R->>F: Create FactoryBean
    F->>A: setApplicationContext()
    F->>A: getObject()
    F->>A: resolve HttpExchangeAdapterFactory
    note right of A: unique or @Primary candidate wins;<br/>otherwise the standard-name bean<br/>(mode-specific default registered at startup)
    A->>F: Return factory
    F->>F: create(HttpExchangeAdapter)
    F->>F: build(HttpServiceProxyFactory)
    F->>F: createClient(apiType)
    F->>C: Return proxy
    alt Load Balanced
        F->>L: Load balance requests
    end
    C->>F: Client ready for use

Class Diagram ​

The class hierarchy shows the relationships between key components:

mermaid
classDiagram
    class CoApi {
        +String baseUrl
        +String serviceId
        +String name
    }
    
    class CoApiDefinition {
        +String name
        +Class apiType
        +String baseUrl
        +boolean loadBalanced
        +String coApiBeanName
        +String httpClientBeanName
        +withOverrides(String, Boolean?) CoApiDefinition
    }
    
    class AbstractCoApiRegistrar {
        #Environment env
        #BeanFactory appContext
        +getCoApiDefinitions(AnnotationMetadata)
        +registerBeanDefinitions(AnnotationMetadata, registry)
    }
    
    class CoApiRegistrar {
        -BeanDefinitionRegistry registry
        -ClientMode clientMode
        +register(Set~CoApiDefinition~)
        +register(CoApiDefinition)
    }
    
    class CoApiFactoryBean {
        -CoApiDefinition coApiDefinition
        +getObject()
        +getObjectType()
    }
    
    class WebClientFactoryBean {
        +getObject()
        +effectiveDefinition() CoApiDefinition
    }
    
    class RestClientFactoryBean {
        +getObject()
        +effectiveDefinition() CoApiDefinition
    }
    
    class HttpServiceProxyFactory {
        +createClient(Class)
    }
    
    class ReactiveHttpExchangeAdapterFactory {
        +create(BeanFactory, String)
    }
    
    class SyncHttpExchangeAdapterFactory {
        +create(BeanFactory, String)
    }
    
    CoApi --> CoApiDefinition : creates
    AbstractCoApiRegistrar --> CoApiDefinition : uses
    AbstractCoApiRegistrar --> CoApiRegistrar : creates
    CoApiRegistrar --> WebClientFactoryBean : registers
    CoApiRegistrar --> RestClientFactoryBean : registers
    CoApiRegistrar --> CoApiFactoryBean : registers
    CoApiFactoryBean --> HttpServiceProxyFactory : uses
    CoApiFactoryBean --> ReactiveHttpExchangeAdapterFactory : gets
    CoApiFactoryBean --> SyncHttpExchangeAdapterFactory : gets
    WebClientFactoryBean --> ReactiveHttpExchangeAdapterFactory : uses
    RestClientFactoryBean --> SyncHttpExchangeAdapterFactory : uses

Layered Architecture ​

The architecture follows a clean layered approach with clear separation of concerns:

mermaid
graph TD
    subgraph "Application Layer"
        A[User Interface]
        B[Business Logic]
        C[CoApi Clients]
    end
    
    subgraph "Service Layer"
        D[Service Interfaces]
        E[Service Implementations]
        F[Domain Services]
    end
    
    subgraph "Infrastructure Layer"
        G[CoApi Framework]
        H[HTTP Clients]
        I[Load Balancers]
        J[Configuration]
    end
    
    subgraph "Framework Layer"
        K[Spring Framework]
        L[Spring Boot]
        M[Spring Cloud]
    end
    
    A --> B
    B --> C
    C --> D
    D --> E
    E --> F
    F --> G
    G --> H
    H --> I
    I --> J
    J --> K
    K --> L
    L --> M

Key Design Patterns ​

CoApi's architecture implements several design patterns to ensure maintainability and extensibility:

1. Factory Pattern ​

Factory beans are used to create complex objects like HTTP clients and proxies with proper configuration.

2. Strategy Pattern ​

Different client modes (reactive vs sync) are handled using the Strategy pattern with different factory implementations.

3. Template Method Pattern ​

Abstract factory classes provide common functionality while allowing specific implementations.

4. Proxy Pattern ​

JDK proxies are used to create type-safe interfaces that delegate to HTTP clients.

5. Builder Pattern ​

HttpServiceProxyFactory and client builders use the Builder pattern for fluent configuration.

Cross-References ​

References ​

Source Files ​

  • [Module Architecture](
  • [Registration Process](
  • [Bean Lifecycle](
  • [Design Patterns](
  • Performance Considerations - Performance optimization guidelines