A CRUD-based contact management system with profile image upload capabilities using AWS S3 for secure image storage. Organizes contact details (name, email, phone, address) in a centralized, paginated interface.
- CRUD Operations: Full Create, Read, Update, Delete functionality.
- Secure Image Upload: AWS S3 integration with private bucket access and presigned URLs.
- Pagination: User-friendly interface with multi-page navigation.
- Detailed Contact Storage: Stores name, email, phone, address, job title, and status.
Category | Technologies/Tools |
---|---|
Backend | Spring Boot 3.3.5, JPA, Lombok |
Frontend | React |
Database | PostgreSQL |
Cloud Storage | AWS S3 SDK 2.20.26, S3 Transfer Manager |
Testing | Selenium 4.20.0, JUnit 5, WebDriverManager 5.7.0 |
Infra | AWS (Hosting), GitHub (Version Control) |
- JDK 17+, Maven, PostgreSQL, Node.js/npm.
- AWS Account with S3 bucket configured.
- Frontend Repo: React-CRUDContactList.
-
Clone & Configure Backend:
git clone https://github.com/KevinLlano/Java_CRUDContactList.git cd contactlistapi
-
Environment Variables Setup: Create
.env
file or set system environment variables:export AWS_ACCESS_KEY_ID=your-aws-access-key export AWS_SECRET_ACCESS_KEY=your-aws-secret-key
-
Configure Application: Update
application.yml
(create from template as it's gitignored for security):spring: datasource: url: jdbc:postgresql://localhost:5432/contactlistdb username: postgres password: yourpassword aws: s3: bucket-name: your-contact-images-bucket region: us-east-1 access-key: ${AWS_ACCESS_KEY_ID:} secret-key: ${AWS_SECRET_ACCESS_KEY:}
Run:
mvn spring-boot:run # Starts backend at http://localhost:8080
-
Set Up Frontend:
cd contactlistweb npm install && npm start # Starts frontend at http://localhost:3000
-
Database Setup:
CREATE DATABASE contactlistdb; # Run in PostgreSQL
Component | Location | Purpose |
---|---|---|
AwsConfig | src/main/java/Kevin/backend/config/AwsConfig.java |
S3Client bean configuration |
S3Service | src/main/java/Kevin/backend/service/S3Service.java |
Image upload/download operations |
Properties | src/main/resources/application.yml |
AWS credentials and bucket config |
- Private ACL: All uploaded images are private by default
- Environment Variables: AWS credentials externalized for security
- Unique File Paths: Images organized by contact ID with UUID filenames
- Presigned URLs: Temporary secure access to private images
- GitIgnore Protection: application.yml excluded from version control
Method | Purpose |
---|---|
uploadImage() |
Securely upload contact images to S3 |
generatePresignedUrl() |
Create temporary access URLs |
deleteImage() |
Remove images from S3 bucket |
- Framework: JUnit 5 + Selenium WebDriver.
- Browser Automation:
WebDriverManager
auto-configures ChromeDriver.- Explicit waits (20-second timeout) for dynamic elements.
- Test Flow:
- Navigate to
http://localhost:3000/contacts
. - Add a contact via form submission.
- Validate contact appears in the list using XPath
//div[contains(., 'John Doe')]
.
- Navigate to
Method | Purpose |
---|---|
setUp() |
Initializes WebDriver and waits. |
testAddContact() |
Tests contact creation and validation. |
tearDown() |
Closes the browser post-test. |
Issue | Symptom | Solution |
---|---|---|
Selenium Version Mismatch | CDP warnings for Chrome 133. | Added selenium-devtools-v133:4.20.0 . |
Element Locator Mismatch | TimeoutException with XPath text() . |
Updated XPath to contains(., 'text') . |
ChromeDriver Setup | Manual driver version conflicts. | Integrated WebDriverManager automation. |




- CDP Warnings: Non-blocking; resolved by aligning Selenium dependencies.
- Best Practices: Use explicit waits and
WebDriverManager
for stable tests. - Image Functionality: Ensure the CORS connection works, and that images upload correctly after a page refresh.