Bringing LLMs to the JVM

For a long time, the AI revolution felt like it was happening exclusively in Python. If you wanted to integrate Large Language Models (LLMs), you usually had to build a side-car Python service or rely on raw HTTP clients to call APIs. However, with the release of Spring AI, the game has changed. In this how to use spring ai with openai tutorial, I’ll show you how to integrate GPT-4 directly into your Java applications using a portable, standardized API.

I’ve spent the last few weeks testing Spring AI in a production-like environment, and what impressed me most is how it abstracts the underlying AI provider. This means you can start with OpenAI and potentially switch to Azure AI or Mistral without rewriting your entire business logic. If you’re already leveraging java virtual threads in spring boot to handle high concurrency, adding AI capabilities via Spring AI is the logical next step for building scalable, intelligent agents.

Prerequisites

Before we dive into the code, ensure you have the following ready:

Step 1: Adding Spring AI Dependencies

First, we need to add the Spring AI Bill of Materials (BOM) to our pom.xml. This ensures all AI-related dependencies use compatible versions. I recommend using the Spring Milestone repository since Spring AI is evolving rapidly.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-M1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

Step 2: Configuring the OpenAI API Key

Never hardcode your API keys in your source code. I always use environment variables or a application.properties file that is excluded from Git. Add the following line to your configuration:

spring.ai.openai.api-key=${OPENAI_API_KEY}

To set this in your terminal, use: export OPENAI_API_KEY='your_key_here'. This ensures that your credentials remain secure even if your code is pushed to a public repository.

Step 3: Implementing the AI Service

Now, let’s create a simple service to handle the interaction with OpenAI. The core of Spring AI is the ChatClient. In my experience, creating a dedicated service wrapper makes it much easier to implement spring boot hexagonal architecture patterns, as you can isolate the AI provider from your core domain.

@Service
public class AiChatService {

    private final ChatClient chatClient;

    public AiChatService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public String getAiResponse(String userPrompt) {
        return chatClient.prompt()
                .user(userPrompt)
                .call()
                .content();
    }
}

As shown in the image below, the interaction flows from the user request through the ChatClient, which handles the JSON serialization and HTTP transport to OpenAI’s servers automatically.

Technical flow diagram showing the request path from Spring Boot ChatClient to OpenAI API
Technical flow diagram showing the request path from Spring Boot ChatClient to OpenAI API

Step 4: Creating the REST Controller

To make this accessible via an API, we’ll create a simple controller. This allows you to test your implementation using Postman or Curl.

@RestController
@RequestMapping("/ai")
public class AiController {

    private final AiChatService aiChatService;

    public AiController(AiChatService aiChatService) {
        this.aiChatService = aiChatService;
    }

    @GetMapping("/generate")
    public String generate(@RequestParam(value = "message") String message) {
        return aiChatService.getAiResponse(message);
    }
}

Pro Tips for Production AI

Troubleshooting Common Issues

If you encounter a 401 Unauthorized error, double-check that your environment variable is actually loaded. I’ve often seen developers set the variable in one terminal window and run the app in another. Use System.getenv("OPENAI_API_KEY") in a temporary print statement to verify.

If you experience slow response times, check if you are using gpt-4o or gpt-3.5-turbo. You can configure the model in your properties file: spring.ai.openai.chat.options.model=gpt-4o.

What’s Next?

Once you’ve mastered this how to use spring ai with openai tutorial, the next step is implementing RAG (Retrieval-Augmented Generation). This allows you to feed your own PDFs or database records into the prompt so the AI can answer questions about your specific business data. You can also explore vector databases like PGVector or Pinecone, which integrate seamlessly with Spring AI.

Want to optimize your AI backend? I recommend checking out my guide on using virtual threads to ensure your application doesn’t block while waiting for the LLM to respond.