A comprehensive RESTful API for blog management built with Spring Boot 3.x. Provides CRUD operations for blog posts, categories, and comments with proper validation, error handling, and documentation.
- ✅ RESTful endpoints for blog posts, categories, and comments
- ✅ JPA entities with proper relationships
- ✅ Request validation and comprehensive error handling
- ✅ Pagination and sorting for list endpoints
- ✅ H2 in-memory database for development
- ✅ PostgreSQL configuration for production
- ✅ OpenAPI/Swagger documentation with interactive UI
- ✅ Comprehensive logging with profile-specific configurations
- ✅ Unit and integration tests with high coverage
- ✅ Postman collection for API testing
- ✅ Performance testing with JMeter support
| Technology | Version | Purpose |
|---|---|---|
| Java | 17+ | Core programming language |
| Spring Boot | 3.2.3 | Application framework |
| Spring Data JPA | 3.2.3 | Database access layer |
| Hibernate ORM | 6.4.4 | Object-relational mapping |
| H2 Database | 2.2.224 | Development database |
| PostgreSQL | 15+ | Production database |
| OpenAPI/Swagger | 2.2.0 | API documentation |
| Maven | 3.9.6 | Build tool |
| JUnit 5 | 5.10.0 | Testing framework |
| Mockito | 5.6.0 | Mocking framework |
- Java 17 or higher
- Maven 3.6 or higher
- Git for version control
- PostgreSQL (for production deployment)
git clone <repository-url>
cd blogapiFor development, the application uses H2 in-memory database automatically.
For production with PostgreSQL, update application-prod.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/blogdb
spring.datasource.username=your-username
spring.datasource.password=your-passwordmvn spring-boot:runmvn clean package
java -jar target/blog-api-0.0.1-SNAPSHOT.jar- API Base URL: http://localhost:8080
- Swagger Documentation: http://localhost:8080/swagger-ui.html
- H2 Database Console: http://localhost:8080/h2-console
- JDBC URL:
jdbc:h2:mem:blogdb - Username:
sa - Password:
password
- JDBC URL:
http://localhost:8080/api
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/posts |
Get all posts (with pagination) |
| GET | /api/posts/{id} |
Get post by ID |
| POST | /api/posts |
Create new post |
| PUT | /api/posts/{id} |
Update post |
| DELETE | /api/posts/{id} |
Delete post |
| GET | /api/posts/category/{categoryId} |
Get posts by category |
| GET | /api/posts/author/{author} |
Get posts by author |
| GET | /api/posts/search |
Search posts by keyword |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/categories |
Get all categories |
| GET | /api/categories/{id} |
Get category by ID |
| POST | /api/categories |
Create new category |
| PUT | /api/categories/{id} |
Update category |
| DELETE | /api/categories/{id} |
Delete category |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/posts/{postId}/comments |
Get comments for post |
| POST | /api/posts/{postId}/comments |
Add comment to post |
| PUT | /api/comments/{id} |
Update comment |
| DELETE | /api/comments/{id} |
Delete comment |
curl -X POST http://localhost:8080/api/posts \
-H "Content-Type: application/json" \
-d '{
"title": "Getting Started with Spring Boot",
"content": "Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can \"just run\".",
"author": "John Doe",
"categoryId": 1
}'curl "http://localhost:8080/api/posts?page=0&size=10&sort=createdAt,desc"curl -X POST http://localhost:8080/api/categories \
-H "Content-Type: application/json" \
-d '{
"name": "Technology",
"description": "Technology related posts"
}'curl -X POST http://localhost:8080/api/posts/1/comments \
-H "Content-Type: application/json" \
-d '{
"author": "Jane Smith",
"content": "Great article! Very helpful for beginners."
}'Category (1) ←→ (N) Post (1) ←→ (N) Comment
CREATE TABLE categories (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
description VARCHAR(255)
);CREATE TABLE posts (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title VARCHAR(200) NOT NULL,
content TEXT,
author VARCHAR(100) NOT NULL,
category_id BIGINT NOT NULL,
created_at TIMESTAMP(6),
updated_at TIMESTAMP(6),
FOREIGN KEY (category_id) REFERENCES categories(id)
);CREATE TABLE comments (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
author VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
post_id BIGINT NOT NULL,
created_at TIMESTAMP(6),
FOREIGN KEY (post_id) REFERENCES posts(id)
);# Run all unit tests
mvn test
# Run specific test class
mvn test -Dtest=CategoryServiceTest
# Run tests with coverage
mvn test jacoco:report# Run all integration tests
mvn verify
# Run integration tests only
mvn test -Dtest=**/*IntegrationTest# Run JMeter tests
jmeter -n -t blog-api-load-test.jmx -l results.jtl
# Generate HTML report
jmeter -g results.jtl -o performance-report/- Service Layer: 95%+ code coverage
- Controller Layer: 90%+ code coverage
- Repository Layer: 80%+ code coverage
- Overall Coverage: 85%+ minimum
# H2 Database
spring.datasource.url=jdbc:h2:mem:blogdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
# JPA
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true# PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/blogdb
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.username=${DB_USERNAME:your-username}
spring.datasource.password=${DB_PASSWORD:your-password}
# JPA
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=falseThe application uses Logback with profile-specific configurations:
- Development: DEBUG level logging with SQL queries
- Production: INFO level logging with file rotation
- Test: WARN level logging for test execution
src/
├── main/
│ ├── java/com/blogapi/
│ │ ├── BlogapiApplication.java # Main application entry point
│ │ ├── controller/
│ │ │ ├── CategoryController.java # Category REST endpoints
│ │ │ ├── CommentController.java # Comment REST endpoints
│ │ │ └── PostController.java # Post REST endpoints
│ │ ├── service/
│ │ │ ├── CategoryService.java # Category business logic
│ │ │ ├── CommentService.java # Comment business logic
│ │ │ └── PostService.java # Post business logic
│ │ ├── repository/
│ │ │ ├── CategoryRepository.java # Category data access
│ │ │ ├── CommentRepository.java # Comment data access
│ │ │ └── PostRepository.java # Post data access
│ │ ├── model/
│ │ │ ├── entity/
│ │ │ │ ├── Category.java # Category entity
│ │ │ │ ├── Comment.java # Comment entity
│ │ │ │ └── Post.java # Post entity
│ │ │ ├── dto/
│ │ │ │ ├── ApiResponse.java # Generic API response
│ │ │ │ ├── PostRequest.java # Post creation DTO
│ │ │ │ └── PostResponse.java # Post response DTO
│ │ │ └── exception/
│ │ │ ├── GlobalExceptionHandler.java # Error handling
│ │ │ └── ResourceNotFoundException.java # Custom exception
│ └── resources/
│ ├── application.properties # Main configuration
│ ├── application-dev.properties # Development profile
│ ├── application-prod.properties # Production profile
│ ├── application-test.properties # Test profile
│ └── logback-spring.xml # Logging configuration
└── test/
└── java/com/blogapi/service/
├── CategoryServiceTest.java # Category tests
├── CommentServiceTest.java # Comment tests
└── PostServiceTest.java # Post tests
Access interactive API documentation at: http://localhost:8080/swagger-ui.html
Download OpenAPI JSON at: http://localhost:8080/v3/api-docs
Import the provided Postman collection for easy API testing:
- Download
Blog-API.postman_collection.json - Open Postman
- Click "Import" → "Upload Files"
- Select the collection file
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Java naming conventions
- Use meaningful variable names
- Add comments for complex logic
- Ensure all tests pass before submitting
# Check if PostgreSQL is running
pg_isready -h localhost -p 5432
# Test connection
psql -h localhost -p 5432 -U your-username -d blogdb# Find process using port 8080
netstat -tulpn | grep :8080
# Kill process
kill -9 <PID># Clean and rebuild
mvn clean install
# Skip tests (for development only)
mvn clean install -DskipTests| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2024-04-15 | Initial release with full CRUD operations |
| 1.1.0 | TBD | Authentication and authorization |
| 1.2.0 | TBD | File upload functionality |
Built with ❤️ using Spring Boot 3.x