This guide will help you set up and understand a Spring Boot application that integrates with Spring AI and Google Vertex AI's embedding capabilities.
Prerequisites
- Java 17 JDK installed
- Maven installed (version 3.6.3 or later)
- Google Cloud account with Vertex AI enabled
- Google Cloud SDK installed and configured (for local development)
1. Project Setup
Final pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
</parent>
<groupId>com.example</groupId>
<artifactId>vertex-ai-embedding-service</artifactId>
<version>1.0.0</version>
<name>Vertex AI Embedding Service</name>
<properties>
<java.version>17</java.version>
<spring-ai.version>0.8.1</spring-ai.version>
</properties>
<dependencies>
<!-- Core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Vertex AI Embedding -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-vertex-ai-embedding</artifactId>
</dependency>
<!-- Lombok (Optional) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. Configuration (application.yml
)
spring:
ai:
vertex:
ai:
embedding:
enabled: true
project-id: ${GCP_PROJECT_ID:your-project-id}
location: ${GCP_LOCATION:us-central1}
credentials:
resource: ${GCP_CREDENTIALS_PATH:classpath:gcp-service-account.json}
options:
model: textembedding-gecko@latest # or textembedding-gecko@003
dimensions: 768 # Optional: Match your model's output dimensions
logging:
level:
org.springframework.ai: DEBUG # Useful for debugging API calls
3. Code Implementation
(A) Embedding Request/Response DTOs
// EmbeddingRequest.java
@Data // Lombok (or manually write getters/setters)
public class EmbeddingRequest {
@NotBlank
private String text;
}
// EmbeddingResponse.java
@Data
public class EmbeddingResponse {
private List<Double> embedding;
private String model;
private Integer tokenCount;
}
(B) Service Layer (EmbeddingService
)
@Service
@RequiredArgsConstructor // Lombok (or use constructor injection)
public class EmbeddingService {
private final EmbeddingClient embeddingClient;
public EmbeddingResponse generateEmbedding(String text) {
EmbeddingResponse embeddingResponse = embeddingClient.embedForResponse(List.of(text));
return EmbeddingResponse.builder()
.embedding(embeddingResponse.getResults().get(0).getOutput())
.model("textembedding-gecko")
.tokenCount(embeddingResponse.getMetadata().getUsage().getPromptTokens())
.build();
}
}
(C) REST API (EmbeddingController
)
@RestController
@RequestMapping("/api/embeddings")
@RequiredArgsConstructor
public class EmbeddingController {
private final EmbeddingService embeddingService;
@PostMapping
public ResponseEntity<EmbeddingResponse> createEmbedding(
@Valid @RequestBody EmbeddingRequest request
) {
return ResponseEntity.ok(embeddingService.generateEmbedding(request.getText()));
}
}
4. Testing
(A) Unit Test (EmbeddingServiceTest
)
@ExtendWith(MockitoExtension.class)
class EmbeddingServiceTest {
@Mock
private EmbeddingClient embeddingClient;
@InjectMocks
private EmbeddingService embeddingService;
@Test
void testGenerateEmbedding() {
// Mock response
EmbeddingResponse mockResponse = new EmbeddingResponse(
List.of(new Embedding(List.of(0.1, 0.2, 0.3), 1)),
new Usage(10, 0, 10)
);
when(embeddingClient.embedForResponse(anyList()))
.thenReturn(mockResponse);
// Test
EmbeddingResponse response = embeddingService.generateEmbedding("test");
// Assertions
assertEquals(3, response.getEmbedding().size());
assertEquals(10, response.getTokenCount());
}
}
(B) Integration Test (EmbeddingControllerIT
)
@SpringBootTest
@AutoConfigureMockMvc
class EmbeddingControllerIT {
@Autowired
private MockMvc mockMvc;
@Test
void testEmbeddingEndpoint() throws Exception {
mockMvc.perform(post("/api/embeddings")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"text\": \"sample text\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.embedding").exists());
}
}
5. Running
Run Locally
export GCP_PROJECT_ID=your-project-id
export GCP_LOCATION=us-central1
export GCP_CREDENTIALS_PATH=/path/to/service-account.json
mvn spring-boot:run
6. Postman Testing
- Endpoint:
POST /api/embeddings
- Body:
{
"text": "This is a test sentence for embeddings."
}
- Response:
{
"embedding": [0.12, -0.34, ...],
"model": "textembedding-gecko",
"tokenCount": 8
}