|
1 | 1 | # Java App Sample |
2 | 2 |
|
3 | | -## Prerequisites |
| 3 | +A comprehensive Spring Boot REST API application for a social media platform with full CRUD operations for posts, comments, and likes. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a production-ready Spring Boot application built with the following specifications: |
| 8 | + |
| 9 | +- **Package Name**: `com.contoso.socialapp` |
| 10 | +- **Artifact ID**: `socialapp` |
| 11 | +- **Group ID**: `com.contoso` |
| 12 | +- **Package Type**: `jar` |
| 13 | +- **Java Version**: OpenJDK 21 |
| 14 | +- **Build Tool**: Gradle |
| 15 | +- **Database**: SQLite (embedded) |
| 16 | +- **Port**: 8080 |
| 17 | + |
| 18 | +### Project Dependencies |
| 19 | + |
| 20 | +- **Spring Boot 3.2.5**: Core framework |
| 21 | +- **Spring Web**: RESTful API endpoints |
| 22 | +- **Spring Data JPA**: Database operations |
| 23 | +- **Spring Boot Actuator**: Application monitoring |
| 24 | +- **Spring Boot Validation**: Input validation |
| 25 | +- **SQLite**: Embedded database |
| 26 | +- **Hibernate Community Dialects**: SQLite support |
| 27 | +- **Springdoc OpenAPI**: API documentation (Swagger UI) |
| 28 | +- **Lombok**: Boilerplate code reduction |
| 29 | + |
| 30 | +### Project Structure |
| 31 | + |
| 32 | +```text |
| 33 | +src/ |
| 34 | +├── main/ |
| 35 | +│ ├── java/ |
| 36 | +│ │ └── com/ |
| 37 | +│ │ └── contoso/ |
| 38 | +│ │ └── socialapp/ |
| 39 | +│ │ ├── SocialAppApplication.java # Main application class |
| 40 | +│ │ ├── config/ |
| 41 | +│ │ │ ├── WebConfig.java # CORS configuration |
| 42 | +│ │ │ └── OpenApiConfig.java # Swagger/OpenAPI config |
| 43 | +│ │ ├── controller/ |
| 44 | +│ │ │ ├── HealthController.java # Health endpoints |
| 45 | +│ │ │ ├── PostController.java # Post management |
| 46 | +│ │ │ └── CommentController.java # Comment & like management |
| 47 | +│ │ ├── model/ |
| 48 | +│ │ │ ├── Post.java # Post entity |
| 49 | +│ │ │ ├── Comment.java # Comment entity |
| 50 | +│ │ │ ├── Like.java # Like entity |
| 51 | +│ │ │ └── dto/ # Data Transfer Objects |
| 52 | +│ │ ├── repository/ |
| 53 | +│ │ │ ├── PostRepository.java # Post data access |
| 54 | +│ │ │ ├── CommentRepository.java # Comment data access |
| 55 | +│ │ │ └── LikeRepository.java # Like data access |
| 56 | +│ │ └── service/ |
| 57 | +│ │ ├── PostService.java # Post business logic |
| 58 | +│ │ └── CommentService.java # Comment business logic |
| 59 | +│ └── resources/ |
| 60 | +│ ├── application.properties # Application configuration |
| 61 | +│ └── data.sql # Sample data (optional) |
| 62 | +└── test/ |
| 63 | + └── java/ |
| 64 | + └── com/ |
| 65 | + └── contoso/ |
| 66 | + └── socialapp/ |
| 67 | + └── SocialAppApplicationTests.java # Integration tests |
| 68 | +``` |
| 69 | + |
| 70 | +## Features |
| 71 | + |
| 72 | +- ✅ Complete RESTful API for social media operations |
| 73 | +- ✅ Post management (Create, Read, Update, Delete) |
| 74 | +- ✅ Comment system with full CRUD operations |
| 75 | +- ✅ Like/Unlike functionality |
| 76 | +- ✅ SQLite database with JPA/Hibernate |
| 77 | +- ✅ OpenAPI/Swagger documentation |
| 78 | +- ✅ CORS enabled for localhost and GitHub Codespaces |
| 79 | +- ✅ Dynamic server URL configuration |
| 80 | +- ✅ Health check endpoints |
| 81 | +- ✅ Spring Boot Actuator integration |
| 82 | +- ✅ Comprehensive error handling |
| 83 | +- ✅ Input validation with Bean Validation |
| 84 | + |
| 85 | +## Quick Start |
| 86 | + |
| 87 | +### Prerequisites |
4 | 88 |
|
5 | 89 | Refer to the [README](../../README.md) doc for preparation. |
6 | 90 |
|
7 | | -## Getting Started |
| 91 | +### 1. Environment Setup |
| 92 | + |
| 93 | +First, set the environment variable of `$REPOSITORY_ROOT`. |
| 94 | + |
| 95 | +```bash |
| 96 | +# bash/zsh |
| 97 | +REPOSITORY_ROOT=$(git rev-parse --show-toplevel) |
| 98 | +``` |
| 99 | + |
| 100 | +```powershell |
| 101 | +# PowerShell |
| 102 | +$REPOSITORY_ROOT = git rev-parse --show-toplevel |
| 103 | +``` |
| 104 | + |
| 105 | +Then, navigate to the java directory. |
| 106 | + |
| 107 | +```bash |
| 108 | +cd $REPOSITORY_ROOT/complete/java |
| 109 | +``` |
| 110 | + |
| 111 | +### 2. Build the Application |
| 112 | + |
| 113 | +```bash |
| 114 | +# Make gradlew executable (if needed) |
| 115 | +chmod +x ./gradlew |
| 116 | + |
| 117 | +# Build the project |
| 118 | +./gradlew build |
| 119 | +``` |
| 120 | + |
| 121 | +### 3. Run the Application |
| 122 | + |
| 123 | +```bash |
| 124 | +# Start the application using Gradle |
| 125 | +./gradlew bootRun |
| 126 | + |
| 127 | +# Alternative: Run the JAR file directly |
| 128 | +# java -jar build/libs/socialapp-0.0.1-SNAPSHOT.jar |
| 129 | +``` |
| 130 | + |
| 131 | +### 4. Verify Application is Running |
| 132 | + |
| 133 | +```bash |
| 134 | +# Check health endpoint |
| 135 | +curl http://localhost:8080/api/health |
| 136 | + |
| 137 | +# Expected response: {"status":"healthy"} |
| 138 | +``` |
| 139 | + |
| 140 | +### 5. Access API Documentation |
| 141 | + |
| 142 | +Open your browser and navigate to: |
| 143 | + |
| 144 | +- **Swagger UI**: [http://localhost:8080/swagger-ui.html](http://localhost:8080/swagger-ui.html) |
| 145 | +- **OpenAPI JSON**: [http://localhost:8080/v3/api-docs](http://localhost:8080/v3/api-docs) |
| 146 | + |
| 147 | +## API Endpoints |
| 148 | + |
| 149 | +### Health & Welcome |
| 150 | + |
| 151 | +- `GET /api/health` - Custom health check endpoint |
| 152 | +- `GET /api/welcome` - Welcome message endpoint |
| 153 | + |
| 154 | +### Posts Management |
| 155 | + |
| 156 | +- `GET /api/posts` - Get all posts |
| 157 | +- `GET /api/posts/{id}` - Get specific post by ID |
| 158 | +- `POST /api/posts` - Create a new post |
| 159 | +- `PATCH /api/posts/{id}` - Update an existing post |
| 160 | +- `DELETE /api/posts/{id}` - Delete a post |
| 161 | + |
| 162 | +### Comments Management |
| 163 | + |
| 164 | +- `GET /api/posts/{postId}/comments` - Get all comments for a post |
| 165 | +- `GET /api/posts/{postId}/comments/{commentId}` - Get specific comment |
| 166 | +- `POST /api/posts/{postId}/comments` - Add a comment to a post |
| 167 | +- `PATCH /api/posts/{postId}/comments/{commentId}` - Update a comment |
| 168 | +- `DELETE /api/posts/{postId}/comments/{commentId}` - Delete a comment |
| 169 | + |
| 170 | +### Likes Management |
| 171 | + |
| 172 | +- `POST /api/posts/{postId}/like` - Like a post |
| 173 | +- `DELETE /api/posts/{postId}/like` - Unlike a post |
| 174 | + |
| 175 | +### Spring Boot Actuator |
| 176 | + |
| 177 | +- `GET /actuator/health` - Spring Boot health indicator |
| 178 | +- `GET /actuator/info` - Application information |
| 179 | + |
| 180 | +## Testing the API |
| 181 | + |
| 182 | +### Using cURL Examples |
| 183 | + |
| 184 | +#### Create a Post |
| 185 | + |
| 186 | +```bash |
| 187 | +curl -X POST http://localhost:8080/api/posts \ |
| 188 | + -H "Content-Type: application/json" \ |
| 189 | + -d '{ |
| 190 | + "title": "My First Post", |
| 191 | + "content": "This is the content of my first post!", |
| 192 | + "authorName": "John Doe" |
| 193 | + }' |
| 194 | +``` |
| 195 | + |
| 196 | +#### Get All Posts |
| 197 | + |
| 198 | +```bash |
| 199 | +curl http://localhost:8080/api/posts |
| 200 | +``` |
| 201 | + |
| 202 | +#### Add a Comment |
| 203 | + |
| 204 | +```bash |
| 205 | +curl -X POST http://localhost:8080/api/posts/1/comments \ |
| 206 | + -H "Content-Type: application/json" \ |
| 207 | + -d '{ |
| 208 | + "content": "Great post!", |
| 209 | + "authorName": "Jane Smith" |
| 210 | + }' |
| 211 | +``` |
| 212 | + |
| 213 | +#### Like a Post |
| 214 | + |
| 215 | +```bash |
| 216 | +curl -X POST http://localhost:8080/api/posts/1/like \ |
| 217 | + -H "Content-Type: application/json" \ |
| 218 | + -d '{ |
| 219 | + "userName": "john_doe" |
| 220 | + }' |
| 221 | +``` |
| 222 | + |
| 223 | +### Using Swagger UI |
| 224 | + |
| 225 | +1. Open [http://localhost:8080/swagger-ui.html](http://localhost:8080/swagger-ui.html) |
| 226 | +2. Explore available endpoints |
| 227 | +3. Click "Try it out" on any endpoint |
| 228 | +4. Fill in parameters and click "Execute" |
| 229 | + |
| 230 | +## Development |
| 231 | + |
| 232 | +### Running Tests |
| 233 | + |
| 234 | +```bash |
| 235 | +# Run all tests |
| 236 | +./gradlew test |
| 237 | + |
| 238 | +# Run with coverage report |
| 239 | +./gradlew test jacocoTestReport |
| 240 | + |
| 241 | +# Run specific test class |
| 242 | +./gradlew test --tests "SocialAppApplicationTests" |
| 243 | +``` |
| 244 | + |
| 245 | +### Database |
| 246 | + |
| 247 | +The application uses SQLite as an embedded database: |
| 248 | + |
| 249 | +- **Database file**: `sns_api.db` (created automatically) |
| 250 | +- **Location**: Project root directory |
| 251 | +- **Schema**: Auto-generated by Hibernate |
| 252 | +- **Sample data**: Loaded from `data.sql` (if present) |
| 253 | + |
| 254 | +To reset the database, simply delete the `sns_api.db` file and restart the application. |
| 255 | + |
| 256 | +## Configuration |
| 257 | + |
| 258 | +### Application Properties |
| 259 | + |
| 260 | +Key configuration settings in `application.properties`: |
| 261 | + |
| 262 | +```properties |
| 263 | +# Application Settings |
| 264 | +spring.application.name=socialapp |
| 265 | +server.port=8080 |
| 266 | + |
| 267 | +# Database Configuration |
| 268 | +spring.datasource.url=jdbc:sqlite:sns_api.db |
| 269 | +spring.jpa.hibernate.ddl-auto=update |
| 270 | + |
| 271 | +# OpenAPI/Swagger Configuration |
| 272 | +springdoc.swagger-ui.path=/swagger-ui.html |
| 273 | +springdoc.swagger-ui.operationsSorter=method |
| 274 | +``` |
| 275 | + |
| 276 | +### CORS Configuration |
| 277 | + |
| 278 | +The application supports both localhost and GitHub Codespaces: |
| 279 | + |
| 280 | +- **Localhost**: `http://localhost:8080` |
| 281 | +- **GitHub Codespaces**: Auto-detected and configured dynamically |
| 282 | + |
| 283 | +### Environment Detection |
| 284 | + |
| 285 | +The application automatically detects the runtime environment: |
| 286 | + |
| 287 | +- **Local Development**: Uses `http://localhost:8080` |
| 288 | +- **GitHub Codespaces**: Uses `https://{codespace-name}-8080.{domain}` |
| 289 | + |
| 290 | +## Deployment |
| 291 | + |
| 292 | +### Building for Production |
| 293 | + |
| 294 | +```bash |
| 295 | +# Create production JAR |
| 296 | +./gradlew clean build |
| 297 | + |
| 298 | +# JAR location |
| 299 | +ls -la build/libs/socialapp-0.0.1-SNAPSHOT.jar |
| 300 | +``` |
| 301 | + |
| 302 | +### Running in Production |
| 303 | + |
| 304 | +```bash |
| 305 | +# Run with production profile |
| 306 | +java -jar build/libs/socialapp-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod |
| 307 | + |
| 308 | +# Or with custom port |
| 309 | +java -jar build/libs/socialapp-0.0.1-SNAPSHOT.jar --server.port=8081 |
| 310 | +``` |
| 311 | + |
| 312 | +## Troubleshooting |
| 313 | + |
| 314 | +### Common Issues |
| 315 | + |
| 316 | +#### Port Already in Use |
| 317 | + |
| 318 | +```bash |
| 319 | +# Find process using port 8080 |
| 320 | +lsof -i :8080 |
| 321 | + |
| 322 | +# Kill the process (replace PID) |
| 323 | +kill -9 <PID> |
| 324 | + |
| 325 | +# Or use a different port |
| 326 | +./gradlew bootRun --args='--server.port=8081' |
| 327 | +``` |
| 328 | + |
| 329 | +#### Build Failures |
| 330 | + |
| 331 | +```bash |
| 332 | +# Clean and rebuild |
| 333 | +./gradlew clean build |
| 334 | + |
| 335 | +# Update Gradle wrapper |
| 336 | +./gradlew wrapper --gradle-version=8.5 |
| 337 | +``` |
| 338 | + |
| 339 | +#### Database Issues |
| 340 | + |
| 341 | +```bash |
| 342 | +# Reset database |
| 343 | +rm sns_api.db |
| 344 | +./gradlew bootRun |
| 345 | +``` |
| 346 | + |
| 347 | +### Logs and Monitoring |
| 348 | + |
| 349 | +- **Application logs**: Console output when running `./gradlew bootRun` |
| 350 | +- **Health check**: `GET /actuator/health` |
| 351 | +- **Application info**: `GET /actuator/info` |
| 352 | + |
| 353 | +## Security Considerations |
| 354 | + |
| 355 | +⚠️ **Development Configuration**: The current setup is optimized for development with: |
| 356 | + |
| 357 | +- CORS enabled for all origins |
| 358 | +- SQLite database (not suitable for production scale) |
| 359 | +- No authentication/authorization |
| 360 | + |
| 361 | +For production deployment, consider: |
8 | 362 |
|
9 | | -### Run Spring Boot Backend |
| 363 | +- Restricting CORS to specific domains |
| 364 | +- Using PostgreSQL/MySQL instead of SQLite |
| 365 | +- Implementing Spring Security for authentication |
| 366 | +- Adding rate limiting and input sanitization |
| 367 | +- Using HTTPS/TLS encryption |
0 commit comments