Project E: Contact Form
Scenario
A company wants to collect contact details from visitors to its website. When someone fills out the contact form, their information must be saved in a PostgreSQL database and an email must be sent.
What You Need to Create
A Spring Boot REST API with:
- A public contact form - anyone can submit their contact details
- A protected admin panel - to view and manage received contacts
- An email system - automatic notifications
The Flow
Form Preview (Frontend)
Here is what the form should look like on the webpage:
┌─────────────────────────────────────────────────────────┐
│ CONTACT US │
├─────────────────────────────────────────────────────────┤
│ │
│ Full Name * Company │
│ ┌─────────────────────────┐ ┌─────────────────────┐│
│ │ Your name │ │ Your company name ││
│ └─────────────────────────┘ └─────────────────────┘│
│ │
│ Email * Phone │
│ ┌─────────────────────────┐ ┌─────────────────────┐│
│ │ your@company.com │ │ Your phone number ││
│ └─────────────────────────┘ └─────────────────────┘│
│ │
│ Request Type * │
│ ┌─────────────────────────────────────────────────┬──┐│
│ │ Select request type │ v││
│ ├─────────────────────────────────────────────────┴──┤│
│ │ > Select request type ││
│ │ Information request ││
│ │ Quote request ││
│ │ Technical support ││
│ │ Partnership ││
│ │ Other ││
│ └────────────────────────────────────────────────────┘│
│ │
│ Message * │
│ ┌────────────────────────────────────────────────────┐│
│ │ Describe your request, your budget, ││
│ │ and your deadlines... ││
│ │ ││
│ │ ││
│ └────────────────────────────────────────────────────┘│
│ │
│ ┌─────────────────────┐ │
│ │ SEND │ │
│ └─────────────────────┘ │
│ │
│ * Required fields │
└─────────────────────────────────────────────────────────┘
Form Fields:
| Field | HTML Type | Validation |
|---|---|---|
| Full Name | <input type="text"> | Required |
| Company | <input type="text"> | Optional |
<input type="email"> | Required, email format | |
| Phone | <input type="tel"> | Optional |
| Request Type | <select> | Required |
| Message | <textarea> | Required, min 10 characters |
Options for "Request Type" field:
| Value | Display |
|---|---|
INFO | Information request |
QUOTE | Quote request |
SUPPORT | Technical support |
PARTNERSHIP | Partnership |
OTHER | Other |
Endpoints to Create
Public Endpoint (no authentication)
| Method | URL | Description |
|---|---|---|
| POST | /api/contact | Submit the form |
Form Data:
- fullName (required)
- company (optional)
- email (required)
- phone (optional)
- requestType (required) - selection list
- message (required)
Admin Endpoints (with JWT)
| Method | URL | Description |
|---|---|---|
| GET | /api/admin/leads | List of contacts |
| GET | /api/admin/leads/\{id\} | Contact details |
| PUT | /api/admin/leads/\{id\}/status | Change status |
| DELETE | /api/admin/leads/\{id\} | Delete |
Class Diagram
Here is a proposed structure. You can modify, add, or simplify as needed.
This diagram is a suggestion. You are free to:
- Add classes (e.g.,
LeadNotefor internal notes) - Add fields (e.g.,
company,source) - Modify relationships
- Simplify if you find it too complex
The important thing is that your solution works and is well-structured.
Database
Create these tables in PostgreSQL:
Table leads
- id (primary key)
- full_name
- company
- email (unique)
- phone
- request_type (INFO, QUOTE, SUPPORT, PARTNERSHIP, OTHER)
- message
- status (NEW, CONTACTED, CONVERTED, LOST)
- created_at
Table users (for admins)
- id
- password
- role
Emails to Send
-
When someone submits the form:
- Email to admin: "New contact received"
- Email to visitor: "Thank you, we have received your message"
-
Use
@Asyncto avoid blocking the request
Configuration
# application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/contactdb
username: postgres
password: postgres
mail:
host: localhost
port: 1025 # MailHog for testing
To test emails locally:
docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog
View emails at http://localhost:8025
Tests to Write
- POST
/api/contactwith valid data → returns 200 - POST
/api/contactwith invalid email → returns 400 - GET
/api/admin/leadswithout token → returns 401 - GET
/api/admin/leadswith token → returns the list
Evaluation
| Criteria | Points |
|---|---|
| Endpoint POST /api/contact works | 20 |
| Data saved in PostgreSQL | 20 |
| Emails sent | 15 |
| Admin endpoints protected by JWT | 20 |
| Tests | 15 |
| Clean code | 10 |
| Total | 100 |
Getting Started
-
Create the project on start.spring.io with:
- Spring Web
- Spring Data JPA
- Spring Security
- Spring Mail
- Validation
- PostgreSQL Driver
- Lombok
-
Create the
Leadentity -
Create the
LeadRepository -
Create the
ContactControllerwith POST/api/contact -
Test with curl or Postman
Deliverables
- Code on GitHub
- README with instructions
- Postman collection for testing