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:
CachedBodyHttpServletRequestCachedBodyHttpServletResponseRequestResponseLoggingFilter
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 GeminiServicehandles 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