- Check database for
is_primaryflag consistency - Verify only one image per vehicle has
is_primary=true - Review delete logic for primary image promotion
- Use set-primary endpoint to explicitly set primary
Overview
sgivu-vehicle manages the vehicle catalog (cars and motorcycles) and associated images. It supports CRUD operations, advanced search, state management (available/unavailable), and image upload/management via AWS S3 with presigned URLs.
Technologies
- Java: 21
- Spring Boot: 4.0.1
- Spring Security: Resource Server (JWT validation)
- Spring Data JPA: PostgreSQL persistence
- Flyway: Database migrations
- AWS SDK S3:
software.amazon.awssdk.s3for image storage - Spring Cloud Config Client: Centralized configuration
- Spring Cloud Eureka Client: Service registration
- SpringDoc OpenAPI: Swagger UI documentation
- MapStruct: DTO mapping
- Lombok: Code generation
Prerequisites
- JDK 21
- Maven 3.9+
- PostgreSQL database
- AWS S3 bucket with proper permissions
sgivu-configandsgivu-discoveryservices running
Running the Service
Development with Docker Compose
Local Execution
Docker Build
AWS S3 Integration
S3 Service
S3Service provides presigned URL generation for:- Upload: Direct client-to-S3 uploads
- Download: Temporary access to images
- Reduces server load (direct upload)
- Secure temporary access
- No proxy bandwidth consumption
Presigned URL Flow
Confirm Upload
Client confirms upload to backend:Backend validates key and registers image metadata in database.
Allowed Image Types
Only these MIME types are accepted:image/jpegimage/pngimage/webp
Primary Image Management
- First Image: Automatically marked as
is_primary=true - Delete Primary: Next oldest image automatically promoted to primary
- Set Primary: Use dedicated endpoint to change primary image
CORS Configuration
Bucket CORS
S3BucketCorsConfig ensures S3 bucket allows uploads from configured origins:Update
allowed-origins to match your frontend domains in production.Security
Authentication
JWT Token Validation:- Tokens issued by
sgivu-auth JwtAuthenticationConvertermaps claims to authorities- Resource Server validates signature via JWKS
Authorization
Required Permissions:vehicle:create- Create vehiclesvehicle:read- View vehiclesvehicle:update- Update vehiclesvehicle:delete- Delete vehiclesvehicle:manage-images- Upload/delete images
Internal Service Communication
InternalServiceAuthenticationFilter:- Allows service-to-service calls via
X-Internal-Service-Key - Bypasses JWT validation for internal endpoints
- Must be kept secret and rotated regularly
AWS Security Recommendations
Database Schema
Flyway Migrations
Location:src/main/resources/db/migration
Tables Created:
vehicles: Main vehicle catalog- Common fields: VIN, brand, model, year, price, status
- Type discriminator for cars vs motorcycles
vehicle_images: Image metadata- S3 key, file name, content type
is_primaryflag- Foreign key to vehicles
vehicles.vin(unique)vehicles.statusvehicles.vehicle_typevehicle_images.vehicle_idvehicle_images.is_primary
API Endpoints
Vehicle Management
List vehicles with advanced filteringRequired Permission:
vehicle:readQuery Parameters:status: Filter by status (AVAILABLE, SOLD, RESERVED)vehicleType: Filter by type (CAR, MOTORCYCLE)minPrice,maxPrice: Price rangebrand,model,year: Search criteriapage,size,sort: Pagination
Get vehicle by ID with imagesRequired Permission:
vehicle:readCreate new vehicleRequired Permission:
vehicle:createValidations:- Unique VIN
- Valid vehicle type
- Required fields for type
Update vehicle informationRequired Permission:
vehicle:updateUpdate vehicle statusRequired Permission:
vehicle:updateBody: {"status": "AVAILABLE"}Delete vehicle (soft delete)Required Permission:
vehicle:deleteImage Management
Request presigned URL for image uploadRequired Permission: Returns:
vehicle:manage-imagesBody:Confirm image upload and register metadataRequired Permission:
vehicle:manage-imagesBody:Get presigned download URL for imageRequired Permission:
vehicle:readReturns:Set image as primaryRequired Permission:
vehicle:manage-imagesDelete vehicle imageRequired Permission:
vehicle:manage-imagesBehavior: If deleting primary image, promotes next image to primaryRequest/Response Examples
Create Car
Response
Observability
Actuator Endpoints
/actuator/health: Service and S3 connectivity health/actuator/info: Application metadata/actuator/metrics: Custom metrics for image operations
OpenAPI Documentation
Swagger UI:/swagger-ui/index.html
Configuration: OpenApiConfig with environment-specific servers
Distributed Tracing
Zipkin Integration:- Configured via
sgivu-config - Traces S3 operations
- Correlates image upload flows
Testing
- Unit tests for services
- Repository integration tests
- S3 service mocking
- Security authorization tests
- Image workflow integration tests
Troubleshooting
401/403 Authorization errors
401/403 Authorization errors
S3 upload failures
S3 upload failures
Symptoms: Presigned URL upload returns 403 or failsSolutions:
- Verify AWS credentials and permissions
- Check S3 bucket policy allows PutObject
- Confirm bucket name is correct
- Validate content type is allowed
- Review CORS configuration on bucket
- Check presigned URL hasn’t expired
Image not uploading
Image not uploading
Symptoms: Upload to S3 succeeds but image not appearingSolutions:
- Ensure confirm-upload endpoint is called
- Verify S3 key matches between upload and confirm
- Check database for image record
- Review backend logs for validation errors
- Confirm vehicle ID exists
CORS errors during upload
CORS errors during upload
Symptoms: Browser blocks S3 upload with CORS errorSolutions:
- Verify
aws.s3.allowed-originsincludes frontend domain - Check S3 bucket CORS configuration applied
- Ensure
S3BucketCorsConfigran on startup - Add explicit CORS rules in AWS console if needed
- Verify Content-Type header matches allowed types
Primary image not set correctly
Primary image not set correctly
Symptoms: Wrong image shows as primary or no primary setSolutions:
Duplicate VIN error
Duplicate VIN error
Symptoms: Vehicle creation fails with constraint violationSolutions:
- Check VIN uniqueness before creation
- Handle duplicate key exception gracefully
- Allow VIN update only in specific scenarios
- Consider soft delete for removed vehicles
Environment Variables
| Variable | Description | Example |
|---|---|---|
DB_HOST | PostgreSQL host | sgivu-postgres-vehicle |
DB_PORT | PostgreSQL port | 5432 |
DB_NAME | Database name | sgivu_vehicle |
DB_USERNAME | Database username | sgivu_user |
DB_PASSWORD | Database password | secure_password |
AWS_ACCESS_KEY_ID | AWS access key | AKIAIOSFODNN7EXAMPLE |
AWS_SECRET_ACCESS_KEY | AWS secret key | wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY |
AWS_REGION | S3 region | us-east-1 |
aws.s3.bucket-name | S3 bucket name | sgivu-vehicles |
aws.s3.allowed-origins | CORS allowed origins | http://localhost:3000 |
SERVICE_INTERNAL_SECRET_KEY | Internal service key | secret-key-value |
Best Practices
Presigned URLs
Use presigned URLs for direct client-to-S3 uploads to reduce server load
Image Validation
Validate image types and sizes before generating presigned URLs
IAM Roles
Use IAM roles instead of access keys in production environments
URL Expiration
Keep presigned URL expiration short (15 minutes) for security
Related Services
Purchase-Sale
References vehicles in purchase/sale contracts
Client Service
Clients purchase vehicles
Gateway
Routes vehicle management requests