diff --git a/spring-boot-modules/spring-boot-3-3/README.md b/spring-boot-modules/spring-boot-3-3/README.md
new file mode 100644
index 000000000000..65f3ce387643
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/README.md
@@ -0,0 +1,5 @@
+## Relevant Articles
+
+insert here
+
+- More articles: [[<-- prev]](/spring-boot-modules/spring-boot-3-2)
diff --git a/spring-boot-modules/spring-boot-3-3/pom.xml b/spring-boot-modules/spring-boot-3-3/pom.xml
new file mode 100644
index 000000000000..c6f43a93c522
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/pom.xml
@@ -0,0 +1,69 @@
+
+ 4.0.0
+ spring-boot-3-3
+ 0.0.1-SNAPSHOT
+ spring-boot-3-3
+ Demo project for Spring Boot
+
+ com.baeldung.spring-boot-modules
+ spring-boot-modules
+ 1.0.0-SNAPSHOT
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.apache.camel.springboot
+ camel-spring-boot-starter
+ ${apache-camel.version}
+
+
+ org.apache.camel.springboot
+ camel-http-starter
+ ${apache-camel.version}
+
+
+ org.apache.camel
+ camel-jackson
+ ${apache-camel.version}
+
+
+ dev.langchain4j
+ langchain4j-core
+ ${langchain4j.version}
+
+
+ dev.langchain4j
+ langchain4j-ollama
+ ${langchain4j.version}
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+ -parameters
+
+
+
+
+
+
+ 3.2.4
+ 4.7.0
+ 0.33.0
+
+
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/ChatbotApplication.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/ChatbotApplication.java
new file mode 100644
index 000000000000..5c4688c18a20
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/ChatbotApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.chatbot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ChatbotApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ChatbotApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/controller/ChatbotController.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/controller/ChatbotController.java
new file mode 100644
index 000000000000..5dbf2bd7a2ce
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/controller/ChatbotController.java
@@ -0,0 +1,18 @@
+package com.baeldung.chatbot.controller;
+
+import com.baeldung.chatbot.service.ChatbotService;
+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;
+
+@RestController
+public class ChatbotController {
+ @Autowired
+ private ChatbotService chatbotService;
+
+ @GetMapping("/api/chatbot/send")
+ public String getChatbotResponse(@RequestParam String question) {
+ return chatbotService.getResponse(question);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/controller/WhatsAppController.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/controller/WhatsAppController.java
new file mode 100644
index 000000000000..d7ec841952ec
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/controller/WhatsAppController.java
@@ -0,0 +1,38 @@
+package com.baeldung.chatbot.controller;
+
+import com.baeldung.chatbot.service.WhatsAppService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+public class WhatsAppController {
+
+ @Value("${whatsapp.verify_token}")
+ private String verifyToken;
+
+ @Autowired
+ private WhatsAppService whatsAppService;
+
+ @PostMapping("/api/whatsapp/send")
+ public String sendWhatsAppMessage(@RequestParam String to, @RequestParam String message) {
+ whatsAppService.sendWhatsAppMessage(to, message);
+ return "Message sent";
+ }
+
+ @GetMapping("/webhook")
+ public String verifyWebhook(@RequestParam("hub.mode") String mode,
+ @RequestParam("hub.verify_token") String token,
+ @RequestParam("hub.challenge") String challenge) {
+ if ("subscribe".equals(mode) && verifyToken.equals(token)) {
+ return challenge;
+ } else {
+ return "Verification failed";
+ }
+ }
+
+ @PostMapping("/webhook")
+ public void receiveMessage(@RequestBody String payload) {
+ whatsAppService.processIncomingMessage(payload);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/service/ChatbotService.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/service/ChatbotService.java
new file mode 100644
index 000000000000..8beda21222ab
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/service/ChatbotService.java
@@ -0,0 +1,58 @@
+package com.baeldung.chatbot.service;
+
+import java.time.Duration;
+
+import org.apache.hc.core5.http.HttpStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.server.ResponseStatusException;
+
+import dev.langchain4j.model.ollama.OllamaChatModel;
+import jakarta.annotation.PostConstruct;
+
+@Service
+public class ChatbotService {
+
+ private static final Logger logger = LoggerFactory.getLogger(ChatbotService.class);
+
+ @Value("${ollama.api_url}")
+ private String apiUrl;
+
+ @Value("${ollama.model}")
+ private String modelName;
+
+ @Value("${ollama.timeout}")
+ private int timeout;
+
+ @Value("${ollama.max_response_length}")
+ private int maxResponseLength;
+
+ private OllamaChatModel ollamaChatModel;
+
+ @PostConstruct
+ public void init() {
+ this.ollamaChatModel = OllamaChatModel.builder()
+ .baseUrl(apiUrl)
+ .modelName(modelName)
+ .timeout(Duration.ofSeconds(timeout))
+ .numPredict(maxResponseLength)
+ .build();
+ }
+
+ public String getResponse(String question) {
+ logger.debug("Sending to Ollama: {}", question);
+ String answer = ollamaChatModel.generate(question);
+ logger.debug("Receiving from Ollama: {}", answer);
+ if (answer != null && !answer.isEmpty()) {
+ return answer;
+ } else {
+ logger.error("Invalid Ollama response for:\n\n" + question);
+ throw new ResponseStatusException(
+ HttpStatus.SC_INTERNAL_SERVER_ERROR,
+ "Ollama didn't generate a valid response",
+ null);
+ }
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/service/WhatsAppService.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/service/WhatsAppService.java
new file mode 100644
index 000000000000..f3097424ff0b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/chatbot/service/WhatsAppService.java
@@ -0,0 +1,92 @@
+package com.baeldung.chatbot.service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.jackson.JacksonDataFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import jakarta.annotation.PostConstruct;
+
+@Service
+public class WhatsAppService {
+
+ private static final Logger logger = LoggerFactory.getLogger(WhatsAppService.class);
+
+ @Value("${whatsapp.api_url}")
+ private String apiUrl;
+
+ @Value("${whatsapp.access_token}")
+ private String apiToken;
+
+ @Autowired
+ private CamelContext camelContext;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Autowired
+ private ProducerTemplate producerTemplate;
+
+ @Autowired
+ private ChatbotService chatbotService;
+
+ @PostConstruct
+ public void init() throws Exception {
+ camelContext.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ JacksonDataFormat jacksonDataFormat = new JacksonDataFormat();
+ jacksonDataFormat.setPrettyPrint(true);
+
+ from("direct:sendWhatsAppMessage")
+ .setHeader("Authorization", constant("Bearer " + apiToken))
+ .setHeader("Content-Type", constant("application/json"))
+ .marshal(jacksonDataFormat)
+ .process(exchange -> {
+ logger.debug("Sending JSON: {}", exchange.getIn().getBody(String.class));
+ }).to(apiUrl).process(exchange -> {
+ logger.debug("Response: {}", exchange.getIn().getBody(String.class));
+ });
+ }
+ });
+ }
+
+ public void sendWhatsAppMessage(String toNumber, String message) {
+ Map body = new HashMap<>();
+ body.put("messaging_product", "whatsapp");
+ body.put("to", toNumber);
+ body.put("type", "text");
+
+ Map text = new HashMap<>();
+ text.put("body", message);
+ body.put("text", text);
+
+ producerTemplate.sendBody("direct:sendWhatsAppMessage", body);
+ }
+
+ public void processIncomingMessage(String payload) {
+ try {
+ JsonNode jsonNode = objectMapper.readTree(payload);
+ JsonNode messages = jsonNode.at("/entry/0/changes/0/value/messages");
+ if (messages.isArray() && messages.size() > 0) {
+ String receivedText = messages.get(0).at("/text/body").asText();
+ String fromNumber = messages.get(0).at("/from").asText();
+ logger.debug(fromNumber + " sent the message: " + receivedText);
+ this.sendWhatsAppMessage(fromNumber, chatbotService.getResponse(receivedText));
+ }
+ } catch (Exception e) {
+ logger.error("Error processing incoming payload: {} ", payload, e);
+ }
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties b/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties
new file mode 100644
index 000000000000..a2c75b9bcc65
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+# WhatsApp API configuration
+whatsapp.verify_token=BaeldungDemo-Verify-Token
+whatsapp.api_url=https://graph.facebook.com/v20.0/PHONE_NUMBER_ID/messages
+whatsapp.access_token=ACCESS_TOKEN
+
+# Ollama API configuration
+ollama.api_url=http://localhost:11434/
+ollama.model=qwen2:1.5b
+ollama.timeout=30
+ollama.max_response_length=1000
+
+# Logging configuration
+logging.level.root=INFO
+logging.level.com.baeldung.chatbot=DEBUG
diff --git a/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/chatbot/ChatbotApplicationTests.java b/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/chatbot/ChatbotApplicationTests.java
new file mode 100644
index 000000000000..4f7c2a7496c0
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/chatbot/ChatbotApplicationTests.java
@@ -0,0 +1,15 @@
+package com.baeldung.chatbot;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SpringBootTest
+class ChatbotApplicationTests {
+
+ @Test
+ void contextLoads() {
+ assertThat(true).isTrue();
+ }
+}