When you have 200 concurrent users hitting a single-threaded service, you’ll see the connection pool exhaustion error: “java.sql.SQLException: Unable to acquire JDBC Connection”. This is because the default connection pool size is too small for the number of concurrent requests. To solve this, we need to implement a semantic search engine using Java, Spring Boot, and vector embeddings.

TL;DR: In this tutorial, you will learn how to build a semantic search engine using Java, Spring Boot, and vector embeddings. You will implement a search engine that can understand the meaning of words and phrases, and return relevant results based on their semantic similarity.

## PREREQUISITES To follow this tutorial, you need: * Java 17 or later * Spring Boot 2.7 or later * Maven 3.8 or later * Gradle 7.4 or later * Java Algorithms knowledge The following Maven dependency is required:

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

## UNDERSTANDING SEMANTIC SEARCH Semantic search is a type of search that understands the meaning of words and phrases, and returns relevant results based on their semantic similarity. This is different from traditional search engines, which rely on keyword matching and do not understand the context of the search query. The following ASCII diagram shows the architecture of a semantic search engine:

 +---------------+ | Search Query | +---------------+ | | v +---------------+ | Tokenizer | +---------------+ | | v +---------------+ | Vector Embeddings | +---------------+ | | v +---------------+ | Similarity Calculator | +---------------+ | | v +---------------+ | Result Ranking | +---------------+ 

The following table compares the different vector embeddings algorithms:

Algorithm Description
Word2Vec A popular algorithm for learning vector embeddings from text data.
GloVe An algorithm that learns vector embeddings by representing words as vectors in a high-dimensional space.
FastText An algorithm that learns vector embeddings by representing words as vectors in a high-dimensional space, with support for subword modeling.

## STEP-BY-STEP IMPLEMENTATION To implement a semantic search engine using Java, Spring Boot, and vector embeddings, follow these steps: ### Step 1: Create a Spring Boot Project Create a new Spring Boot project using your favorite IDE or the Spring Initializr web application.

 package com.example.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } 

Expected output:

 2023-03-09 14:30:00.000 INFO 12345 --- [ main] com.example.app.App : Started App in 2.234 seconds (JVM running for 2.456) 

### Step 2: Add Dependencies Add the following dependencies to your `pom.xml` file:

 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.deeplearning4j</groupId> <artifactId>deeplearning4j-core</artifactId> </dependency> 

### Step 3: Create a Vector Embeddings Model Create a vector embeddings model using the Word2Vec algorithm.

 package com.example.app; import org.deeplearning4j.models.word2vec.Word2Vec; import org.deeplearning4j.text.tokenization.tokenizerfactory.TokenizerFactory; import org.deeplearning4j.text.tokenization.tokenizerfactory.UimaTokenizerFactory; import java.util.List; public class VectorEmbeddingsModel { private Word2Vec model; public VectorEmbeddingsModel() { model = new Word2Vec.Builder() .layerSize(100) .seed(42) .tokenizerFactory(new UimaTokenizerFactory()) .build(); } public void train(List<String> texts) { model.fit(texts); } public double[] getVector(String word) { return model.getWordVector(word); } } 

### Step 4: Create a Similarity Calculator Create a similarity calculator that calculates the similarity between two vectors.

 package com.example.app; import org.nd4j.linalg.api.ndarray.INDArray; import org.nd4j.linalg.factory.Nd4j; public class SimilarityCalculator { public double calculateSimilarity(double[] vector1, double[] vector2) { INDArray array1 = Nd4j.create(vector1); INDArray array2 = Nd4j.create(vector2); return array1.dotProduct(array2) / (array1.norm2() * array2.norm2()); } } 

## COMPLETE WORKING EXAMPLE The following is a complete working example of a semantic search engine using Java, Spring Boot, and vector embeddings:

 package com.example.app; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class SearchController { @Autowired private VectorEmbeddingsModel model; @Autowired private SimilarityCalculator calculator; @GetMapping("/search") public List<String> search(@RequestParam("query") String query) { double[] queryVector = model.getVector(query); List<String> results = new ArrayList<>(); // Calculate similarity and rank results return results; } } 

You can test the search engine using the following curl command:

 curl -X GET "http://localhost:8080/search?query=hello" 

This will return a list of relevant results based on the semantic similarity of the query. ## COMMON MISTAKES AND HOW TO FIX THEM ### Mistake 1: Not Closing the Connection Pool If you don’t close the connection pool, you will see the following error: “java.sql.SQLException: Unable to acquire JDBC Connection”

 // WRONG - causes connection pool exhaustion public void search(String query) { Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password"); // ... } 

To fix this, you need to close the connection pool:

 public void search(String query) { Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password"); try { // ... } finally { connection.close(); } } 

### Mistake 2: Not Handling Exceptions If you don’t handle exceptions, you will see the following error: “java.lang.RuntimeException: Error processing search query”

 // WRONG - doesn't handle exceptions public void search(String query) { // ... } 

To fix this, you need to handle exceptions:

 public void search(String query) { try { // ... } catch (Exception e) { // Handle exception } } 

## PERFORMANCE AND PRODUCTION TIPS

Production tip: Use a connection pool to improve performance. Set the hikari.maximum-pool-size property to a reasonable value, such as 10.

Production tip: Use a caching layer to improve performance. Set the spring.cache.type property to redis or ehcache.

Production tip: Monitor your application’s performance using metrics such as response time and error rate. Use a tool such as Spring Batch to monitor and optimize your application’s performance.

For more information on Spring Boot, visit the Spring Boot Tutorials page. ## TESTING To test the search engine, you can use the following JUnit 5 test:

 package com.example.app; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest public class SearchEngineTest { @Autowired private SearchController controller; @Test public void testSearch() { String query = "hello"; List<String> results = controller.search(query); assertEquals(10, results.size()); } } 

This test checks that the search engine returns 10 results for the query “hello”. ## KEY TAKEAWAYS * Use a connection pool to improve performance * Handle exceptions to prevent errors * Monitor your application’s performance using metrics such as response time and error rate * Use a caching layer to improve performance * Use a tool such as Spring Batch to monitor and optimize your application’s performance * Test your application thoroughly to ensure it works as expected * Use a vector embeddings model to improve search results * Use a similarity calculator to calculate the similarity between vectors

Read Next

Pillar Guide: Spring Boot Tutorials Hub — explore the full learning path.

Source Code on GitHub
spring-boot-examples — Clone, Star & Contribute

You Might Also Like

Mastering CrewAI Tutorial: A Step-by-Step Guide to Multi-Agent AI Workflow in 2026
AI Code Review Tools for Java and Spring Boot Projects 2026
AutoGPT vs LangChain Agents vs CrewAI Comparison 2026


Leave a Reply

Your email address will not be published. Required fields are marked *