DEV Community

Abhishek Hulule
Abhishek Hulule

Posted on

Step-by-Step Guide to Connect Google Gemini AI with Spring Boot and React

Connect Google Gemini AI with Spring Boot and React

Step-by-Step Guide to Connect Google Gemini AI with Spring Boot and React

AI is no longer a concept reserved only for research labs or big tech companies. Today, developers can add powerful AI features to everyday applications with very little effort.

In this blog, I’ll show you how to integrate Google’s powerful Gemini AI into a full-stack application using a Spring Boot backend and a React frontend. This will be a hands-on, step-by-step guide. By the end, you’ll have a custom, working AI chatbot interface communicating securely with Google’s servers.

What is Google Gemini?
Google Gemini is a next-generation Large Language Model (LLM) designed to understand and generate human-like text. It can answer questions, summarize text, and power intelligent chatbots. Google provides Gemini via a REST API, making it incredibly easy to integrate into backend systems like Spring Boot.

Why This Architecture? (Spring Boot + React)
You might wonder: Why not just call the Gemini API directly from React?

Calling the AI directly from the frontend is a major security risk because it exposes your secret API key to the public. The correct and secure way to build an AI app is:

  1. React Frontend: Captures the user’s prompt and displays the UI.

  2. Spring Boot Backend: Acts as a secure proxy. It holds the secret API key, receives the prompt from React, talks to Google, and sends the answer back.

Let’s dive into the code!

Prerequisites

Part 1: System SetUp:

Before starting, ensure you have:

Java 17+ and Maven installed
Node.js installed for React
A basic Spring Boot project and a React (Vite or CRA) project ready
A Gemini API Key (You can get one for free at Google AI Studio)

Google AI Studio( Gemini API Key )
Google AI Studio( Gemini API Key)

Part 2: Spring Boot Backend Setup:

Required Dependencies (pom.xml)

One of the best parts about this architecture is how lightweight it is. Because we are communicating directly with Google’s REST API using Spring’s built-in RestTemplate, we do not need to install heavy external AI libraries or wait for third-party wrappers to update when Google releases a new model.

All you need is the standard Spring Boot Web starter! Ensure you have the following dependency in your pom.xml:

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

Enter fullscreen mode Exit fullscreen mode

(Note: If you are using Spring Security or JWT authentication in your app, you will naturally have those dependencies as well, but spring-boot-starter-web is the only requirement for the AI communication.)

Part 1: Spring Boot Backend Setup

1. Configure Your API Key
First, keep your API key safe by adding it to your application.properties (or application-local.properties):

A Gemini API Key (You can get one for free at Google AI Studio)

properties

gemini.api.url=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
gemini.api.key=YOUR_ACTUAL_API_KEY_HERE

Enter fullscreen mode Exit fullscreen mode

2. Create the Data Transfer Objects (DTOs)
Google expects a very specific JSON structure. To handle this easily, we use Jackson and standard Java classes. Create a GeminiDTO.java file to map the request and response:

java

package com.yourpackage.dto;

import java.util.List;

public class GeminiDTO {
    public static class Request {
        public List<Content> contents;
        public Request() {} 
        public Request(String text) {
            this.contents = List.of(new Content(new Part(text)));
        }
    }

    public static class Content {
        public List<Part> parts;
        public Content() {} 
        public Content(Part part) { this.parts = List.of(part); }
    }

    public static class Part {
        public String text;
        public Part() {} 
        public Part(String text) { this.text = text; }
    }

    public static class Response {
        public List<Candidate> candidates;
        public Response() {} 
    }

    public static class Candidate {
        public Content content;
        public Candidate() {} 
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Create the AI Service
We will use Spring’s RestTemplate to make the HTTP POST request to Google. Create GeminiService.java:

java

@Service
public class GeminiService {

    @Value("${gemini.api.url}")
    private String apiUrl;

    @Value("${gemini.api.key}")
    private String apiKey;

    private final RestTemplate restTemplate = new RestTemplate();

    public String getChatResponse(String prompt) {
        String urlWithKey = apiUrl + "?key=" + apiKey;
        GeminiDTO.Request requestBody = new GeminiDTO.Request(prompt);

        try {
            GeminiDTO.Response response = restTemplate.postForObject(
                urlWithKey, requestBody, GeminiDTO.Response.class
            );

            if (response != null && response.candidates != null && !response.candidates.isEmpty()) {
                return response.candidates.get(0).content.parts.get(0).text;
            }
            return "I couldn't generate a response.";
        } catch (Exception e) {
            return "Error connecting to AI: " + e.getMessage();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Expose the REST Controller
Finally, expose this service to your React frontend via a REST endpoint in GeminiController.java:

java

@RestController
@RequestMapping("/api/ai")
public class GeminiController {

    private final GeminiService geminiService;

    public GeminiController(GeminiService geminiService) {
        this.geminiService = geminiService;
    }

    @PostMapping("/chat")
    public ResponseEntity<Map<String, String>> chat(@RequestBody Map<String, String> request) {
        String prompt = request.get("message");
        String response = geminiService.getChatResponse(prompt);
        return ResponseEntity.ok(Map.of("response", response));
    }
}
Enter fullscreen mode Exit fullscreen mode

Part 2: React Frontend Setup
Now that our backend securely handles the AI logic, we can build a sleek chat interface in React.

Create an AIChat.jsx component. This component will manage the chat history and make an API call to our Spring Boot backend:

javascript

import React, { useState } from "react";
import "./AIChat.css"; // Add your custom styling here in the AIChat.css file

const AIChat = () => {
  const [input, setInput] = useState("");
  const [messages, setMessages] = useState([
    { sender: "ai", text: "Hi! I am your AI assistant. How can I help you today?" }
  ]);
  const [loading, setLoading] = useState(false);

  const sendMessage = async () => {
    if (!input.trim()) return;

    const userMessage = { sender: "user", text: input };
    setMessages((prev) => [...prev, userMessage]);
    setInput("");
    setLoading(true);

    try {
      // Make sure this URL matches your Spring Boot server!
// enter the correct the URL here 
      const response = await fetch("http://localhost:8080/api/ai/chat", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          // Include Authorization headers here if using JWT! . 
// So if you are not using the JWT then don't use it 

        },
        body: JSON.stringify({ message: userMessage.text }),
      });

      const data = await response.json();
      setMessages((prev) => [...prev, { sender: "ai", text: data.response }]);
    } catch (error) {
      setMessages((prev) => [...prev, { sender: "ai", text: "Sorry, I am offline." }]);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="ai-chat-container">
      <div className="chat-history">
        {messages.map((msg, index) => (
          <div key={index} className={`message ${msg.sender}`}>
            <p>{msg.text}</p>
          </div>
        ))}
        {loading && <div className="message ai"><p>Thinking...</p></div>}
      </div>

      <div className="chat-input-area">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && sendMessage()}
          placeholder="Ask me anything..."
        />
        <button onClick={sendMessage} disabled={loading}>Send</button>
      </div>
    </div>
  );
};

export default AIChat;
Enter fullscreen mode Exit fullscreen mode

When you send the prompt
When you send the prompt

After receiving the Answer for the prompt
After receiving the Answer for the prompt

By following this guide, you have successfully built a full-stack AI application! You kept your API key completely secure on the backend, parsed the data cleanly using Java DTOs, and built a responsive UI to interact with it.

Google’s Gemini API is incredibly powerful, and by pairing it with Spring Boot and React, the possibilities are endless. Happy coding!

Common Errors & Troubleshooting

When integrating the Gemini API, you might run into a few common errors. Here is a quick guide on why they happen and how to fix them:

1. Java Error: 404 Not Found

Why it happens: You are trying to use an old or retired model (for example, gemini-1.5-flash). Google frequently updates their models and retires older versions.

How to fix it: Check the URL in your application.properties file. Make sure you are using the latest supported model, such as gemini-2.0-flash.

2. Java Error: 429 Too Many Requests

Why it happens: You have exceeded the free tier rate limit. The free tier only allows 15 requests per minute.

How to fix it: Just wait a minute and try again!

Important Note: If the error message specifically says limit: 0, this means Google does not offer the free tier in your country (like the UK or parts of Europe). You will need to either add a credit card to your Google Cloud billing or switch to a different free API provider like Groq.

3. Java Error: Cannot construct instance of GeminiDTO$Content (no Creators, like default constructor, exist)

Why it happens: Your API key works and Google successfully returned an answer! However, your Java backend crashed when trying to read the JSON response. The Jackson JSON parser requires empty “default” constructors to build the nested objects.

How to fix it: Make sure every nested class inside your GeminiDTO.java file (like Request, Content, Part, etc.) has an empty constructor, for example: public Content() {}.

4. Browser Error: POST http://localhost:8080/api/ai/chat 403 (Forbidden)

Why it happens: If you are using Spring Security (like JWT authentication), and your AI backend code throws an exception, Spring Boot tries to redirect to the /error page. Because the user is not authenticated for /error, Spring blocks it and returns a 403 to the frontend instead of the real error.

How to fix it: Check your Java backend console. The real error (like a typo in your properties file or a 429 rate limit) will be printed there. Fix the backend issue, and the 403 will disappear.

Get the Code: You can get the complete project source code from my GitHub repository here: 👉 https://github.com/AbhishekHulule9579/Study-Group-Finder

Note: I have integrate the AI chat service to the One of my project .And not done the AI chat service on the simple project . So if you wants to take a look on the whole project then just visit my Git profile OR the repository link give above .

Let’s Connect! Written by Abhishek Hulule, a full-stack developer passionate about simplifying backend development and exploring modern AI integrations.

💼 LinkedIn: https://www.linkedin.com/in/abhishek-hulule-711566292/
🌐 GitHub: https://github.com/AbhishekHulule9579
📧 Email: abhihulule2603@gmail.com

Other Blogs :
https://medium.com/@abhihulule2603/aws-certificate-manager-acm-complete-guide-to-ssl-tls-certificates-and-https-setup-2887244daebd?source=user_profile_page---------0-------------8e71f4b98ed4----------------------

Top comments (0)