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?
140+ Endpoints
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.
Swiss 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 — 65 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.
140+ Calculations
Birth charts, Vimshottari dasha, ashtakavarga, muhurta, numerology, compatibility, transit analysis — far more than the 50-80 endpoints competitors provide.
MCP Server Support
The world's first 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.
Swiss 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 140+ endpoints, 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 — 65 mock endpoints, no auth, no cost
- Review the full API reference for all 140+ endpoints
- 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 Swiss Ephemeris-verified precision, supporting both Vedic and Western astrology across 30 languages.