A modern Spring Boot application to manage a family tree using Neo4j, leveraging Java Records for DTOs and following best development practices.
- Features
- Prerequisites
- Installation
- Configuration
- Running the Application
- API Endpoints
- Testing
- Docker
- Architecture
- Best Practices
- Useful Cypher Queries
- Contributing
- License
- Authors
- Acknowledgements
- β Java 17 with Records for DTOs
- β Spring Boot 3.2 with layered architecture
- β Neo4j as a graph database
- β OpenAPI/Swagger for documentation
- β Bean Validation with Jakarta Validation
- β Centralized exception handling
- β Unit and integration tests
- β Docker multi-stage build
- β Docker Compose for orchestration
- β Structured logging with SLF4J
- β Typed enums for Gender and Relationships
- β Mappers for Entity β DTO conversion
- β Service interface + implementation
- Java 17 or higher
- Maven 3.9+
- Docker & Docker Compose (recommended)
- Neo4j 5.15 (for local installation)
- Clone the repository
git clone https://github.com/Juste120/family-tree.git cd family-tree - Copy the environment file
cp .env.example .env
- Modify variables if necessary
# Edit .env with your settings nano .env
dev: Development with detailed logsprod: Production with limited logstest: Testing with a dedicated Neo4j database
SPRING_PROFILE=dev
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=password
SERVER_PORT=8080# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose downThe application will be accessible at:
- API:
http://localhost:8080 - Swagger UI:
http://localhost:8080/swagger-ui.html - Neo4j Browser:
http://localhost:7474
# Start Neo4j with Docker
docker run -d \
--name neo4j \
-p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/password \
neo4j:5.15.0
# Run the application
mvn spring-boot:run -Dspring-boot.run.profiles=dev# Compile
mvn clean package -DskipTests
# Run
java -jar target/family-tree.jar# List all persons
GET /api/v1/persons
# Get a person by ID
GET /api/v1/persons/{id}
# Create a person
POST /api/v1/persons
# Update a person
PUT /api/v1/persons/{id}
# Delete a person
DELETE /api/v1/persons/{id}# Add a parent-child relationship
POST /api/v1/persons/{parentId}/children/{childId}
# Add a marriage relationship
POST /api/v1/persons/{person1Id}/spouse/{person2Id}
# Remove relationships
DELETE /api/v1/persons/{parentId}/children/{childId}
DELETE /api/v1/persons/{person1Id}/spouse/{person2Id}# Descendants
GET /api/v1/persons/{id}/descendants
# Ancestors
GET /api/v1/persons/{id}/ancestors
# Siblings
GET /api/v1/persons/{id}/siblings
# Grandchildren
GET /api/v1/persons/{id}/grandchildren
# Grandparents
GET /api/v1/persons/{id}/grandparents
# Count descendants
GET /api/v1/persons/{id}/descendants/count
# Path between two persons
GET /api/v1/persons/path?from={id1}&to={id2}# Search by name
GET /api/v1/persons/search?lastName=Smith
# Statistics
GET /api/v1/persons/stats/count
GET /api/v1/persons/stats/alivecurl -X POST http://localhost:8080/api/v1/persons \
-H "Content-Type: application/json" \
-d '{
"firstName": "Alice",
"lastName": "Martin",
"birthDate": "1990-05-15",
"gender": "F"
}'# Parent (ID 1) β Child (ID 2)
curl -X POST http://localhost:8080/api/v1/persons/1/children/2mvn testmvn test -Dtest=PersonServiceImplTestmvn clean verify
# Report in target/site/jacoco/index.html# Production
docker build -t family-tree:latest .
# Development
docker build -f Dockerfile.dev -t family-tree:dev .docker run -d \
-p 8080:8080 \
-e SPRING_PROFILE=prod \
-e NEO4J_URI=bolt://neo4j:7687 \
--name family-tree-app \
family-tree:latest# Start
docker-compose up -d
# Logs
docker-compose logs -f family-tree-app
# Rebuild
docker-compose up -d --build
# Stop and delete
docker-compose down -vsrc/main/java/com/example/familytree/
βββ FamilyTreeApplication.java
βββ config/ # Spring Configuration
β βββ Neo4jConfig.java
β βββ OpenApiConfig.java
β βββ DataInitializer.java
βββ model/ # Neo4j Entities
β βββ Person.java
βββ dto/ # DTOs (Java Records)
β βββ PersonDTO.java
β βββ PersonSummaryDTO.java
β βββ PersonCreateDTO.java
β βββ PersonUpdateDTO.java
β βββ ...
βββ enums/ # Enumerations
β βββ Gender.java
β βββ RelationType.java
βββ mapper/ # Entity β DTO Conversion
β βββ PersonMapper.java
βββ repository/ # Neo4j Data Access
β βββ PersonRepository.java
βββ service/ # Business Logic
β βββ PersonService.java
β βββ impl/
β βββ PersonServiceImpl.java
βββ controller/ # REST API
β βββ PersonController.java
βββ exception/ # Error Handling
βββ GlobalExceptionHandler.java
βββ PersonNotFoundException.java
βββ ...
- Layered Architecture
- Clear separation of concerns
Controller β Service β Repository- DTOs to decouple the API from the model
- Java Records for DTOs
- Immutable by default
- Concise code (-47% lines)
- Thread-safe
- Validation
- Bean Validation on DTOs
- Business validation in the service layer
- Clear error messages
- Custom Exceptions
GlobalExceptionHandlerfor centralization- Standardized JSON responses
- Structured logs
- Testing
- Unit tests (Mockito)
- Integration tests (MockMvc)
- Coverage > 80%
- Docker
- Optimized multi-stage build
- Lightweight Alpine image
- Non-root user for security
- Health checks
- Documentation
- Integrated OpenAPI/Swagger
- JavaDoc on public methods
- Comprehensive README
- Security
- Input validation
- Non-root user in Docker
- No sensitive data in logs
// Visualize the whole family
MATCH path = (p:Person)-[*]-(p2:Person)
RETURN path
LIMIT 100
// Find the person with the most descendants
MATCH (p:Person)-[:PARENT_OF*]->(d:Person)
WITH p, count(d) as descendants
RETURN p.firstName, p.lastName, descendants
ORDER BY descendants DESC
LIMIT 1
// Calculate the tree depth
MATCH path = (root:Person)-[:PARENT_OF*]->(leaf:Person)
WHERE NOT (leaf)-[:PARENT_OF]->()
RETURN max(length(path)) as maxDepth- Fork the project
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Juste Pakou - Initial work - Juste120 - [email protected]
- Spring Boot Team
- Neo4j Community
- OpenAPI Initiative
Made with β€οΈ and β by the Family Tree Team
