This blog post will integrate the Spring AI framework into a Java application. We’ll use a simple project that includes a ChatService and a ChatController to demonstrate using the Spring AI framework to generate text & image responses and horoscopes based on user input.
Update 12/28/2025 – Updated from M1 release to Spring AI 1.1.0 GA
Prerequisites
Before we start, make sure you have the following:
- Java Development Kit (JDK) installed
- Familiarity with Spring Framework
- Basic understanding of RESTful APIs
- An OpenAI API key
Obtaining an OpenAI API Key
To use the OpenAI API, you’ll need to sign up for an API key:
- Go to the OpenAI website.
- Sign up for an account if you don’t already have one.
- Navigate to the API section and generate a new API key.
Once you have your API key, set the OS environment variable OPEN_API_KEY to this value. We will refer to it in the spring application.properties file
Setting Up the Project
First, let’s set up our project. Create a new Spring Boot project and add the necessary dependencies for Spring AI.
Maven Dependencies
Add the following dependencies to your pom.xml:
1 2 3 4 5 6 7 8 9 10 11 | <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-openai</artifactId> </dependency> <!-- Add other necessary dependencies here --> </dependencies> |
Configuring the API Key
Point to the OpenAI API key in the application.properties file. Please make sure to set the environment variable OPENAI_API_KEY to the API key. Avoid hardcoding the API key directly in the properties file.
1 | spring.ai.openai.api-key=${OPENAI_API_KEY} |
Implementing the ChatService
The ChatService class contains methods to process AI prompts and generate horoscopes. Here’s the complete implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import java.util.Map; import org.springframework.ai.image.ImageModel; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.OpenAiImageOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ChatService { @Autowired private ChatClient chatClient; @Autowired private ImageModel imageModel; public String processPrompt(String prompt, String gptModelName, double temperature) { if (prompt == null || prompt.trim().isEmpty()) { throw new IllegalArgumentException("Prompt cannot be null or empty"); } return chatClient.prompt(new Prompt( prompt, OpenAiChatOptions.builder() .withModel(gptModelName) .withTemperature(temperature) .build() )) .call() .content(); } public String getMyHoroscope(String zodiacSign, int days, String gptModelName, double temperature) { String template = "I am a fortune teller. I can predict your future. Given your zodiac sign {zodiacSign} please tell me my future for the next {days} days?"; PromptTemplate promptTemplate = new PromptTemplate(template); Map<String, Object> params = Map.of( "zodiacSign", zodiacSign, "days", days ); return chatClient.prompt(new Prompt( promptTemplate.render(params), OpenAiChatOptions.builder() .withModel(gptModelName) .withTemperature(temperature) .build() )) .call() .content(); } public String generateImage(String message) { ImagePrompt imagePrompt = new ImagePrompt(message); return imageModel.generate(imagePrompt, OpenAiImageOptions.builder().build()); } } |
processPrompt: This method takes a prompt, model name, and temperature as parameters and returns the AI-generated text response.getMyHoroscope: This method generates a horoscope based on the user’s zodiac sign and the specified number of days for which you want to know your future. Note: I do not have to say this, but I will — this is a generic response and nothing to do with your real life or what you should expect in the future (just saying!)lgenerateImage: This method generates an image based on the provided message. It returns the URL where you can view the generated image.
Implementing the ChatController
The ChatController class exposes REST endpoints to interact with the ChatService. Here’s the complete implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | /** * Service class for handling AI chat and image generation operations. Provides * methods to interact with OpenAI's chat models and image generation * capabilities. */ @Service public class ChatService { @Autowired private ChatClient chatClient; @Autowired private ImageModel imageModel; /** * Processes a user prompt using the specified GPT model and temperature * setting. * * @param prompt the user's input prompt to be processed by the AI model * @param gptModelName the name of the GPT model to use (e.g., "gpt-5.2", * "gpt-4") * @param temperature controls randomness in the response (0.0 = * deterministic, 2.0 = very random) * @return the AI-generated response content * @throws IllegalArgumentException if the prompt is null or empty */ public String processPrompt(String prompt, String gptModelName, double temperature) { if (prompt == null || prompt.trim().isEmpty()) { throw new IllegalArgumentException("Prompt cannot be null or empty"); } return chatClient.prompt(new Prompt( prompt, OpenAiChatOptions.builder() .model(gptModelName) .temperature(temperature) .build() )) .call() .content(); } /** * Generates a personalized horoscope prediction based on zodiac sign and * number of days. Uses a fortune-telling prompt template to create * predictions. * * @param zodiacSign the zodiac sign for the horoscope (e.g., "Aries", * "Taurus") * @param days the number of days to predict into the future * @param gptModelName the name of the GPT model to use (e.g., "gpt-5.2", * "gpt-4") * @param temperature controls randomness in the response (0.0 = * deterministic, 2.0 = very random) * @return the AI-generated horoscope prediction */ public String getMyHorosope(String zodiacSign, int days, String gptModelName, double temperature) { String template = "I am a fortune teller. I can predict your future. Given your zodiac sign {zodiacSign} please tell me my future for the next {days} days?"; PromptTemplate promptTemplate = new PromptTemplate(template); Map<String, Object> params = Map.of( "zodiacSign", zodiacSign, "days", days ); return chatClient.prompt(new Prompt( promptTemplate.render(params), OpenAiChatOptions.builder() .model(gptModelName) .temperature(temperature) .build() )) .call() .content(); } /** * Generates an image using DALL-E 3 based on the provided text prompt. The * image is generated with standard quality at 1024x1024 resolution. * * @param imagePrompt the text description of the image to generate * @return the URL of the generated image */ public String generateImage(String imagePrompt) { return imageModel.call( new ImagePrompt(imagePrompt, OpenAiImageOptions.builder() .quality("standard") .model("dall-e-3") .N(1) .height(1024) .width(1024).build()) ).getResult().getOutput().getUrl(); } } |
Running the Application
To run the application, use the following command line from your Mac OS terminal.
1 2 3 | ./mvnw clean spring-boot:run curl -X POST -H "Content-Type: application/json" http://localhost:8080/api/chat -d '{"prompt": "who are you?"}' |
I have included a Postman collection in the Git project repository.
Conclusion
In this blog post, we demonstrated how to integrate the Spring AI framework into a Java application. We created a ChatService to handle AI prompts and horoscope generation, and exposed REST endpoints through a ChatController. This should give you a good starting point for building more advanced AI-powered Spring AI applications. The code is at https://github.com/thomasma/spring-ai