Java remains the language of choice for enterprise backends — and for good reason. Type safety, mature tooling, the Spring ecosystem, and decades of production-proven patterns make it the dominant platform for fintech, matrimony platforms, media companies, and enterprise SaaS. If you're building an astrology feature into an existing Java application, or starting a new astrology microservice from scratch, this guide shows you exactly how to integrate Vedika API using Spring Boot 3.x best practices.
By the end of this tutorial, you'll have a fully functional Spring Boot service with WebClient reactive calls, DTOs, service layer, Spring Cache for cost optimization, @ControllerAdvice error handling, and @Async parallel processing — all production-ready.
What You'll Build: A Spring Boot 3.x microservice that exposes astrology REST endpoints — birth chart, daily horoscope, AI-powered query, and compatibility matching — backed by Vedika API. Includes caching, error handling, async processing, and an application.yml configuration pattern suitable for enterprise deployment.
Why Vedika API for Java Enterprise Applications?
704 Operations
Birth charts, dashas, transits, muhurta, numerology, AI chatbot — all via a single REST API with JSON payloads.
AI-Powered Queries
Natural language endpoint: ask "When is the best time to launch my product?" and get a chart-verified answer.
XALEN Ephemeris Precision
Astronomical-grade planetary calculations. Not a lookup table — real ephemeris math for every request.
$12/month Starting
Starter at $12, Pro at $60, Business at $120, Enterprise at $240. Pay only for what you use with wallet-based billing.
Prerequisites
- Java 17 or later (LTS recommended)
- Spring Boot 3.x (Spring Initializr)
- Maven or Gradle build tool
- Vedika API key — get yours here
- Basic familiarity with Spring Boot REST services
Step 1: Project Setup with Spring Initializr
Generate a new project at start.spring.io with the following selections, or use this pom.xml:
<project>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
</parent>
<groupId>io.vedika</groupId>
<artifactId>astrology-service</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Step 2: Application Configuration
Configure your API key and base URL in application.yml. Never hardcode secrets — use environment variables or Spring Cloud Config in production:
vedika:
api:
base-url: https://api.vedika.io
key: ${VEDIKA_API_KEY}
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=500,expireAfterWrite=3600s
task:
execution:
pool:
core-size: 4
max-size: 16
queue-capacity: 100
thread-name-prefix: vedika-async-
Step 3: DTO Classes
Define strongly-typed DTOs for request and response payloads. Spring Boot's Jackson auto-maps JSON automatically:
package io.vedika.dto;
import jakarta.validation.constraints.*;
import lombok.*;
import com.fasterxml.jackson.annotation.JsonProperty;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BirthDetailsDto {
@NotBlank
private String datetime;
@NotNull
private Double latitude;
@NotNull
private Double longitude;
@NotBlank
private String timezone;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AstrologyQueryDto {
@NotBlank
private String question;
@Valid
private BirthDetailsDto birthDetails;
}
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class AstrologyResponseDto {
private String answer;
private String system;
private Map<String, Object> birthChart;
private Map<String, Object> usage;
}
Step 4: WebClient Configuration Bean
Configure a singleton WebClient bean with proper timeouts, base URL, and the API key header pre-loaded:
package io.vedika.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.web.reactive.function.client.*;
import io.netty.channel.ChannelOption;
import reactor.netty.http.client.HttpClient;
import java.time.Duration;
@Configuration
@EnableCaching
@EnableAsync
public class VedikaClientConfig {
@Value("${vedika.api.key}")
private String apiKey;
@Value("${vedika.api.base-url}")
private String baseUrl;
@Bean
public WebClient vedikaWebClient() {
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.responseTimeout(Duration.ofSeconds(60));
return WebClient.builder()
.baseUrl(baseUrl)
.clientConnector(new ReactorClientHttpConnector(httpClient))
.defaultHeader("x-api-key", apiKey)
.defaultHeader("Content-Type", "application/json")
.defaultHeader("Accept", "application/json")
.build();
}
}
Step 5: Astrology Service Layer
Build the service class that wraps all Vedika API interactions. Use @Cacheable on deterministic endpoints — the same birth data always produces the same chart, so caching eliminates redundant API costs:
package io.vedika.service;
import io.vedika.dto.*;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.concurrent.CompletableFuture;
@Service
public class AstrologyService {
private final WebClient webClient;
public AstrologyService(WebClient vedikaWebClient) {
this.webClient = vedikaWebClient;
}
@Cacheable(value = "birthCharts", key = "#request.birthDetails.datetime + #request.birthDetails.latitude + #request.birthDetails.longitude")
public AstrologyResponseDto query(AstrologyQueryDto request) {
return webClient.post()
.uri("/api/vedika/chat")
.bodyValue(request)
.retrieve()
.onStatus(status -> status.is4xxClientError(),
resp -> resp.bodyToMono(String.class)
.map(body -> new VedikaApiException("Client error: " + body)))
.onStatus(status -> status.is5xxServerError(),
resp -> resp.bodyToMono(String.class)
.map(body -> new VedikaApiException("Server error: " + body)))
.bodyToMono(AstrologyResponseDto.class)
.block();
}
@Cacheable(value = "birthCharts", key = "'chart:' + #details.datetime + ':' + #details.latitude + ':' + #details.longitude")
public AstrologyResponseDto getBirthChart(BirthDetailsDto details) {
AstrologyQueryDto request = AstrologyQueryDto.builder()
.question("Generate my complete Vedic birth chart with planetary positions, houses, and active yogas.")
.birthDetails(details)
.build();
return query(request);
}
@Async("taskExecutor")
public CompletableFuture<AstrologyResponseDto> getDailyHoroscopeAsync(
BirthDetailsDto details, String zodiacSign) {
AstrologyQueryDto request = AstrologyQueryDto.builder()
.question("What is today's detailed horoscope for " + zodiacSign +
"? Include career, relationships, health, and finance predictions.")
.birthDetails(details)
.build();
AstrologyResponseDto result = query(request);
return CompletableFuture.completedFuture(result);
}
public AstrologyResponseDto getCompatibility(
BirthDetailsDto person1, BirthDetailsDto person2) {
AstrologyQueryDto request = AstrologyQueryDto.builder()
.question("Calculate the kundali matching score (Guna Milan) between these two birth charts. " +
"Provide the Ashtakoot score and compatibility assessment.")
.birthDetails(person1)
.build();
return query(request);
}
}
Step 6: REST Controller
Expose clean REST endpoints that your frontend or other microservices can call. The controller stays thin — all business logic lives in the service layer:
package io.vedika.controller;
import io.vedika.dto.*;
import io.vedika.service.AstrologyService;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.CompletableFuture;
@RestController
@RequestMapping("/api/astrology")
public class AstrologyController {
private final AstrologyService astrologyService;
public AstrologyController(AstrologyService astrologyService) {
this.astrologyService = astrologyService;
}
@PostMapping("/query")
public ResponseEntity<AstrologyResponseDto> query(
@Valid @RequestBody AstrologyQueryDto request) {
AstrologyResponseDto response = astrologyService.query(request);
return ResponseEntity.ok(response);
}
@PostMapping("/birth-chart")
public ResponseEntity<AstrologyResponseDto> birthChart(
@Valid @RequestBody BirthDetailsDto details) {
AstrologyResponseDto response = astrologyService.getBirthChart(details);
return ResponseEntity.ok(response);
}
@PostMapping("/daily-horoscope")
public CompletableFuture<ResponseEntity<AstrologyResponseDto>> dailyHoroscope(
@Valid @RequestBody BirthDetailsDto details,
@RequestParam String zodiacSign) {
return astrologyService
.getDailyHoroscopeAsync(details, zodiacSign)
.thenApply(ResponseEntity::ok);
}
@PostMapping("/compatibility")
public ResponseEntity<AstrologyResponseDto> compatibility(
@Valid @RequestBody CompatibilityRequestDto request) {
AstrologyResponseDto response = astrologyService
.getCompatibility(request.getPerson1(), request.getPerson2());
return ResponseEntity.ok(response);
}
}
Step 7: Global Error Handling with @ControllerAdvice
Centralize error handling so your controllers stay clean. Map Vedika API errors to appropriate HTTP status codes with descriptive messages:
package io.vedika.exception;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.MethodArgumentNotValidException;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(VedikaApiException.class)
public ResponseEntity<Map<String, Object>> handleVedikaError(VedikaApiException ex) {
HttpStatus status = ex.getStatusCode() == 402
? HttpStatus.PAYMENT_REQUIRED
: ex.getStatusCode() == 429
? HttpStatus.TOO_MANY_REQUESTS
: HttpStatus.BAD_GATEWAY;
return ResponseEntity.status(status).body(Map.of(
"error", ex.getMessage(),
"code", status.value(),
"source", "vedika-api"
));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, Object>> handleValidation(
MethodArgumentNotValidException ex) {
String message = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(fe -> fe.getField() + ": " + fe.getDefaultMessage())
.findFirst()
.orElse("Validation failed");
return ResponseEntity.badRequest().body(Map.of(
"error", message,
"code", 400
));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleGeneral(Exception ex) {
return ResponseEntity.internalServerError().body(Map.of(
"error", "An unexpected error occurred",
"code", 500
));
}
}
Ready to Build Enterprise Astrology Features?
Try the FREE Sandbox — 700+ mock endpoints, no auth required. Production plans from $12/month.
Explore the Sandbox
Step 8: Scheduled Batch Processing
Use Spring's @Scheduled and @Async together to generate daily horoscopes for all users in parallel overnight — dramatically reducing your peak-hour API usage:
package io.vedika.scheduler;
import io.vedika.service.*;
import org.springframework.scheduling.annotation.*;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Component
public class DailyHoroscopeScheduler {
private final AstrologyService astrologyService;
private final UserService userService;
public DailyHoroscopeScheduler(AstrologyService astrologyService,
UserService userService) {
this.astrologyService = astrologyService;
this.userService = userService;
}
@Scheduled(cron = "0 30 19 * * *", zone = "UTC")
public void generateDailyHoroscopes() {
List<UserProfile> users = userService.getAllActiveUsers();
List<CompletableFuture<?>> futures = users.stream()
.map(user -> astrologyService.getDailyHoroscopeAsync(
user.getBirthDetails(), user.getZodiacSign()))
.toList();
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
System.out.println("Generated horoscopes for " + users.size() + " users");
}
}
Step 9: Integration Test
Write a Spring Boot integration test to verify your service wires correctly before deploying. Use @SpringBootTest with a mock WebClient for CI environments:
@SpringBootTest
class AstrologyServiceTest {
@Autowired
private AstrologyService astrologyService;
@Test
void testBirthChartQuery() {
BirthDetailsDto details = BirthDetailsDto.builder()
.datetime("1990-06-15T14:30:00")
.latitude(28.6139)
.longitude(77.2090)
.timezone("+05:30")
.build();
AstrologyResponseDto response = astrologyService.getBirthChart(details);
assertNotNull(response);
assertNotNull(response.getAnswer());
assertFalse(response.getAnswer().isEmpty());
}
@Test
void testCachingReducesApiCalls() {
BirthDetailsDto details = BirthDetailsDto.builder()
.datetime("1985-03-21T08:00:00")
.latitude(19.0760).longitude(72.8777)
.timezone("+05:30")
.build();
AstrologyResponseDto first = astrologyService.getBirthChart(details);
AstrologyResponseDto second = astrologyService.getBirthChart(details);
assertEquals(first.getAnswer(), second.getAnswer());
}
}
Sample curl Request
Test your running Spring Boot service directly:
curl -X POST http://localhost:8080/api/astrology/birth-chart \
-H "Content-Type: application/json" \
-d '{
"datetime": "1990-06-15T14:30:00",
"latitude": 28.6139,
"longitude": 77.2090,
"timezone": "+05:30"
}'
curl -X POST http://localhost:8080/api/astrology/query \
-H "Content-Type: application/json" \
-d '{
"question": "What are my career prospects for 2026?",
"birthDetails": {
"datetime": "1990-06-15T14:30:00",
"latitude": 28.6139,
"longitude": 77.2090,
"timezone": "+05:30"
}
}'
Why Choose Vedika API Over Competitors?
AI Chatbot Built-In
No other astrology API includes a natural language AI engine. One endpoint handles any question — no complex orchestration required.
704 Calculations
Birth charts, Vimshottari dasha, ashtakavarga, muhurta, numerology, compatibility, transit analysis — far more than the 50-80 endpoints competitors provide.
MCP Server Support
The native first-party astrology MCP server. Your AI agents can call Vedika directly through the Model Context Protocol — no REST wrappers needed.
30 Languages
Support for Hindi, Tamil, Telugu, Bengali, Gujarati, Marathi, and 24 more languages for truly global astrology applications.
XALEN Ephemeris
Astronomical-grade ephemeris calculations — not lookup tables. Same engine used by professional Vedic astrology software worldwide.
Enterprise-Ready
99.9% uptime SLA, dual-region deployment (US + Mumbai), rate limiting, secure API key auth, and comprehensive monitoring.
Pricing
Vedika API uses wallet-based billing starting at $12/month — pay only for queries you actually run:
- Starter: $12/month — ideal for indie Java developers
- Professional: $60/month — for growing enterprise services
- Business: $120/month — for production platforms
- Enterprise: $240/month — top-up credits, SLA support, dedicated onboarding
All plans include access to all 700+ operations, the AI chatbot, and 30-language support. Compare plans in detail.
Conclusion
Integrating Vedika API into a Java Spring Boot application follows standard enterprise patterns — no exotic dependencies or special adapters required. The key architectural decisions made in this guide:
- WebClient for reactive, non-blocking HTTP calls — critical for high-concurrency services
- Spring Cache with Caffeine — birth chart calculations are deterministic; cache aggressively to cut API costs
- @Async + CompletableFuture — parallel horoscope generation for batch jobs
- @ControllerAdvice — centralized error handling that maps Vedika error codes to correct HTTP status
- Environment-based configuration — never hardcode API keys; use
${VEDIKA_API_KEY} with Spring's property injection
Next steps:
- Get your API key at vedika.io/dashboard
- Try the free sandbox — 700+ mock endpoints, no auth, no cost
- Review the full API reference for all 700+ operations
- Add Resilience4j circuit breaker for production-grade fault tolerance
- Set up Spring Actuator metrics to monitor cache hit rates and API latency
About Vedika Intelligence: Vedika is the only B2B astrology API with an AI-powered chatbot engine, serving production enterprise applications worldwide. The Vedika Intelligence Engine enables natural language astrology queries with XALEN Ephemeris-verified precision, supporting both Vedic and Western astrology across 30 languages.