Quarkus extension deployment module for integrating Ollama LLM models with Quarkus applications through the LangChain4j framework
The Quarkus LangChain4j Ollama Deployment module is a complex Quarkus extension that operates during the application build phase. This document describes the overall architecture, key components, and how they interact within the Quarkus build chain.
As a Quarkus deployment module, this extension participates in the Quarkus build process through annotated build step methods. The architecture follows the standard Quarkus extension pattern with clear separation between build-time (deployment) and runtime concerns.
┌─────────────────────────────────────────────────────────────────┐
│ Quarkus Build Process │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Ollama Deployment Module (Build Time) │
│ │
│ ┌──────────────────┐ ┌─────────────────────────────────┐ │
│ │ OllamaProcessor │ │ OllamaDevServicesProcessor │ │
│ │ │ │ │ │
│ │ • Feature │ │ • Container Management │ │
│ │ • Indexing │ │ • Lifecycle Control │ │
│ │ • Native Support │ │ • Configuration Injection │ │
│ │ • Providers │ │ │ │
│ │ • Bean Creation │ └─────────────────────────────────┘ │
│ └──────────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────────────────┐ │
│ │ │ OllamaContainer │ │
│ │ │ (Testcontainers wrapper) │ │
│ │ └──────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ OllamaRecorder (Runtime Recorder) │ │
│ │ • chatModel(configName) │ │
│ │ • streamingChatModel(configName) │ │
│ │ • embeddingModel(configName) │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Runtime Module (Application) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ ChatModel Bean │ │ EmbeddingModel │ │
│ │ (Synthetic CDI) │ │ Bean │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │ │
│ └──────────┬───────────┘ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Application Code │ │
│ │ (@Inject models) │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘The extension contains three main processor classes that participate in the build chain:
Package: io.quarkiverse.langchain4j.ollama.deployment
Responsibility: Core build-time processing for Ollama integration
Build Steps:
Key Interactions:
Package: io.quarkiverse.langchain4j.ollama.deployment.devservices
Responsibility: DevServices container lifecycle management
Build Steps:
Key Interactions:
Conditions:
Package: io.quarkiverse.langchain4j.ollama.deployment.devui
Responsibility: Dev UI integration
Build Steps:
Key Interactions:
Build-Time Configuration:
LangChain4jOllamaOpenAiBuildConfig - Root configurationChatModelBuildConfig - Chat model enablementEmbeddingModelBuildConfig - Embedding model enablementOllamaDevServicesBuildConfig - DevServices settingsConfiguration Phase: BUILD_TIME - Read during application build
Configuration Processing Flow:
application.propertiesPurpose: Automatic Ollama container provisioning for development
Components:
OllamaDevServicesProcessor: Lifecycle coordinator
OllamaContainer: Testcontainers wrapper
org.testcontainers.ollama.OllamaContainerLifecycle Flow:
Start → Check Conditions → Check Existing Instance →
Compare Config → Start Container → Inject Config →
Register Cleanup → Running → ShutdownActivation Conditions:
State Management:
Build Item Flow:
Configuration → Provider Candidates → Provider Selection →
DevServices Requirements → DevServices Startup →
Bean Generation → Runtime InitializationKey Build Items:
Provider Registration:
ChatModelProviderCandidateBuildItemEmbeddingModelProviderCandidateBuildItemImplicitlyUserConfiguredChatProviderBuildItemProvider Selection (External):
SelectedChatModelProviderBuildItemSelectedEmbeddingModelCandidateBuildItemDevServices:
DevServicesChatModelRequiredBuildItemDevServicesEmbeddingModelRequiredBuildItemDevServicesOllamaConfigBuildItemDevServicesResultBuildItemBean Generation:
SyntheticBeanBuildItemBuild Step Dependencies:
Pattern: Recorder Pattern
Build-Time:
OllamaProcessor.generateBeans() build step executesSyntheticBeanBuildItemRuntime Initialization:
Bean Types Created:
ChatModel - Standard chat interfaceStreamingChatModel - Streaming chat interfaceEmbeddingModel - Text embedding interfaceBean Characteristics:
@ApplicationScoped@ModelName(configName) for named configurationsInstance<ChatModelListener>Reflection Configuration:
Why Needed:
Configured Classes:
OllamaChatRequest - Full hierarchy with nested typesOllamaChatResponse - Full hierarchy with nested typesFormatSerializer - Constructor reflection onlyOllamaDateDeserializer - Constructor reflection onlyConfigSourceInterceptor implementations - Service providersSeparation of Concerns:
Deployment Module (this module):
Runtime Module (quarkus-langchain4j-ollama):
Communication:
Typical execution sequence:
Early Steps (Parallel):
OllamaProcessor.feature()OllamaProcessor.indexUpstreamOllamaModule()OllamaDevServicesProcessor.feature()Configuration Steps:
OllamaProcessor.nativeSupport()OllamaProcessor.providerCandidates()OllamaProcessor.implicitlyConfiguredProviders()Provider Selection (External to this module)
DevServices Steps (Conditional):
OllamaProcessor.devServicesSupport()OllamaDevServicesProcessor.startOllamaDevService()Bean Generation:
OllamaProcessor.generateBeans()Finalization:
OllamaProcessor.deprioritizeJsonb()OllamaDevUiProcessor.registerOpenWebUiCard()application.properties → SmallRye Config →
Build Config Interfaces → Processor Build Steps →
Build Items → Provider Selectionapplication.properties → SmallRye Config →
Runtime Config Interfaces → OllamaRecorder →
Model Client InstantiationContainer Started → Extract Config →
Inject base-url Properties → Runtime Config →
Model Clients Use Injected URLsThe deployment module provides several extension points:
Applications can override default beans:
@ApplicationScoped
@Priority(APPLICATION + 10)
public class CustomChatModel implements ChatModel {
// Custom implementation
}Applications can provide listeners for chat events:
@ApplicationScoped
public class MyChatListener implements ChatModelListener {
// Listen to chat events
}Named configurations allow multiple Ollama instances:
quarkus.langchain4j.ollama.instance1.base-url=http://ollama1:11434
quarkus.langchain4j.ollama.instance2.base-url=http://ollama2:11434Build steps are single-threaded within the Quarkus build process. No synchronization needed.
Static volatile fields in OllamaDevServicesProcessor:
devService - Currently running containercfg - Current configurationfirst - First run flagMarked volatile for visibility across hot-reload scenarios in development mode.
Model beans are @ApplicationScoped singletons:
Enable Quarkus build logging:
mvn clean install -XCheck DevServices logs:
docker logs <container-id>View DevServices state in Dev UI:
Enable HTTP client logging:
quarkus.log.category."dev.langchain4j.model.ollama".level=DEBUGmvn clean package -Pnative
./target/app-runnerSyntheticBeanBuildItem.configure()OllamaRecorder bean creationChatModelListener injection@ApplicationScoped beansonlyIf, onlyIfNotquarkus-arc-deployment - CDI supportquarkus-rest-client-jackson-deployment - REST clientquarkus-qute-deployment - Templatingquarkus-langchain4j-core-deployment - Core LangChain4jquarkus-langchain4j-ollama - Runtime moduletestcontainers-ollama - DevServices containerquarkus-devservices-deployment - DevServices supportquarkus-devui-spi - Dev UI integrationInstall with Tessl CLI
npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-ollama-deployment