This Spring Boot application provides a complete product management system with image upload and download capabilities using Amazon S3 for storage.
- Product Management: Create, read, update, and delete products
- Image Upload: Upload product images to Amazon S3
- Image Download: Download and display product images from S3
- Web Interface: Simple HTML interface for testing functionality
- REST API: Complete REST API for product and image management
- Java 21+
- Maven 3.6+
- PostgreSQL database
- AWS Account with S3 access
- AWS CLI configured (optional, for local development)
For local development and testing, we use MinIO (S3-compatible storage) and PostgreSQL via Docker:
# Run the setup script
./setup-local.sh
# Or manually start services
docker compose -f docker-compose-services.yml up -dThis will start:
- PostgreSQL on port 5333
- MinIO (S3-compatible) on port 9000 (API) and 9001 (Console)
- MinIO bucket initialization (creates product-imagesbucket)
Option A: Use Docker (Recommended)
docker compose -f docker-compose-services.yml up -dOption B: Local PostgreSQL
- Install PostgreSQL
- Create a database named jfs
- Update application.propertieswith your database credentials
The application is pre-configured for local development with MinIO:
# Database Configuration
spring.datasource.url=jdbc:postgresql://localhost:5333/jfs
spring.datasource.username=amigoscode
spring.datasource.password=password
# AWS S3 Configuration (MinIO for local development)
aws.region=us-east-1
aws.s3.bucket=product-images
aws.s3.endpoint-override=http://localhost:9000
aws.s3.path-style-enabled=true
aws.access-key-id=minioadmin
aws.secret-access-key=minioadmin123For production deployment with real AWS S3:
- Log into AWS Console
- Go to S3 service
- Create a new bucket (e.g., your-product-images-bucket)
- Note the bucket name for configuration
Option A: AWS CLI (Recommended for local development)
aws configureOption B: Environment Variables
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_DEFAULT_REGION=us-east-1Option C: IAM Roles (for EC2/ECS deployment)
- Attach appropriate IAM role with S3 permissions
# AWS S3 Configuration (Production)
aws.region=us-east-1
aws.s3.bucket=your-product-images-bucket
aws.s3.endpoint-override=
aws.s3.path-style-enabled=false
aws.access-key-id=${AWS_ACCESS_KEY_ID}
aws.secret-access-key=${AWS_SECRET_ACCESS_KEY}Your AWS credentials need the following S3 permissions:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:HeadObject"
            ],
            "Resource": "arn:aws:s3:::your-product-images-bucket/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::your-product-images-bucket"
        }
    ]
}# Quick setup (recommended)
./setup-local.sh
# Or manually
docker compose -f docker-compose-services.yml up -dmvn clean packagemvn spring-boot:runOr run the JAR file:
java -jar target/product-service.jar- Web Interface: http://localhost:8080
- API Base URL: http://localhost:8080/api/v1/products
- MinIO Console: http://localhost:9001 (minioadmin/minioadmin123)
- GET /api/v1/products- Get all products
- GET /api/v1/products/{id}- Get product by ID
- POST /api/v1/products- Create new product (JSON)
- POST /api/v1/products- Create new product with image (multipart/form-data)
- PUT /api/v1/products/{id}- Update product
- DELETE /api/v1/products/{id}- Delete product
- POST /api/v1/products/{id}/image- Upload product image
- GET /api/v1/products/{id}/image- Download product image
Using the Web Interface:
- Open http://localhost:8080
- Fill in the product form
- Select an image file
- Click "Create Product"
Using cURL (Single Request - Recommended):
# Create product with image in single request
curl -X POST http://localhost:8080/api/v1/products \
  -F "name=Sample Product" \
  -F "description=A sample product description" \
  -F "price=29.99" \
  -F "stockLevel=100" \
  -F "image=@/path/to/image.jpg"Using cURL (Separate Requests):
# Create product first
curl -X POST http://localhost:8080/api/v1/products \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sample Product",
    "description": "A sample product description",
    "price": 29.99,
    "stockLevel": 100
  }'
# Upload image (replace {product-id} with actual ID)
curl -X POST http://localhost:8080/api/v1/products/{product-id}/image \
  -F "file=@/path/to/image.jpg"curl -O http://localhost:8080/api/v1/products/{product-id}/imagesrc/
├── main/
│   ├── java/com/amigoscode/
│   │   ├── config/
│   │   │   └── AwsS3Config.java          # AWS S3 configuration
│   │   ├── product/
│   │   │   ├── Product.java              # Product entity
│   │   │   ├── ProductController.java    # REST controller
│   │   │   ├── ProductService.java       # Business logic
│   │   │   ├── ProductImageService.java  # Image handling service
│   │   │   └── ProductRepository.java    # Data access
│   │   └── storage/
│   │       └── S3StorageService.java     # S3 operations
│   └── resources/
│       ├── static/
│       │   └── index.html                 # Web interface
│       └── application.properties        # Configuration
mvn jib:builddocker compose up -dmvn testmvn verify- 
MinIO Connection Issues (Local Development) - Ensure MinIO is running: docker ps | grep minio
- Check MinIO logs: docker logs jfs-minio-local
- Verify MinIO is accessible: curl http://localhost:9000/minio/health/live
- Access MinIO console at http://localhost:9001
 
- Ensure MinIO is running: 
- 
AWS Credentials Not Found (Production) - Ensure AWS credentials are properly configured
- Check environment variables or AWS CLI configuration
 
- 
S3 Bucket Access Denied - Verify bucket name in configuration
- Check IAM permissions for S3 access
- For MinIO: ensure bucket exists and is public
 
- 
Database Connection Issues - Ensure PostgreSQL is running: docker ps | grep postgres
- Check database logs: docker logs jfs-postgres-local
- Verify database credentials in application.properties
 
- Ensure PostgreSQL is running: 
- 
Image Upload Fails - Check file size limits
- Verify image file format is supported
- Ensure S3/MinIO bucket exists and is accessible
- Check MinIO bucket policy: should be public for downloads
 
Check application logs for detailed error messages:
tail -f logs/application.log- Use IAM roles instead of access keys when possible
- Implement proper CORS configuration for production
- Add authentication and authorization as needed
- Consider using S3 pre-signed URLs for direct uploads
- Implement file type validation and size limits
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
This project is licensed under the MIT License.