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 productsGET /api/v1/products/{id}- Get product by IDPOST /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 productDELETE /api/v1/products/{id}- Delete product
POST /api/v1/products/{id}/image- Upload product imageGET /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.