Artificial Intelligence 7 min read

Simplify Java AI Integration with Spring AI Custom Annotations and AI Services

AI Services, inspired by Spring Data JPA and Retrofit, offers a declarative Java API that abstracts LLM interactions, supporting input formatting, output parsing, chat memory, function calling, and RAG, with detailed examples using LangChain4j, custom Spring AI annotations, AOP aspects, and controller integration.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
Simplify Java AI Integration with Spring AI Custom Annotations and AI Services

What is AI Services

AI Services is inspired by Spring Data JPA and Retrofit, using declarative interfaces to define APIs, with the framework generating proxy implementations that hide LLM interaction complexity and provide a simple API.

AI Services mainly handles common operations:

Formatting input for LLM

Parsing LLM output

It also supports advanced features:

Chat memory management

Function calling

Retrieval‑augmented generation (RAG)

Basic usage example

LangChain4j is a popular Java framework offering low‑level and high‑level APIs; AI Services is a high‑level API solution. The simplest example:

<code>// Define interface
interface Assistant {
    String chat(String userMessage);
}

// Create low‑level component
ChatLanguageModel model = OpenAiChatModel.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .modelName("gpt-4o-mini")
    .build();

// Create AI Service instance
Assistant assistant = AiServices.create(Assistant.class, model);

// Use AI Service
String answer = assistant.chat("Hello");
System.out.println(answer); // Hello, how can I help you?</code>

Using system and user messages

LangChain4j provides @SystemMessage and @UserMessage annotations to customize prompts:

<code>// System message example
interface Friend {
    @SystemMessage("You are a good friend of mine. Answer using slang.")
    String chat(String userMessage);
}

// User message template example
interface Advisor {
    @UserMessage("You are a professional advisor. Please answer this question: {{it}}")
    String getAdvice(String question);
}</code>

Custom annotation implementation based on Spring AI

For projects already using Spring AI, a lightweight custom annotation can simplify integration.

Required dependencies

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

Configure ChatClient

<code>@Bean
public ChatClient chatClient(ChatModel chatModel) {
    return ChatClient.builder(chatModel)
        .defaultSystem("You are a helpful AI assistant that can answer user questions.")
        .build();
}
</code>

Create custom annotation

<code>@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AiPrompt {
    String systemMessage() default "";
}
</code>

Implement AOP aspect

<code>@Aspect
@Component
@RequiredArgsConstructor
public class AiPromptAspect {
    private final ChatClient deepSeekChatClient;

    @Around("@annotation(aiPrompt)")
    public Object processAiPrompt(ProceedingJoinPoint joinPoint, AiPrompt aiPrompt) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if (args.length == 0) {
            return joinPoint.proceed();
        }
        String userMessage = args[0].toString();
        ChatClient.ChatClientRequestSpec requestSpec = deepSeekChatClient.prompt();
        if (!aiPrompt.systemMessage().isEmpty()) {
            requestSpec = requestSpec.system(aiPrompt.systemMessage());
        }
        return requestSpec.user(userMessage).call().content();
    }
}
</code>

Usage example

<code>@Service
@RequiredArgsConstructor
public class ChatService {
    @AiPrompt(systemMessage = "You are a professional Java development advisor, good at Spring framework questions.")
    public String getJavaAdvice(String question) {
        return null; // The return value will be overridden by the AOP aspect
    }
}
</code>

Controller example

<code>@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class ChatController {
    private final ChatService chatService;

    @PostMapping("/chat")
    public String getJavaAdvice(@RequestBody String question) {
        return chatService.getJavaAdvice(question);
    }
}
</code>

Conclusion

Following the high‑level API design of LangChain4j, AI services implemented with custom Spring AI annotations enable centralized prompt template management and reuse, automatically handling AI interface calls via AOP, greatly improving development efficiency. This approach reduces code complexity, decouples business logic from AI infrastructure, and can be combined with other Spring features such as caching.

JavaAOPLLMprompt engineeringSpring AIAI Services
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.