This Spring Boot application demonstrates multiple approaches to integrate with Google's Gemini Veo 3 video generation API from Java. The implementation is based on the REST API documented at https://ai.google.dev/gemini-api/docs/video (note that the official examples only show Python, JavaScript, and Go, but this project demonstrates Java integration patterns).
⚠️ Important: This is a demonstration project showing different Java polling strategies for long-running operations. Each video generation costs ~$3.20 with the fast preview model and requires Google API access approval.
-
Multiple Client Implementations:
- Spring
RestClient - Java
HttpClient(standalone) - Reactive
WebClient
- Spring
-
Multiple Polling Strategies:
SelfScheduling-based polling (dynamic intervals)FixedRate-based polling (fixed intervals)VirtualThread-based polling (Java 21+)- Reactive
Flux-based polling (WebClient compatibility issue - see notes)
-
REST API Endpoints for testing all approaches
-
Configuration via
application.properties -
Video File Saving with
Base64decoding
- Java 24 or later (with preview features for primitive patterns)
- Gradle (wrapper included)
- Gemini API Key with Veo 3 Access — Set the
GOOGLEAI_API_KEYorGEMINI_API_KEYenvironment variable- Note: Veo 3 is in controlled access and may require approval from Google
export GOOGLEAI_API_KEY="your-api-key-here"
# OR
export GEMINI_API_KEY="your-api-key-here"./gradlew buildChoose one of these approaches:
# Spring Boot application (full context)
./gradlew bootRun
# Lightweight demo (application plugin)
./gradlew run
# Or from IDE after setting Java 24
# Run VeoVideoDemo.main() directlyThe application starts on http://localhost:8080
- POST
/api/video/generate/rest-client - POST
/api/video/generate/http-client - POST
/api/video/generate/self-scheduling - POST
/api/video/generate/fixed-rate - POST
/api/video/generate/virtual-thread - POST
/api/video/generate/reactive
Request body:
{
"prompt": "A cat playing with a ball of yarn in a sunny garden"
}- GET
/api/video/strategies- List available strategies - GET
/api/video/health- Health check
curl -X POST http://localhost:8080/api/video/generate/rest-client \
-H "Content-Type: application/json" \
-d '{"prompt": "A beautiful sunset over mountains"}'Run the interactive demo:
# Recommended: Use Gradle (handles Java 24 toolchain automatically)
./gradlew run
# Alternative: Direct execution (requires Java 24 with preview features)
# java --enable-preview -cp "build/classes/java/main:$(./gradlew -q printClasspath)" com.kousenit.veojava.VeoVideoDemoThe demo will present an interactive menu where you can:
- Choose which approach to test (options 1-6)
- Enter custom prompts or use the default
- See cost warnings before generating videos
- Compare different implementations safely
Available options in demo:
- HttpClient (pure Java, no Spring)
- RestClient (Spring's modern HTTP client)
- SelfScheduling polling strategy
- FixedRate polling strategy
- Reactive polling strategy
⚠️ (known WebClient compatibility issue) - VirtualThread polling strategy
Edit src/main/resources/application.properties:
# API Configuration - checks GOOGLEAI_API_KEY first, then GEMINI_API_KEY
gemini.api.key=${GOOGLEAI_API_KEY:${GEMINI_API_KEY}}
veo.api.model=veo-3.0-fast-generate-preview
# Polling Configuration
veo.polling.interval-seconds=5
veo.polling.max-timeout-minutes=10
# Output Configuration
veo.output.directory=./videos
# Async Configuration - video generation takes 2-4 minutes
spring.mvc.async.request-timeout=600000RestClient— Uses Spring'sRestClientwith autoconfigured JacksonHttpClient— Uses Java 11+HttpClientwith explicitObjectMapperReactiveClient— UsesWebClientwithMono/Fluxpatterns
SelfScheduling— Reschedules after each check completes (dynamic timing)FixedRate— UsesScheduledExecutorServicefor fixed periodic checksVirtualThread— Uses virtual threads for lightweight blocking operations (recommended)Reactive— UsesFlux.intervalwith clean polling patterns (WebClient compatibility issue)
- Submit video generation request → Get operation ID
- Poll operation status every 5 seconds → Wait for
done: true - Extract download URL from response → Get file URI with redirect
- Download video file → Follow 302 redirects to actual content
- Save to local file system → Write binary data to MP4 file
Key Discovery: Veo 3 returns download URLs instead of base64-encoded data, requiring redirect handling for proper file retrieval.
- Paid Feature: Veo 3 fast preview costs $0.40/second (~$3.20 for 8-second videos)
- 8-second videos: Current limitation of the API
- 720p @ 24 fps: Fixed resolution and frame rate
- Redirect handling: All HTTP clients must follow 302 redirects for video downloads
- Buffer limits: WebClient requires 2MB+ buffer for video files (default 256KB insufficient)
- Content filtering: Audio may be blocked while video succeeds
- Controlled access: Veo 3 requires special API access approval
- English prompts: Only English language supported
- Async timeout: REST endpoints require 10-minute timeout due to 2-4 minute generation time
⚠️ WebClient Compatibility: The reactive approach (option 5) has a known compatibility issue with Google's Veo 3 API where identical requests work with HttpClient but fail with 400 Bad Request using WebClient/Reactor Netty. This appears to be a low-level protocol incompatibility. Use VirtualThread approach (option 6) for best reactive-style experience.
src/main/java/com/kousenit/veojava/
├── client/ # HTTP client implementations
├── config/ # Spring configuration
├── controller/ # REST endpoints
├── model/ # Data models (records)
├── service/ # Business logic and polling strategies
└── VeoVideoDemo.java # Standalone demo
Run tests:
./gradlew testNote: Integration tests are disabled by default (using @Disabled) to prevent accidental API costs. Each test video costs ~$6 and takes several minutes to generate.
Test Coverage: The project includes comprehensive unit tests covering:
- Service layer with mocked clients using
@MockitoBean(Spring Boot 3.4+) - REST controller endpoints with proper async testing patterns
- All polling strategies with business logic validation
- Input validation with Bean Validation (
@Valid,@NotBlank) - Resource cleanup patterns with
@PreDestroymethods
Build the project:
./gradlew buildRun all checks including tests:
./gradlew checkCreate a distribution:
./gradlew bootJar
java -jar build/libs/VeoJava-0.0.1-SNAPSHOT.jarThis project demonstrates several key Java/Spring patterns:
- Multiple HTTP Client Approaches: Compare Spring
RestClient, JavaHttpClient, andWebClient - Async Patterns:
SelfScheduling,FixedRate,VirtualThread, and Reactive streams - Polling Strategy Analysis: Comprehensive comparison of non-busy-waiting approaches
- Record-Based Data Models: All DTOs in a single
VeoJavaRecordsclass for easy static imports - Modern Java Features: Sealed interfaces, pattern matching, virtual threads, text blocks, primitive patterns with guards (Java 24 preview), exception pattern matching
- Configuration Properties: Type-safe configuration with
@ConfigurationPropertiesand proper Spring Boot 3.4+ patterns - Polling Strategies: Different approaches to handle long-running operations with proper resource cleanup
- Error Handling: Comprehensive error handling across sync and async flows
- Resource Management: Proper
@PreDestroycleanup forScheduledExecutorServiceinstances to prevent memory leaks - Input Validation: Bean Validation with
@Validand@NotBlankannotations - Testing Patterns: Modern Spring Boot testing with
@MockitoBean, async controller testing, and cost-protection measures
This project demonstrates cutting-edge Java 24 features:
- MODERN_JAVA_FEATURES.md - Comprehensive documentation of Java 24 preview features and modern patterns
- Primitive Patterns with Guards: Type-safe pattern matching on primitive types
- Text Blocks: Multi-line strings throughout the application
- Exception Pattern Matching: Clean error handling with switch expressions
- Enhanced Switch Expressions: Multiple case values and arrow syntax
This project includes comprehensive educational content for Java developers:
- script.md - Complete YouTube video script explaining all 5 polling strategies
- polling-strategy-comparison.md - Detailed comparison matrix with performance metrics and decision guidelines
- mermaid-examples.md - Visual diagrams for presentations and documentation
The tutorial covers the journey from naive busy-waiting to enterprise-grade async patterns, perfect for developers learning modern Java concurrency patterns.
- NETWORKING_STRATEGY_ANALYSIS.md - Comprehensive analysis of HTTP clients and polling strategies with recommendations
- API Implementation Notes - Detailed technical documentation about redirect handling, response structures, and API behavior discoveries
- CLAUDE.md - Development context and implementation decisions
This project serves multiple purposes:
- Production Example: Real-world integration with Google's Veo 3 API including proper error handling, timeouts, and redirect management
- Learning Resource: Comprehensive comparison of 5 different polling strategies from naive blocking to advanced async patterns
- Modern Java Showcase: Demonstrates records, sealed interfaces, virtual threads, primitive patterns with guards (Java 24 preview), reactive streams, and other contemporary features
- Performance Analysis: Includes detailed metrics and recommendations for different concurrency approaches
This is a demonstration project showing different Java approaches to REST API integration with async polling patterns. The implementation includes important discoveries about Google's Veo 3 API behavior, particularly around redirect handling and URL-based video delivery. Feel free to explore and adapt the patterns for your own use cases.
The educational materials (script.md, comparison tables, diagrams) are designed to help other developers understand the trade-offs between different async programming approaches in Java.