Spring Boot + Gemini Vertex AI: Smart Configuration and File-Aware Code Flow
In this section, we walk through the complete backend architecture that connects Spring Boot 2.6 with Gemini Vertex AI using REST. This design uses file-aware logic to decide when to embed a file or upload it to Google Cloud Storage (GCS), all managed by configuration through application.yml
.
Centralized Configuration in application.yml
The application uses a single YAML configuration file to manage:
- model-endpoint: REST API URL to call Gemini
- gcs-upload-url: Template for uploading files to GCS
- bucket-name: Target bucket for large file uploads
- access-token: Token injected via environment or Google service credentials
- instruction-text: Default system instruction for Gemini agent behavior
- Proxy setup: Includes host, port, bypass list, and protocol
These are bound into Spring Boot using GeminiConfig.java
and ProxyConfig.java
via @ConfigurationProperties
.
Configuration Binding Classes
- GeminiConfig: Binds model ID, GCS URLs, tokens, and templates
- ProxyConfig: Reads proxy settings and applies them as system properties
- JavaExecutorConfig: Optional class for executing compiled Java code (used in advanced scenarios)
Unified Endpoint in DocumentController
The entrypoint for all Gemini operations is:
POST /bancsai/api/doc/processJson
This endpoint is mapped in the controller and calls GeminiService.processJson()
:
@PostMapping(value = "/processJson", consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> processJsonRequest(@RequestBody Map<String, Object> requestJsonMap) { JsonObject requestJson = new Gson().toJsonTree(requestJsonMap).getAsJsonObject(); GeminiFunctionCall result = geminiService.processJson(requestJson); ... }
GeminiService.java – Core Business Logic
The class GeminiService
handles all Gemini-related operations. The core method processJson() does the following:
- Extracts prompt and file information from the incoming JSON request
- If a file is present, determines its size using
isInlineFile()
- For small files: extracts base64 and embeds as
inlineData
- For large files: decodes, uploads to GCS via
uploadFileBytesToGCS()
, and adds afileUri
- Prepares a Gemini-compliant payload including generation config
- Calls Gemini using the method
callGeminiApi()
Deciding File Type Using isInlineFile()
This utility method decides whether to embed or upload based on the configured threshold (7MB):
private static boolean isInlineFile(String text, Charset charset, long thresholdBytes) { byte[] bytes = text.getBytes(charset); return bytes.length < thresholdBytes; }
Uploading Large Files to GCS
The method uploadFileBytesToGCS()
takes decoded bytes, builds an authenticated request using the GCS upload URL template, and returns a gs://
file URI:
private String uploadFileBytesToGCS(String fileName, String contentType, byte[] fileBytes) { String uploadUrl = config.getGcsUploadUrl(fileName); ... return "gs://" + config.getBucketName() + "/" + fileName; }
This file URI is then included in the Gemini request payload as file_data
.
Calling the Gemini REST API
The callGeminiApi()
method sends the prepared JSON request to the Gemini endpoint using HttpURLConnection
. It sets headers like:
Authorization: Bearer <accessToken>
Content-Type: application/json
All payloads and responses are logged using HttpLogHelper.logRequest()
and logResponse()
.
Token Handling and Proxy Routing
Google OAuth2 tokens are generated using:
GoogleCredentials.fromStream(...).createScoped(SCOPES).refreshAccessToken()
Proxy setup is read from application.yml
and set globally at runtime by ProxyConfig
. This enables Gemini and GCS calls to work in corporate networks.
Request Logging and Filter Middleware
To support full request/response logging, the following classes are used:
CachedBodyHttpServletRequest
CachedBodyHttpServletResponse
RequestResponseLoggingFilter
These enable request re-reading without disrupting Spring's input stream, so full audit logs can be captured.
Summary of Backend Workflow
- Incoming prompt (and file, if any) is sent to
/processJson
GeminiService
handles decision making (embed vs upload)- Configuration is cleanly externalized in
application.yml
- All calls to external APIs (Gemini, GCS) are logged and secured with proper OAuth2
- Proxy and request logging is fully integrated
Contributor: Team CodeNib — Spring Boot Gemini Integration Series, Page 2
0 Comments